summaryrefslogtreecommitdiffstats
path: root/audio/decode/ad_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-11 19:20:41 +0200
committerwm4 <wm4@nowhere>2013-07-11 19:20:41 +0200
commit6f6632b8dd9273a3cbc8e3e0d69e1d3dceed6f45 (patch)
tree3b7f34069b768850a3f9cdb3a81895c3f5385b31 /audio/decode/ad_lavc.c
parent06281848de53153266d8d4639bbc98e12505994b (diff)
downloadmpv-6f6632b8dd9273a3cbc8e3e0d69e1d3dceed6f45.tar.bz2
mpv-6f6632b8dd9273a3cbc8e3e0d69e1d3dceed6f45.tar.xz
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).
Diffstat (limited to 'audio/decode/ad_lavc.c')
-rw-r--r--audio/decode/ad_lavc.c21
1 files changed, 19 insertions, 2 deletions
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 <libavcodec/avcodec.h>
#include <libavutil/opt.h>
+#include <libavutil/common.h>
#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;