From e855eba5c0d126f2849bad1585457425ec69e973 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 6 Jun 2021 12:40:37 -0300 Subject: [PATCH 1/4] pcm_a52: add some padding bytes to outbuf Since it's used as AVPacket payload, the API requires it to be padded. Signed-off-by: James Almer --- a52/pcm_a52.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/a52/pcm_a52.c b/a52/pcm_a52.c index b6a8f55..2ccc478 100644 --- a/a52/pcm_a52.c +++ b/a52/pcm_a52.c @@ -62,6 +62,12 @@ #define AV_CODEC_ID_AC3 CODEC_ID_AC3 #endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 0) +#ifndef AV_INPUT_BUFFER_PADDING_SIZE +#define AV_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE +#endif +#endif + #if LIBAVCODEC_VERSION_INT < 0x371c01 #define av_frame_alloc avcodec_alloc_frame #define av_frame_free avcodec_free_frame @@ -623,9 +629,10 @@ static int a52_prepare(snd_pcm_ioplug_t *io) return -EINVAL; rec->outbuf_size = rec->avctx->frame_size * 4; - rec->outbuf = malloc(rec->outbuf_size); + rec->outbuf = malloc(rec->outbuf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (! rec->outbuf) return -ENOMEM; + memset(rec->outbuf + rec->outbuf_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (alloc_input_buffer(io)) return -ENOMEM; From 05a5e191c8385633bdff23cd045bb7e11d24dbe7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 6 Jun 2021 14:38:11 -0300 Subject: [PATCH 2/4] pcm_a52: propagate errors from do_encode() Signed-off-by: James Almer --- a52/pcm_a52.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/a52/pcm_a52.c b/a52/pcm_a52.c index 2ccc478..ecf7430 100644 --- a/a52/pcm_a52.c +++ b/a52/pcm_a52.c @@ -111,25 +111,35 @@ static int do_encode(struct a52_ctx *rec) .data = rec->outbuf + 8, .size = rec->outbuf_size - 8 }; - int got_frame; + int ret, got_frame; + + ret = avcodec_encode_audio2(rec->avctx, &pkt, rec->frame, &got_frame); + if (ret < 0) + return -EINVAL; - avcodec_encode_audio2(rec->avctx, &pkt, rec->frame, &got_frame); return pkt.size; } #else static int do_encode(struct a52_ctx *rec) { - return avcodec_encode_audio(rec->avctx, rec->outbuf + 8, + int ret = avcodec_encode_audio(rec->avctx, rec->outbuf + 8, rec->outbuf_size - 8, rec->inbuf); + if (ret < 0) + return -EINVAL; + + return ret; } #endif /* convert the PCM data to A52 stream in IEC958 */ -static void convert_data(struct a52_ctx *rec) +static int convert_data(struct a52_ctx *rec) { int out_bytes = do_encode(rec); + if (out_bytes < 0) + return out_bytes; + rec->outbuf[0] = 0xf8; /* sync words */ rec->outbuf[1] = 0x72; rec->outbuf[2] = 0x4e; @@ -145,6 +155,8 @@ static void convert_data(struct a52_ctx *rec) rec->outbuf_size - 8 - out_bytes); rec->remain = rec->outbuf_size / 4; rec->filled = 0; + + return 0; } /* write pending encoded data to the slave pcm */ @@ -204,7 +216,9 @@ static int a52_drain(snd_pcm_ioplug_t *io) memset(rec->inbuf + rec->filled * io->channels, 0, (rec->avctx->frame_size - rec->filled) * io->channels * 2); } - convert_data(rec); + err = convert_data(rec); + if (err < 0) + return err; } err = write_out_pending(io, rec); if (err < 0) @@ -303,7 +317,9 @@ static int fill_data(snd_pcm_ioplug_t *io, } rec->filled += size; if (rec->filled == rec->avctx->frame_size) { - convert_data(rec); + err = convert_data(rec); + if (err < 0) + return err; write_out_pending(io, rec); } return (int)size; From 5db4841812069f7145cb0ab6e69b23ccce9cbdd4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 6 Jun 2021 14:55:08 -0300 Subject: [PATCH 3/4] pcm_a52: support the new libavcodec encode API ffmpeg 4.4 is the last version with avcodec_encode_audio2(). Starting from the next release the new decoupled input-output API will be the only one available. BugLink: #22 Signed-off-by: James Almer --- a52/pcm_a52.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/a52/pcm_a52.c b/a52/pcm_a52.c index ecf7430..816e5e3 100644 --- a/a52/pcm_a52.c +++ b/a52/pcm_a52.c @@ -44,6 +44,11 @@ #define USE_AVCODEC_FRAME #endif +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 0) +#include +#define USE_AVCODEC_PACKET_ALLOC +#endif + #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 0, 0) #ifndef AV_CH_LAYOUT_STEREO #define AV_CH_LAYOUT_STEREO CH_LAYOUT_STEREO @@ -92,6 +97,9 @@ struct a52_ctx { unsigned int slave_period_size; unsigned int slave_buffer_size; snd_pcm_hw_params_t *hw_params; +#ifdef USE_AVCODEC_PACKET_ALLOC + AVPacket *pkt; +#endif #ifdef USE_AVCODEC_FRAME AVFrame *frame; int is_planar; @@ -104,7 +112,26 @@ struct a52_ctx { #define use_planar(rec) 0 #endif -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 34, 0) +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 0) +static int do_encode(struct a52_ctx *rec) +{ + AVPacket *pkt = rec->pkt; + int ret; + + ret = avcodec_send_frame(rec->avctx, rec->frame); + if (ret < 0) + return -EINVAL; + ret = avcodec_receive_packet(rec->avctx, pkt); + if (ret < 0) + return -EINVAL; + + if (pkt->size > rec->outbuf_size - 8) + return -EINVAL; + memcpy(rec->outbuf + 8, pkt->data, pkt->size); + + return pkt->size; +} +#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 34, 0) static int do_encode(struct a52_ctx *rec) { AVPacket pkt = { @@ -558,6 +585,9 @@ static void a52_free(struct a52_ctx *rec) #endif #endif +#ifdef USE_AVCODEC_PACKET_ALLOC + av_packet_free(&rec->pkt); +#endif free(rec->inbuf); rec->inbuf = NULL; free(rec->outbuf); @@ -603,6 +633,12 @@ static int alloc_input_buffer(snd_pcm_ioplug_t *io) io->channels, rec->avctx->frame_size, rec->avctx->sample_fmt, 0) < 0) return -ENOMEM; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 0) + rec->frame->extended_data = rec->frame->data; + rec->frame->format = rec->avctx->sample_fmt; + rec->frame->channels = rec->avctx->channels; + rec->frame->channel_layout = rec->avctx->channel_layout; +#endif rec->frame->nb_samples = rec->avctx->frame_size; rec->inbuf = (short *)rec->frame->data[0]; #else @@ -644,6 +680,12 @@ static int a52_prepare(snd_pcm_ioplug_t *io) if (err < 0) return -EINVAL; +#ifdef USE_AVCODEC_PACKET_ALLOC + rec->pkt = av_packet_alloc(); + if (!rec->pkt) + return -ENOMEM; +#endif + rec->outbuf_size = rec->avctx->frame_size * 4; rec->outbuf = malloc(rec->outbuf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (! rec->outbuf) From 66b1db798123e91d143d5fe6dc0adbbf7da3873d Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 8 Jun 2021 17:08:41 -0300 Subject: [PATCH 4/4] pcm_a52: don't call avcodec_register_all() on newer libavocdec versions It's no longer available starting with LIBAVCODEC_VERSION_MAJOR == 59. Signed-off-by: James Almer --- a52/pcm_a52.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/a52/pcm_a52.c b/a52/pcm_a52.c index 816e5e3..14e444d 100644 --- a/a52/pcm_a52.c +++ b/a52/pcm_a52.c @@ -1004,7 +1004,9 @@ SND_PCM_PLUGIN_DEFINE_FUNC(a52) #ifndef USE_AVCODEC_FRAME avcodec_init(); #endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 0, 0) avcodec_register_all(); +#endif rec->codec = avcodec_find_encoder_by_name("ac3_fixed"); if (rec->codec == NULL)