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 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'audio/decode/ad_lavc.c') 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; -- 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/decode/ad_lavc.c') 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_lavc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'audio/decode/ad_lavc.c') 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; } -- 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/decode/ad_lavc.c') 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