From 2bca90a1ce579ed19cfa604f7ea0af778f5450cd Mon Sep 17 00:00:00 2001 From: Romain Beauxis Date: Mon, 21 Oct 2024 10:25:20 -0500 Subject: [PATCH] Added packed big array API (#68) --- CHANGES | 6 +++++ dune-project | 2 +- ffmpeg-av.opam | 2 +- ffmpeg-avcodec.opam | 2 +- ffmpeg-avdevice.opam | 2 +- ffmpeg-avfilter.opam | 2 +- ffmpeg-avutil.opam | 2 +- ffmpeg-swresample.opam | 2 +- ffmpeg-swscale.opam | 2 +- ffmpeg.opam | 2 +- swscale/swscale.ml | 9 ++++++- swscale/swscale.mli | 12 +++++++-- swscale/swscale_stubs.c | 59 ++++++++++++++++++++++++++++++++++++++++- 13 files changed, 91 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 99b6eb84..93500010 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +1.2.1 (unreleased) +====== +* Fixed plane size when allocating big array planes in `swscale`. +* Added packed big array API to `swscale` where all planes are alloacted in + on contiguous memory region. + 1.2.0 (2024-09-24) ===== * Removed unused `Av.write_audio_frame`/`Av.write_video_frame`. diff --git a/dune-project b/dune-project index 4755b8ac..70fdb4ef 100644 --- a/dune-project +++ b/dune-project @@ -1,7 +1,7 @@ (lang dune 3.6) (name ffmpeg) -(version 1.2.0) +(version 1.2.1) (source (github savonet/ocaml-ffmpeg)) (license LGPL-2.1-only) (authors "The Savonet Team ") diff --git a/ffmpeg-av.opam b/ffmpeg-av.opam index b3da502c..034183d2 100644 --- a/ffmpeg-av.opam +++ b/ffmpeg-av.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg libraries -- top-level helpers" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg-avcodec.opam b/ffmpeg-avcodec.opam index 05718eca..23319828 100644 --- a/ffmpeg-avcodec.opam +++ b/ffmpeg-avcodec.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg avcodec library" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg-avdevice.opam b/ffmpeg-avdevice.opam index e9d72ea3..8bb2f2b9 100644 --- a/ffmpeg-avdevice.opam +++ b/ffmpeg-avdevice.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg avdevice library" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg-avfilter.opam b/ffmpeg-avfilter.opam index 00ae9b9c..97191394 100644 --- a/ffmpeg-avfilter.opam +++ b/ffmpeg-avfilter.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg avfilter library" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg-avutil.opam b/ffmpeg-avutil.opam index 5b49596f..48ce7f5a 100644 --- a/ffmpeg-avutil.opam +++ b/ffmpeg-avutil.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg avutil libraries" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg-swresample.opam b/ffmpeg-swresample.opam index c1400758..553e0514 100644 --- a/ffmpeg-swresample.opam +++ b/ffmpeg-swresample.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg swresample library" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg-swscale.opam b/ffmpeg-swscale.opam index 08a5e63d..32b1fa1c 100644 --- a/ffmpeg-swscale.opam +++ b/ffmpeg-swscale.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg swscale library" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/ffmpeg.opam b/ffmpeg.opam index 2258de33..0e61f680 100644 --- a/ffmpeg.opam +++ b/ffmpeg.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "1.2.0" +version: "1.2.1" synopsis: "Bindings for the ffmpeg libraries" maintainer: ["Romain Beauxis "] authors: ["The Savonet Team "] diff --git a/swscale/swscale.ml b/swscale/swscale.ml index 4ccfb85b..df47b7f1 100644 --- a/swscale/swscale.ml +++ b/swscale/swscale.ml @@ -20,7 +20,7 @@ type planes = (data * int) array external scale : t -> planes -> int -> int -> planes -> int -> unit = "ocaml_swscale_scale_byte" "ocaml_swscale_scale" -type vector_kind = Ba | Frm | Str +type vector_kind = PackedBa | Ba | Frm | Str module type VideoData = sig type t @@ -34,6 +34,13 @@ module BigArray = struct let vk = Ba end +module PackedBigArray = struct + type plane = { plane_size : int; stride : int } + type t = { data : data; planes : plane array } + + let vk = PackedBa +end + module Frame = struct type t = video frame diff --git a/swscale/swscale.mli b/swscale/swscale.mli index 11b6f7ca..b9b09fe8 100644 --- a/swscale/swscale.mli +++ b/swscale/swscale.mli @@ -27,7 +27,7 @@ val scale : t -> planes -> int -> int -> planes -> int -> unit (**/**) -type vector_kind = Ba | Frm | Str +type vector_kind = PackedBa | Ba | Frm | Str (**/**) @@ -68,13 +68,21 @@ module Make (I : VideoData) (O : VideoData) : sig val convert : t -> I.t -> O.t end -(** Unsigned 8 bit bigarray. *) +(** Unsigned 8 bit bigarray split by planes. *) module BigArray : sig type t = planes val vk : vector_kind end +(** Unsigned 8 bit bigarray in a single packed array.. *) +module PackedBigArray : sig + type plane = { plane_size : int; stride : int } + type t = { data : data; planes : plane array } + + val vk : vector_kind +end + (** Video frame. *) module Frame : sig type t = video frame diff --git a/swscale/swscale_stubs.c b/swscale/swscale_stubs.c index 60ebb3cd..09f384f6 100644 --- a/swscale/swscale_stubs.c +++ b/swscale/swscale_stubs.c @@ -158,7 +158,7 @@ CAMLprim value ocaml_swscale_scale_byte(value *argv, int argn) { /***** Contexts *****/ -typedef enum _vector_kind { Ba, Frm, Str } vector_kind; +typedef enum _vector_kind { PackedBa, Ba, Frm, Str } vector_kind; struct video_t { int width; @@ -235,6 +235,27 @@ static int get_in_pixels_ba(sws_t *sws, value *in_vector) { CAMLreturnT(int, nb_planes); } +static int get_in_pixels_packed_ba(sws_t *sws, value *in_vector) { + CAMLparam0(); + CAMLlocal1(v); + uint8_t *data = Caml_ba_data_val(Field(*in_vector, 0)); + int i, nb_planes = Wosize_val(Field(*in_vector, 1)); + int stride, plane_size, offset = 0; + + for (i = 0; i < nb_planes && i < 4; i++) { + v = Field(Field(*in_vector, 1), i); + plane_size = Int_val(Field(v, 0)); + stride = Int_val(Field(v, 1)); + + sws->in.slice[i] = data + offset; + sws->in.stride[i] = stride; + + offset += plane_size; + } + + CAMLreturnT(int, nb_planes); +} + static int alloc_out_frame(sws_t *sws, value *out_vect, value *tmp) { int ret; AVFrame *frame = av_frame_alloc(); @@ -325,6 +346,38 @@ static int alloc_out_ba(sws_t *sws, value *out_vect, value *tmp) { return 0; } +static int alloc_out_packed_ba(sws_t *sws, value *out_vect, value *tmp) { + int i, offset = 0; + intnat out_size = 0; + uint8_t *data; + + for (i = 0; i < sws->out.nb_planes; i++) + out_size += sws->out.plane_sizes[i]; + + out_size += 16; + + *out_vect = caml_alloc_tuple(2); + Store_field( + *out_vect, 0, + caml_ba_alloc(CAML_BA_C_LAYOUT | CAML_BA_UINT8, 1, NULL, &out_size)); + Store_field(*out_vect, 1, caml_alloc_tuple(sws->out.nb_planes)); + + data = Caml_ba_data_val(Field(*out_vect, 0)); + + for (i = 0; i < sws->out.nb_planes; i++) { + *tmp = caml_alloc_tuple(2); + Store_field(*tmp, 0, Val_int(sws->out.plane_sizes[i])); + Store_field(*tmp, 1, Val_int(sws->out.stride[i])); + + Store_field(Field(*out_vect, 1), i, *tmp); + + sws->out.slice[i] = data + offset; + offset += sws->out.plane_sizes[i]; + } + + return 0; +} + CAMLprim value ocaml_swscale_convert(value _sws, value _in_vector) { CAMLparam2(_sws, _in_vector); CAMLlocal2(out_vect, tmp); @@ -436,6 +489,8 @@ CAMLprim value ocaml_swscale_create(value flags_, value in_vector_kind_, } else if (in_vector_kind == Str) { sws->get_in_pixels = get_in_pixels_string; sws->in.owns_data = 1; + } else if (in_vector_kind == PackedBa) { + sws->get_in_pixels = get_in_pixels_packed_ba; } else { sws->get_in_pixels = get_in_pixels_ba; } @@ -446,6 +501,8 @@ CAMLprim value ocaml_swscale_create(value flags_, value in_vector_kind_, sws->alloc_out = alloc_out_string; sws->copy_out = copy_out_string; sws->out.owns_data = 1; + } else if (out_vect_kind == PackedBa) { + sws->alloc_out = alloc_out_packed_ba; } else { sws->alloc_out = alloc_out_ba; }