Skip to content

Commit

Permalink
Better channel copy. Fixes: savonet/liquidsoap#4065, savonet/liquidso…
Browse files Browse the repository at this point in the history
  • Loading branch information
toots authored Aug 3, 2024
1 parent 91527f5 commit 7c2ca7b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 46 deletions.
13 changes: 9 additions & 4 deletions avcodec/avcodec_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 3 additions & 4 deletions avfilter/avfilter_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
86 changes: 49 additions & 37 deletions avutil/avutil_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,26 +338,37 @@ 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_malloc(sizeof(AVChannelLayout));

if (!ch_layout)
caml_raise_out_of_memory();

// Channel layout should always be initialized
av_channel_layout_copy(ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);

*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;

av_channel_layout_uninit(ch_layout);
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))
Expand Down Expand Up @@ -391,15 +402,18 @@ 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);

if (!channel_layout)
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);
}
Expand Down Expand Up @@ -452,30 +466,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 ****/
Expand Down Expand Up @@ -941,9 +952,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) {
Expand Down Expand Up @@ -1185,7 +1199,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;
Expand Down Expand Up @@ -1289,14 +1303,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;

Expand Down Expand Up @@ -1329,9 +1341,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;
Expand Down Expand Up @@ -1410,12 +1422,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:
Expand Down
3 changes: 2 additions & 1 deletion avutil/avutil_stubs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ****/

Expand Down

0 comments on commit 7c2ca7b

Please sign in to comment.