1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-26 17:12:36 +00:00

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).
This commit is contained in:
wm4 2013-07-11 19:20:41 +02:00
parent 06281848de
commit 6f6632b8dd

View File

@ -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;