From af0c41e162725b0edcd6c3d066a2dbef05a3b896 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 7 Jul 2013 23:54:11 +0200 Subject: Remove old demuxers Delete demux_avi, demux_asf, demux_mpg, demux_ts. libavformat does better than them (except in rare corner cases), and the demuxers have a bad influence on the rest of the code. Often they don't output proper packets, and require additional audio and video parsing. Most work only in --no-correct-pts mode. Remove them to facilitate further cleanups. --- audio/decode/dec_audio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'audio') diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 4f2f462b92..3275bae705 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -21,6 +21,8 @@ #include #include +#include + #include "demux/codec_tags.h" #include "config.h" -- cgit v1.2.3 From aac5d758c5a60f13162bc2b500618389bfd92602 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 00:13:53 +0200 Subject: demux: remove audio parser The audio parser was needed only by the "old" demuxers, and demux_rawaudio. All other demuxers output already parsed packets. demux_rawaudio is usually for raw audio, so using a parser with it doesn't usually make sense. But you can also force it to read compressed formats with fixed packet sizes, in which case the parser would have been used. This use case is probably broken now, but you will be able to do the same thing with libavformat demuxers. --- audio/decode/ad_lavc.c | 11 +++-------- audio/decode/ad_spdif.c | 20 ++------------------ 2 files changed, 5 insertions(+), 26 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index b5a4ee1ef8..2495012e47 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -344,7 +344,6 @@ static int control(sh_audio_t *sh, int cmd, void *arg) switch (cmd) { case ADCTRL_RESYNC_STREAM: avcodec_flush_buffers(ctx->avctx); - ds_clear_parser(sh->ds); ctx->previous_data_left = 0; ctx->output_left = 0; return CONTROL_TRUE; @@ -384,10 +383,7 @@ static int decode_new_packet(struct sh_audio *sh) if (!mpkt) { assert(!priv->previous_data_left); start = NULL; - insize = 0; - ds_parse(sh->ds, &start, &insize, pts, 0); - if (insize <= 0) - return -1; // error or EOF + return -1; // error or EOF } else { assert(mpkt->len >= priv->previous_data_left); if (!priv->previous_data_left) { @@ -396,8 +392,7 @@ static int decode_new_packet(struct sh_audio *sh) } insize = priv->previous_data_left; start = mpkt->buffer + mpkt->len - priv->previous_data_left; - int consumed = ds_parse(sh->ds, &start, &insize, pts, 0); - priv->previous_data_left -= consumed; + priv->previous_data_left -= insize; priv->previous_data_left = FFMAX(priv->previous_data_left, 0); } @@ -420,7 +415,7 @@ static int decode_new_packet(struct sh_audio *sh) return -1; } // The "insize >= ret" test is sanity check against decoder overreads - if (!sh->parser && insize >= ret) + if (insize >= ret) priv->previous_data_left = insize - ret; if (!got_frame) return 0; diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 1314110062..49b7d9a0d8 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -132,20 +132,8 @@ static int init(sh_audio_t *sh, const char *decoder) pts = MP_NOPTS_VALUE; x = 0; } - ds_parse(sh->ds, &start, &x, pts, 0); srate = 48000; //fake value bps = 768000/8; //fake value - if (x && sh->avctx) { // we have parser and large enough buffer - if (sh->avctx->sample_rate < 44100) { - mp_msg(MSGT_DECAUDIO,MSGL_INFO, - "This stream sample_rate[%d Hz] may be broken. " - "Force reset 48000Hz.\n", - sh->avctx->sample_rate); - srate = 48000; //fake value - } else - srate = sh->avctx->sample_rate; - bps = sh->avctx->bit_rate/8; - } sh->ds->buffer_pos -= in_size; int num_channels = 0; @@ -239,14 +227,10 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, break; x = ds_get_packet_pts(sh->ds, &start, &pts); if (x <= 0) { - x = 0; - ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0); - if (x == 0) - continue; // END_NOT_FOUND - in_size = x; + continue; // END_NOT_FOUND } else { in_size = x; - consumed = ds_parse(sh->ds, &start, &x, pts, 0); + consumed = x; if (x == 0) { mp_msg(MSGT_DECAUDIO,MSGL_V, "start[%p] in_size[%d] consumed[%d] x[%d].\n", -- cgit v1.2.3 From 9200538b398a2f6d1be6bca107c58fd1a4070b01 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 23:32:44 +0200 Subject: audio: remove decoder input buffer This was unused. --- audio/decode/ad.h | 1 - audio/decode/dec_audio.c | 11 ----------- 2 files changed, 12 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad.h b/audio/decode/ad.h index ff51ecbe35..1f45e88f98 100644 --- a/audio/decode/ad.h +++ b/audio/decode/ad.h @@ -42,7 +42,6 @@ typedef struct ad_functions // NULL terminated array of all drivers extern const ad_functions_t * const mpcodecs_ad_drivers[]; -// fallback if ADCTRL_RESYNC not implemented: sh_audio->a_in_buffer_len=0; #define ADCTRL_RESYNC_STREAM 1 // resync, called after seeking // fallback if ADCTRL_SKIP not implemented: ds_fill_buffer(sh_audio->ds); diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 3275bae705..1bf217de80 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -55,15 +55,6 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) return 0; } - /* allocate audio in buffer: */ - if (sh_audio->audio_in_minsize > 0) { - sh_audio->a_in_buffer_size = sh_audio->audio_in_minsize; - mp_tmsg(MSGT_DECAUDIO, MSGL_V, - "dec_audio: Allocating %d bytes for input buffer.\n", - sh_audio->a_in_buffer_size); - sh_audio->a_in_buffer = av_mallocz(sh_audio->a_in_buffer_size); - } - const int base_size = 65536; // At least 64 KiB plus rounding up to next decodable unit size sh_audio->a_buffer_size = base_size + sh_audio->audio_out_minsize; @@ -194,7 +185,6 @@ void uninit_audio(sh_audio_t *sh_audio) talloc_free(sh_audio->gsh->decoder_desc); sh_audio->gsh->decoder_desc = NULL; av_freep(&sh_audio->a_buffer); - av_freep(&sh_audio->a_in_buffer); } @@ -370,7 +360,6 @@ void decode_audio_prepend_bytes(struct bstr *outbuf, int count, int byte) void resync_audio_stream(sh_audio_t *sh_audio) { - sh_audio->a_in_buffer_len = 0; // clear audio input buffer sh_audio->pts = MP_NOPTS_VALUE; if (!sh_audio->initialized) return; -- cgit v1.2.3 From 052d4ddbbbc91e95e9e4b380423ddb2f67437888 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 10 Jul 2013 02:06:49 +0200 Subject: ad_lavc: simplify We don't need to deal with partial packet reads, manually using an audio parser, or having to call the libavcodec decoder multiple times per packet. Actually, I'm not sure about the last point. ffplay still does this, but the ffmpeg demuxing.c example doesn't. --- audio/decode/ad_lavc.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 2495012e47..c311bc2cb8 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -50,7 +50,6 @@ struct priv { uint8_t *output_packed; // used by deplanarize to store packed audio samples int output_left; int unitsize; - int previous_data_left; // input demuxer packet data bool force_channel_map; }; @@ -344,7 +343,6 @@ static int control(sh_audio_t *sh, int cmd, void *arg) switch (cmd) { case ADCTRL_RESYNC_STREAM: avcodec_flush_buffers(ctx->avctx); - ctx->previous_data_left = 0; ctx->output_left = 0; return CONTROL_TRUE; } @@ -374,35 +372,15 @@ static int decode_new_packet(struct sh_audio *sh) { struct priv *priv = sh->context; AVCodecContext *avctx = priv->avctx; - double pts = MP_NOPTS_VALUE; - int insize; - bool packet_already_used = priv->previous_data_left; - struct demux_packet *mpkt = ds_get_packet2(sh->ds, - priv->previous_data_left); - unsigned char *start; - if (!mpkt) { - assert(!priv->previous_data_left); - start = NULL; + struct demux_packet *mpkt = ds_get_packet2(sh->ds, false); + if (!mpkt) return -1; // error or EOF - } else { - assert(mpkt->len >= priv->previous_data_left); - if (!priv->previous_data_left) { - priv->previous_data_left = mpkt->len; - pts = mpkt->pts; - } - insize = priv->previous_data_left; - start = mpkt->buffer + mpkt->len - priv->previous_data_left; - priv->previous_data_left -= insize; - priv->previous_data_left = FFMAX(priv->previous_data_left, 0); - } AVPacket pkt; mp_set_av_packet(&pkt, mpkt); - pkt.data = start; - pkt.size = insize; - if (pts != MP_NOPTS_VALUE && !packet_already_used) { - sh->pts = pts; + if (mpkt->pts != MP_NOPTS_VALUE) { + sh->pts = mpkt->pts; sh->pts_bytes = 0; } int got_frame = 0; @@ -414,9 +392,6 @@ static int decode_new_packet(struct sh_audio *sh) mp_msg(MSGT_DECAUDIO, MSGL_V, "lavc_audio: error\n"); return -1; } - // The "insize >= ret" test is sanity check against decoder overreads - if (insize >= ret) - priv->previous_data_left = insize - ret; if (!got_frame) return 0; uint64_t unitsize = (uint64_t)av_get_bytes_per_sample(avctx->sample_fmt) * @@ -433,7 +408,7 @@ static int decode_new_packet(struct sh_audio *sh) } else { priv->output = priv->avframe->data[0]; } - mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", insize, + mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", mpkt->len, priv->output_left); return 0; } -- cgit v1.2.3 From a5224836293ac02bd13f688cfc848aae6818e963 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:10:33 +0200 Subject: demux: remove facility for partial packet reads Partial packet reads were needed because the video/audio parsers were working on top of them. So it could happen that a parser read a part of a packet, and returned that to the decoder. With libavformat/libavcodec, packets are already parsed, and everything is much simpler. Most of the simplifications in ad_spdif could have been done earlier. Remove some other stuff as well, like the questionable slave mode start time reporting (could be replaced by proper code, but we don't bother). Remove the unused skip_audio_frame() functionality as well (it was used by old demuxers). Some functions become private to demux.c, like demux_fill_buffer(). Introduce new packet read functions, which have simpler semantics. Packets returned from them are owned by the caller, and all packets in the demux.c packet queue are considered unread. Remove special code that dropped subtitle packets with size 0. This used to be needed because it caused special cases in the old code. --- audio/decode/ad.h | 3 --- audio/decode/ad_lavc.c | 7 ++++-- audio/decode/ad_mpg123.c | 16 ++++++------- audio/decode/ad_spdif.c | 59 +++++++++--------------------------------------- audio/decode/dec_audio.c | 11 --------- 5 files changed, 23 insertions(+), 73 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad.h b/audio/decode/ad.h index 1f45e88f98..1c8a211f5b 100644 --- a/audio/decode/ad.h +++ b/audio/decode/ad.h @@ -44,7 +44,4 @@ extern const ad_functions_t * const mpcodecs_ad_drivers[]; #define ADCTRL_RESYNC_STREAM 1 // resync, called after seeking -// fallback if ADCTRL_SKIP not implemented: ds_fill_buffer(sh_audio->ds); -#define ADCTRL_SKIP_FRAME 2 // skip block/frame, called while seeking - #endif /* MPLAYER_AD_H */ diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index c311bc2cb8..d197bed072 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -372,10 +372,12 @@ static int decode_new_packet(struct sh_audio *sh) { struct priv *priv = sh->context; AVCodecContext *avctx = priv->avctx; - struct demux_packet *mpkt = ds_get_packet2(sh->ds, false); + struct demux_packet *mpkt = demux_read_packet(sh->gsh); if (!mpkt) return -1; // error or EOF + int in_len = mpkt->len; + AVPacket pkt; mp_set_av_packet(&pkt, mpkt); @@ -385,6 +387,7 @@ static int decode_new_packet(struct sh_audio *sh) } int got_frame = 0; int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); + talloc_free(mpkt); // LATM may need many packets to find mux info if (ret == AVERROR(EAGAIN)) return 0; @@ -408,7 +411,7 @@ static int decode_new_packet(struct sh_audio *sh) } else { priv->output = priv->avframe->data[0]; } - mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", mpkt->len, + mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", in_len, priv->output_left); return 0; } diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c index 08739b7f4b..8d97468e06 100644 --- a/audio/decode/ad_mpg123.c +++ b/audio/decode/ad_mpg123.c @@ -217,27 +217,25 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) /* Feed the decoder. This will only fire from the second round on. */ if (ret == MPG123_NEED_MORE) { - int incount; - double pts; - unsigned char *inbuf; /* Feed more input data. */ - incount = ds_get_packet_pts(sh->ds, &inbuf, &pts); - if (incount <= 0) + struct demux_packet *pkt = demux_read_packet(sh->gsh); + if (!pkt) break; /* Apparently that's it. EOF. */ /* Next bytes from that presentation time. */ - if (pts != MP_NOPTS_VALUE) { - sh->pts = pts; + if (pkt->pts != MP_NOPTS_VALUE) { + sh->pts = pkt->pts; sh->pts_bytes = 0; } #ifdef AD_MPG123_FRAMEWISE /* Have to use mpg123_feed() to avoid decoding here. */ - ret = mpg123_feed(con->handle, inbuf, incount); + ret = mpg123_feed(con->handle, pkt->buffer, pkt->len); #else /* Do not use mpg123_feed(), added in later libmpg123 versions. */ - ret = mpg123_decode(con->handle, inbuf, incount, NULL, 0, NULL); + ret = mpg123_decode(con->handle, pkt->buffer, pkt->len, NULL, 0, NULL); #endif + talloc_free(pkt); if (ret == MPG123_ERR) break; } diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 49b7d9a0d8..f4fc430208 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -84,9 +84,7 @@ static int codecs[] = { static int init(sh_audio_t *sh, const char *decoder) { - int x, in_size, srate, bps, *dtshd_rate; - unsigned char *start; - double pts; + int srate, bps, *dtshd_rate; AVFormatContext *lavf_ctx = NULL; AVStream *stream = NULL; const AVOption *opt = NULL; @@ -125,16 +123,8 @@ static int init(sh_audio_t *sh, const char *decoder) goto fail; } - // get sample_rate & bitrate from parser - x = ds_get_packet_pts(sh->ds, &start, &pts); - in_size = x; - if (x <= 0) { - pts = MP_NOPTS_VALUE; - x = 0; - } srate = 48000; //fake value bps = 768000/8; //fake value - sh->ds->buffer_pos -= in_size; int num_channels = 0; switch (lavf_ctx->streams[0]->codec->codec_id) { @@ -214,42 +204,24 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, struct spdifContext *spdif_ctx = sh->context; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; AVPacket pkt; - double pts; - int ret, in_size, consumed, x; - unsigned char *start = NULL; - consumed = spdif_ctx->out_buffer_len = 0; + spdif_ctx->out_buffer_len = 0; spdif_ctx->out_buffer_size = maxlen; spdif_ctx->out_buffer = buf; while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen && spdif_ctx->out_buffer_len < minlen) { - if (sh->ds->eof) + struct demux_packet *mpkt = demux_read_packet(sh->gsh); + if (!mpkt) break; - x = ds_get_packet_pts(sh->ds, &start, &pts); - if (x <= 0) { - continue; // END_NOT_FOUND - } else { - in_size = x; - consumed = x; - if (x == 0) { - mp_msg(MSGT_DECAUDIO,MSGL_V, - "start[%p] in_size[%d] consumed[%d] x[%d].\n", - start, in_size, consumed, x); - continue; // END_NOT_FOUND - } - sh->ds->buffer_pos -= in_size - consumed; - } - av_init_packet(&pkt); - pkt.data = start; - pkt.size = x; - mp_msg(MSGT_DECAUDIO,MSGL_V, - "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", - start, pkt.size, in_size, consumed, x); - if (pts != MP_NOPTS_VALUE) { - sh->pts = pts; + mp_set_av_packet(&pkt, mpkt); + mp_msg(MSGT_DECAUDIO,MSGL_V, "pkt.data[%p] pkt.size[%d]\n", + pkt.data, pkt.size); + if (mpkt->pts != MP_NOPTS_VALUE) { + sh->pts = mpkt->pts; sh->pts_bytes = 0; } - ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); + int ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); + talloc_free(mpkt); if (ret < 0) break; } @@ -259,15 +231,6 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, static int control(sh_audio_t *sh, int cmd, void *arg) { - unsigned char *start; - double pts; - - switch (cmd) { - case ADCTRL_RESYNC_STREAM: - case ADCTRL_SKIP_FRAME: - ds_get_packet_pts(sh->ds, &start, &pts); - return CONTROL_TRUE; - } return CONTROL_UNKNOWN; } diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 1bf217de80..8c80a0b119 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -365,14 +365,3 @@ void resync_audio_stream(sh_audio_t *sh_audio) return; sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); } - -void skip_audio_frame(sh_audio_t *sh_audio) -{ - if (!sh_audio->initialized) - return; - if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) - == CONTROL_TRUE) - return; - // default skip code: - ds_fill_buffer(sh_audio->ds); // skip block -} -- cgit v1.2.3 From 7a4f9cc4d2509a0d9afa68ea53ed97b72525d001 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:14:30 +0200 Subject: ad_spdif: better PTS sync pts_bytes can't just be changed at the end. It must be offset to the pts value, which is reset with each packet read from the demuxer. Make sure the pts_byte field is always reset after receiving a new PTS, i.e. increment it after actually writing to the output buffer. Flush the AVFormatContext's write buffer, because otherwise the audio PTS will jump around too much: the calculation doesn't use the exact output buffer size if there's still data in the avio buffer. --- audio/decode/ad_spdif.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'audio') diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index f4fc430208..d0fa43aa25 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -220,12 +220,14 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, sh->pts = mpkt->pts; sh->pts_bytes = 0; } + int out_len = spdif_ctx->out_buffer_len; int ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); + avio_flush(lavf_ctx->pb); + sh->pts_bytes += spdif_ctx->out_buffer_len - out_len; talloc_free(mpkt); if (ret < 0) break; } - sh->pts_bytes += spdif_ctx->out_buffer_len; return spdif_ctx->out_buffer_len; } -- cgit v1.2.3 From 23e303859aa93572f00b17e3b2bc0a552ad7c348 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:15:09 +0200 Subject: mplayer: fix incorrect audio sync after format changes This is not directly related to the handling of format changes itself, but playing audio normally after the change. This was broken: the output byte rate was not recalculated, so audio-video sync was simply broken. Fix this by calculating the byte rate on the fly, instead of storing it in sh_audio. Format changes are relatively common (switches between stereo and 5.1 in TV recordings), so this fixes a somewhat critical bug. --- audio/decode/dec_audio.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'audio') diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 8c80a0b119..d6b57dd2b5 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -84,9 +84,6 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) return 0; } - if (!sh_audio->o_bps) - sh_audio->o_bps = sh_audio->channels.num * sh_audio->samplerate - * sh_audio->samplesize; return 1; } @@ -150,12 +147,9 @@ int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n", sh_audio->gsh->decoder_desc); mp_msg(MSGT_DECAUDIO, MSGL_V, - "AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n", + "AUDIO: %d Hz, %d ch, %s\n", sh_audio->samplerate, sh_audio->channels.num, - af_fmt2str_short(sh_audio->sample_format), - sh_audio->i_bps * 8 * 0.001, - ((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0, - sh_audio->i_bps, sh_audio->o_bps); + af_fmt2str_short(sh_audio->sample_format)); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num); -- cgit v1.2.3 From 6f6632b8dd9273a3cbc8e3e0d69e1d3dceed6f45 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:20:41 +0200 Subject: ad_lavc: re-unsimplify, fix libavcodec API usage It turns out that some code that was removed earlier was still needed. avcodec_decode_audio4() can decode packets "partially". In that case, you have to "slice" the packet and call the decode function again. Codecs which need this are obscure and in low numbers. One sample that needs it is here: rsync://fate-suite.ffmpeg.org/fate-suite/lossless-audio/luckynight-partial.shn (This one decodes in rather small increments.) The new code is much simpler than what has been removed earlier, though. The fact that we own the packet returned by the demuxer helps a lot. Not sure what should happen if avcodec_decode_audio4() returns 0. Currently, we throw away the packet in this case. We don't want to be stuck in an endless loop (could happen if the decoder produces no output either). --- audio/decode/ad_lavc.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index d197bed072..e78e26f208 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -24,6 +24,7 @@ #include #include +#include #include "talloc.h" @@ -51,6 +52,7 @@ struct priv { int output_left; int unitsize; bool force_channel_map; + struct demux_packet *packet; }; #define OPT_BASE_STRUCT struct MPOpts @@ -344,6 +346,8 @@ static int control(sh_audio_t *sh, int cmd, void *arg) case ADCTRL_RESYNC_STREAM: avcodec_flush_buffers(ctx->avctx); ctx->output_left = 0; + talloc_free(ctx->packet); + ctx->packet = NULL; return CONTROL_TRUE; } return CONTROL_UNKNOWN; @@ -372,10 +376,14 @@ static int decode_new_packet(struct sh_audio *sh) { struct priv *priv = sh->context; AVCodecContext *avctx = priv->avctx; - struct demux_packet *mpkt = demux_read_packet(sh->gsh); + struct demux_packet *mpkt = priv->packet; + if (!mpkt) + mpkt = demux_read_packet(sh->gsh); if (!mpkt) return -1; // error or EOF + priv->packet = talloc_steal(priv, mpkt); + int in_len = mpkt->len; AVPacket pkt; @@ -387,7 +395,16 @@ static int decode_new_packet(struct sh_audio *sh) } int got_frame = 0; int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); - talloc_free(mpkt); + if (ret > 0) { + ret = FFMIN(ret, mpkt->len); // sanity check against decoder overreads + mpkt->buffer += ret; + mpkt->len -= ret; + mpkt->pts = MP_NOPTS_VALUE; // don't reset PTS next time + } + if (mpkt->len == 0 || ret <= 0) { + talloc_free(mpkt); + priv->packet = NULL; + } // LATM may need many packets to find mux info if (ret == AVERROR(EAGAIN)) return 0; -- cgit v1.2.3