From 6d9b6f2dc523198d071adbdbaa7cba002636a7e9 Mon Sep 17 00:00:00 2001 From: Romain Beauxis Date: Sat, 3 Aug 2024 09:55:26 -0500 Subject: [PATCH] Better channel copy. Fixes: savonet/liquidsoap#4065, savonet/liquidsoap#4064 (#64) --- avcodec/avcodec_stubs.c | 13 +++++-- avfilter/avfilter_stubs.c | 7 ++-- avutil/avutil_stubs.c | 82 +++++++++++++++++++++------------------ avutil/avutil_stubs.h | 3 +- 4 files changed, 59 insertions(+), 46 deletions(-) diff --git a/avcodec/avcodec_stubs.c b/avcodec/avcodec_stubs.c index 022f8363..f74226ab 100644 --- a/avcodec/avcodec_stubs.c +++ b/avcodec/avcodec_stubs.c @@ -1286,14 +1286,16 @@ CAMLprim value ocaml_avcodec_hw_methods(value _codec) { CAMLprim value ocaml_avcodec_get_supported_channel_layouts(value _codec) { CAMLparam1(_codec); - CAMLlocal2(list, cons); + CAMLlocal3(list, cons, ch_layout); int i; List_init(list); const AVCodec *codec = AvCodec_val(_codec); if (codec->ch_layouts) { - for (i = 0; codec->ch_layouts[i].nb_channels != 0; i++) - List_add(list, cons, value_of_channel_layout(&codec->ch_layouts[i])); + for (i = 0; codec->ch_layouts[i].nb_channels != 0; i++) { + value_of_channel_layout(&ch_layout, &codec->ch_layouts[i]); + List_add(list, cons, ch_layout); + } } CAMLreturn(list); @@ -1337,9 +1339,12 @@ CAMLprim value ocaml_avcodec_parameters_get_audio_codec_id(value _cp) { CAMLprim value ocaml_avcodec_parameters_get_channel_layout(value _cp) { CAMLparam1(_cp); + CAMLlocal1(_ch_layout); AVCodecParameters *cp = CodecParameters_val(_cp); - CAMLreturn(value_of_channel_layout(&cp->ch_layout)); + value_of_channel_layout(&_ch_layout, &cp->ch_layout); + + CAMLreturn(_ch_layout); } CAMLprim value ocaml_avcodec_parameters_get_nb_channels(value _cp) { diff --git a/avfilter/avfilter_stubs.c b/avfilter/avfilter_stubs.c index d103e663..892bca48 100644 --- a/avfilter/avfilter_stubs.c +++ b/avfilter/avfilter_stubs.c @@ -467,11 +467,10 @@ CAMLprim value ocaml_avfilter_buffersink_get_channel_layout(value _src) { CAMLparam0(); CAMLlocal1(ret); AVFilterContext *filter_ctx = AvFilterContext_val(_src); - AVChannelLayout channel_layout; - int err = av_buffersink_get_ch_layout(filter_ctx, &channel_layout); + AVChannelLayout *channel_layout = + caml_avutil_alloc_custom_channel_layout(&ret); - ret = value_of_channel_layout(&channel_layout); - av_channel_layout_uninit(&channel_layout); + int err = av_buffersink_get_ch_layout(filter_ctx, channel_layout); CAMLreturn(ret); } diff --git a/avutil/avutil_stubs.c b/avutil/avutil_stubs.c index b704be25..78d2f8dd 100644 --- a/avutil/avutil_stubs.c +++ b/avutil/avutil_stubs.c @@ -338,26 +338,33 @@ static struct custom_operations channel_layout_ops = { custom_compare_default, custom_hash_default, custom_serialize_default, custom_deserialize_default}; -value value_of_channel_layout(const AVChannelLayout *channel_layout) { - value ret; +AVChannelLayout *caml_avutil_alloc_custom_channel_layout(value *ret) { AVChannelLayout *ch_layout; int err; - if (!channel_layout) - Fail("Empty channel_layout"); + ch_layout = av_mallocz(sizeof(AVChannelLayout)); + + if (!ch_layout) + caml_raise_out_of_memory(); + + *ret = + caml_alloc_custom(&channel_layout_ops, sizeof(AVChannelLayout *), 0, 1); + AVChannelLayout_val(*ret) = ch_layout; + + return ch_layout; +} + +void value_of_channel_layout(value *ret, + const AVChannelLayout *channel_layout) { + AVChannelLayout *ch_layout = caml_avutil_alloc_custom_channel_layout(ret); + int err; - ch_layout = av_malloc(sizeof(AVChannelLayout)); err = av_channel_layout_copy(ch_layout, channel_layout); if (err) { av_free(ch_layout); ocaml_avutil_raise_error(err); } - - ret = caml_alloc_custom(&channel_layout_ops, sizeof(AVChannelLayout *), 0, 1); - AVChannelLayout_val(ret) = ch_layout; - - return ret; } #define AVChannelLayoutOpaque_val(v) (*(void ***)Data_custom_val(v)) @@ -391,7 +398,7 @@ CAMLprim value ocaml_avutil_start_standard_iteration() { CAMLprim value ocaml_avutil_get_standard(value _opaque) { CAMLparam1(_opaque); - CAMLlocal1(ret); + CAMLlocal2(_ch_layout, ret); void **opaque = AVChannelLayoutOpaque_val(_opaque); const AVChannelLayout *channel_layout = av_channel_layout_standard(opaque); @@ -399,7 +406,10 @@ CAMLprim value ocaml_avutil_get_standard(value _opaque) { CAMLreturn(Val_none); ret = caml_alloc_tuple(1); - Store_field(ret, 0, value_of_channel_layout(channel_layout)); + + value_of_channel_layout(&_ch_layout, channel_layout); + + Store_field(ret, 0, _ch_layout); CAMLreturn(ret); } @@ -452,30 +462,27 @@ ocaml_avutil_get_channel_layout_nb_channels(value _channel_layout) { CAMLprim value ocaml_avutil_get_default_channel_layout(value _nb_channels) { CAMLparam0(); - CAMLlocal1(ret); - AVChannelLayout channel_layout; - - av_channel_layout_default(&channel_layout, Int_val(_nb_channels)); + CAMLlocal1(_ch_layout); + AVChannelLayout *channel_layout = + caml_avutil_alloc_custom_channel_layout(&_ch_layout); - ret = value_of_channel_layout(&channel_layout); - av_channel_layout_uninit(&channel_layout); + av_channel_layout_default(channel_layout, Int_val(_nb_channels)); - CAMLreturn(ret); + CAMLreturn(_ch_layout); } CAMLprim value ocaml_avutil_get_channel_layout(value _name) { CAMLparam1(_name); - CAMLlocal1(ret); - AVChannelLayout channel_layout; - int err = av_channel_layout_from_string(&channel_layout, String_val(_name)); + CAMLlocal1(_ch_layout); + AVChannelLayout *channel_layout = + caml_avutil_alloc_custom_channel_layout(&_ch_layout); + + int err = av_channel_layout_from_string(channel_layout, String_val(_name)); if (err) ocaml_avutil_raise_error(err); - ret = value_of_channel_layout(&channel_layout); - av_channel_layout_uninit(&channel_layout); - - CAMLreturn(ret); + CAMLreturn(_ch_layout); } /**** Sample format ****/ @@ -941,9 +948,12 @@ CAMLprim value ocaml_avutil_audio_frame_get_channels(value _frame) { CAMLprim value ocaml_avutil_audio_frame_get_channel_layout(value _frame) { CAMLparam1(_frame); + CAMLlocal1(_ch_layout); AVFrame *frame = Frame_val(_frame); - CAMLreturn(value_of_channel_layout(&frame->ch_layout)); + value_of_channel_layout(&_ch_layout, &frame->ch_layout); + + CAMLreturn(_ch_layout); } CAMLprim value ocaml_avutil_audio_frame_nb_samples(value _frame) { @@ -1185,7 +1195,7 @@ CAMLprim value ocaml_avutil_get_opt(value _type, value search_children, double d; AVRational r; int w_out, h_out; - AVChannelLayout channel_layout; + AVChannelLayout *channel_layout; enum AVPixelFormat pf; enum AVSampleFormat sf; AVDictionary *dict = NULL; @@ -1289,14 +1299,12 @@ CAMLprim value ocaml_avutil_get_opt(value _type, value search_children, break; case PVV_Channel_layout: + channel_layout = caml_avutil_alloc_custom_channel_layout(&ret); err = av_opt_get_chlayout((void *)obj, (const char *)String_val(name), - search_flags, &channel_layout); + search_flags, channel_layout); if (err < 0) ocaml_avutil_raise_error(err); - ret = value_of_channel_layout(&channel_layout); - av_channel_layout_uninit(&channel_layout); - CAMLreturn(ret); break; @@ -1329,9 +1337,9 @@ CAMLprim value ocaml_avutil_get_opt(value _type, value search_children, CAMLprim value ocaml_avutil_av_opt_iter(value _cursor, value _class) { CAMLparam2(_cursor, _class); - CAMLlocal4(_opt, _type, _tmp, _spec); + CAMLlocal5(_opt, _type, _tmp, _spec, _ch_layout); int unimplement_option = 0; - AVChannelLayout channel_layout; + AVChannelLayout *channel_layout; const AVClass *class; const struct AVOption *option; @@ -1410,12 +1418,12 @@ CAMLprim value ocaml_avutil_av_opt_iter(value _cursor, value _class) { break; case AV_OPT_TYPE_CHLAYOUT: _type = PVV_Channel_layout; + channel_layout = caml_avutil_alloc_custom_channel_layout(&_ch_layout); if (option->default_val.str && - av_channel_layout_from_string(&channel_layout, + av_channel_layout_from_string(channel_layout, option->default_val.str)) { - Store_field(_tmp, 0, value_of_channel_layout(&channel_layout)); + Store_field(_tmp, 0, _ch_layout); Store_field(_spec, 0, _tmp); - av_channel_layout_uninit(&channel_layout); } break; case AV_OPT_TYPE_PIXEL_FMT: diff --git a/avutil/avutil_stubs.h b/avutil/avutil_stubs.h index 7d60c91f..655b636f 100644 --- a/avutil/avutil_stubs.h +++ b/avutil/avutil_stubs.h @@ -62,7 +62,8 @@ int64_t second_fractions_of_time_format(value time_format); #define AVChannelLayout_val(v) (*(struct AVChannelLayout **)Data_custom_val(v)) -value value_of_channel_layout(const AVChannelLayout *); +AVChannelLayout *caml_avutil_alloc_custom_channel_layout(value *v); +void value_of_channel_layout(value *v, const AVChannelLayout *); /**** Sample format ****/