From fd8750c25b4eec77f6401033ab1c2c5385cbedaf Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 9 Mar 2013 08:26:10 +0100 Subject: af_lavcac3enc: switch to avcodec_encode_audio2() avcodec_encode_audio() was deprecated, and was finally removed from Libav and FFmpeg git. This appears to work. I get heavy A/V desync with -ao alsa and -ao pcm, but this was already so before this change. --- audio/filter/af_lavcac3enc.c | 116 ++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index 2b7a4ffb4c..94d59a11ca 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -27,7 +27,9 @@ #include #include +#include #include +#include #include #include "config.h" @@ -47,6 +49,7 @@ const uint16_t ac3_bitrate_tab[19] = { typedef struct af_ac3enc_s { struct AVCodec *lavc_acodec; struct AVCodecContext *lavc_actx; + AVPacket pkt; bool planarize; int add_iec61937_header; int bit_rate; @@ -105,6 +108,8 @@ static int control(struct af_instance *af, int cmd, void *arg) // Put sample parameters s->lavc_actx->channels = af->data->nch; + s->lavc_actx->channel_layout = + av_get_default_channel_layout(af->data->nch); s->lavc_actx->sample_rate = af->data->rate; s->lavc_actx->bit_rate = bit_rate; @@ -155,12 +160,13 @@ static int control(struct af_instance *af, int cmd, void *arg) // Deallocate memory static void uninit(struct af_instance* af) { + af_ac3enc_t *s = af->setup; + if (af->data) free(af->data->audio); free(af->data); - if (af->setup) { - af_ac3enc_t *s = af->setup; - af->setup = NULL; + if (s) { + av_free_packet(&s->pkt); if(s->lavc_actx) { avcodec_close(s->lavc_actx); av_free(s->lavc_actx); @@ -176,8 +182,8 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) af_ac3enc_t *s = af->setup; struct mp_audio *c = data; // Current working data struct mp_audio *l; - int len, left, outsize = 0, destsize; - char *buf, *src, *dest; + int left, outsize = 0; + char *buf, *src; int max_output_len; int frame_num = (data->len + s->pending_len) / s->expect_len; int samplesize = af_fmt2bits(s->in_sampleformat) / 8; @@ -207,6 +213,8 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) while (left > 0) { + int ret; + if (left + s->pending_len < s->expect_len) { memcpy(s->pending_data + s->pending_len, src, left); src += left; @@ -215,8 +223,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) break; } - dest = s->add_iec61937_header ? buf + 8 : buf; - destsize = (char *)l->audio + l->len - buf; + char *src2 = src; if (s->pending_len) { int needs = s->expect_len - s->pending_len; @@ -225,58 +232,69 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) src += needs; left -= needs; } + src2= s->pending_data; + } - if (c->nch >= 5) - reorder_channel_nch(s->pending_data, - AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, - AF_CHANNEL_LAYOUT_LAVC_DEFAULT, - c->nch, - s->expect_len / samplesize, samplesize); - - void *data = (void *) s->pending_data; - if (s->planarize) { - void *data2 = malloc(s->expect_len); - reorder_to_planar(data2, data, samplesize, - c->nch, s->expect_len / samplesize / c->nch); - data = data2; - } + if (c->nch >= 5) { + reorder_channel_nch(src2, + AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, + AF_CHANNEL_LAYOUT_LAVC_DEFAULT, + c->nch, + s->expect_len / samplesize, + samplesize); + } - len = avcodec_encode_audio(s->lavc_actx, dest, destsize, data); + void *data = (void *) src2; + if (s->planarize) { + void *data2 = malloc(s->expect_len); + reorder_to_planar(data2, data, samplesize, + c->nch, s->expect_len / samplesize / c->nch); + data = data2; + } - if (s->planarize) - free(data); + AVFrame *frame = avcodec_alloc_frame(); + if (!frame) { + mp_msg(MSGT_AFILTER, MSGL_FATAL, "[libaf] Could not allocate memory \n"); + return NULL; + } + frame->nb_samples = AC3_FRAME_SIZE; + frame->format = s->lavc_actx->sample_fmt; + frame->channel_layout = s->lavc_actx->channel_layout; + + ret = avcodec_fill_audio_frame(frame, c->nch, s->lavc_actx->sample_fmt, + (const uint8_t*)data, s->expect_len, 0); + if (ret < 0) { + mp_msg(MSGT_AFILTER, MSGL_FATAL, "[lavac3enc] Frame setup failed.\n"); + return NULL; + } - s->pending_len = 0; + int ok; + ret = avcodec_encode_audio2(s->lavc_actx, &s->pkt, frame, &ok); + if (ret < 0 || !ok) { + mp_msg(MSGT_AFILTER, MSGL_FATAL, "[lavac3enc] Encode failed.\n"); + return NULL; } - else { - if (c->nch >= 5) - reorder_channel_nch(src, - AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, - AF_CHANNEL_LAYOUT_LAVC_DEFAULT, - c->nch, - s->expect_len / samplesize, samplesize); - - void *data = (void *) src; - if (s->planarize) { - void *data2 = malloc(s->expect_len); - reorder_to_planar(data2, data, samplesize, - c->nch, s->expect_len / samplesize / c->nch); - data = data2; - } - len = avcodec_encode_audio(s->lavc_actx, dest, destsize, data); + if (s->planarize) + free(data); - if (s->planarize) - free(data); + avcodec_free_frame(&frame); + if (s->pending_len) { + s->pending_len = 0; + } else { src += s->expect_len; left -= s->expect_len; } + mp_msg(MSGT_AFILTER, MSGL_DBG2, "avcodec_encode_audio got %d, pending %d.\n", - len, s->pending_len); + s->pkt.size, s->pending_len); + int len = s->pkt.size; + int header_len = 0; if (s->add_iec61937_header) { - int bsmod = dest[5] & 0x7; + assert(s->pkt.size > 5); + int bsmod = s->pkt.data[5] & 0x7; AV_WB16(buf, 0xF872); // iec 61937 syncword 1 AV_WB16(buf + 2, 0x4E1F); // iec 61937 syncword 2 @@ -285,9 +303,15 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) AV_WB16(buf + 6, len << 3); // number of bits in payload memset(buf + 8 + len, 0, AC3_FRAME_SIZE * 2 * 2 - 8 - len); + header_len = 8; len = AC3_FRAME_SIZE * 2 * 2; } + assert(buf + len <= (char *)af->data->audio + af->data->len); + assert(s->pkt.size <= len - header_len); + + memcpy(buf + header_len, s->pkt.data, s->pkt.size); + outsize += len; buf += len; } @@ -360,6 +384,8 @@ static int af_open(struct af_instance* af){ mp_msg(MSGT_AFILTER, MSGL_WARN, "[af_lavcac3enc]: need to planarize audio data\n"); + av_init_packet(&s->pkt); + return AF_OK; } -- cgit v1.2.3