summaryrefslogtreecommitdiffstats
path: root/audio/decode/ad_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-11-12 23:42:04 +0100
committerwm4 <wm4@nowhere>2013-11-12 23:42:04 +0100
commite4bbb1d348dafbb32722f413648006a7bd9d0897 (patch)
tree7165ed9f86a77b751187600d0a9de8b35416f380 /audio/decode/ad_lavc.c
parente4f2fcc0ecd31322df65141edf0ddbff9c075f5d (diff)
parent22b3f522cacfbdba76d311c86efd6091512eb089 (diff)
downloadmpv-e4bbb1d348dafbb32722f413648006a7bd9d0897.tar.bz2
mpv-e4bbb1d348dafbb32722f413648006a7bd9d0897.tar.xz
Merge branch 'planar_audio'
Conflicts: audio/out/ao_lavc.c
Diffstat (limited to 'audio/decode/ad_lavc.c')
-rw-r--r--audio/decode/ad_lavc.c161
1 files changed, 53 insertions, 108 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 72bb51e00c..2e0cade8c5 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -36,25 +36,20 @@
#include "mpvcore/av_opts.h"
#include "ad.h"
-#include "audio/reorder_ch.h"
#include "audio/fmt-conversion.h"
-#include "compat/mpbswap.h"
#include "compat/libav.h"
struct priv {
AVCodecContext *avctx;
AVFrame *avframe;
- uint8_t *output;
- uint8_t *output_packed; // used by deplanarize to store packed audio samples
- int output_left;
- int unitsize;
+ struct mp_audio frame;
bool force_channel_map;
struct demux_packet *packet;
};
static void uninit(sh_audio_t *sh);
-static int decode_audio(sh_audio_t *sh,unsigned char *buffer,int minlen,int maxlen);
+static int decode_new_packet(struct sh_audio *sh);
#define OPT_BASE_STRUCT struct MPOpts
@@ -138,22 +133,21 @@ static int preinit(sh_audio_t *sh)
return 1;
}
-/* Prefer playing audio with the samplerate given in container data
- * if available, but take number the number of channels and sample format
- * from the codec, since if the codec isn't using the correct values for
- * those everything breaks anyway.
- */
-static int setup_format(sh_audio_t *sh_audio,
- const AVCodecContext *lavc_context)
+static int setup_format(sh_audio_t *sh_audio)
{
struct priv *priv = sh_audio->context;
- int sample_format =
- af_from_avformat(av_get_packed_sample_fmt(lavc_context->sample_fmt));
- int samplerate = lavc_context->sample_rate;
- // If not set, try container samplerate
+ AVCodecContext *lavc_context = priv->avctx;
+
+ int sample_format = af_from_avformat(lavc_context->sample_fmt);
+ if (!sample_format)
+ return -1;
+
+ int samplerate = lavc_context->sample_rate;
if (!samplerate && sh_audio->wf) {
+ // If not set, try container samplerate.
+ // (Maybe this can't happen, and it's an artifact from the past.)
samplerate = sh_audio->wf->nSamplesPerSec;
- mp_tmsg(MSGT_DECAUDIO, MSGL_V, "ad_lavc: using container rate.\n");
+ mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "ad_lavc: using container rate.\n");
}
struct mp_chmap lavc_chmap;
@@ -166,14 +160,9 @@ static int setup_format(sh_audio_t *sh_audio,
lavc_chmap = sh_audio->channels;
}
- if (!mp_chmap_equals(&lavc_chmap, &sh_audio->channels) ||
- samplerate != sh_audio->samplerate ||
- sample_format != sh_audio->sample_format) {
- sh_audio->channels = lavc_chmap;
- sh_audio->samplerate = samplerate;
- sh_audio->sample_format = sample_format;
- return 1;
- }
+ sh_audio->channels = lavc_chmap;
+ sh_audio->samplerate = samplerate;
+ sh_audio->sample_format = sample_format;
return 0;
}
@@ -273,15 +262,12 @@ static int init(sh_audio_t *sh_audio, const char *decoder)
mp_msg(MSGT_DECAUDIO, MSGL_V, "INFO: libavcodec \"%s\" init OK!\n",
lavc_codec->name);
- // Decode at least 1 byte: (to get header filled)
- for (int tries = 0;;) {
- int x = decode_audio(sh_audio, sh_audio->a_buffer, 1,
- sh_audio->a_buffer_size);
- if (x > 0) {
- sh_audio->a_buffer_len = x;
+ // Decode at least 1 sample: (to get header filled)
+ for (int tries = 1; ; tries++) {
+ int x = decode_new_packet(sh_audio);
+ if (x >= 0 && ctx->frame.samples > 0)
break;
- }
- if (++tries >= 5) {
+ if (tries >= 5) {
mp_msg(MSGT_DECAUDIO, MSGL_ERR,
"ad_lavc: initial decode failed\n");
uninit(sh_audio);
@@ -293,12 +279,6 @@ static int init(sh_audio_t *sh_audio, const char *decoder)
if (sh_audio->wf && sh_audio->wf->nAvgBytesPerSec)
sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
- int af_sample_fmt =
- af_from_avformat(av_get_packed_sample_fmt(lavc_context->sample_fmt));
- if (af_sample_fmt == AF_FORMAT_UNKNOWN) {
- uninit(sh_audio);
- return 0;
- }
return 1;
}
@@ -326,7 +306,7 @@ static int control(sh_audio_t *sh, int cmd, void *arg)
switch (cmd) {
case ADCTRL_RESYNC_STREAM:
avcodec_flush_buffers(ctx->avctx);
- ctx->output_left = 0;
+ ctx->frame.samples = 0;
talloc_free(ctx->packet);
ctx->packet = NULL;
return CONTROL_TRUE;
@@ -334,29 +314,13 @@ static int control(sh_audio_t *sh, int cmd, void *arg)
return CONTROL_UNKNOWN;
}
-static av_always_inline void deplanarize(struct sh_audio *sh)
-{
- struct priv *priv = sh->context;
-
- uint8_t **planes = priv->avframe->extended_data;
- size_t bps = av_get_bytes_per_sample(priv->avctx->sample_fmt);
- size_t nb_samples = priv->avframe->nb_samples;
- size_t channels = priv->avctx->channels;
- size_t size = bps * nb_samples * channels;
-
- if (talloc_get_size(priv->output_packed) != size)
- priv->output_packed =
- talloc_realloc_size(priv, priv->output_packed, size);
-
- reorder_to_packed(priv->output_packed, planes, bps, channels, nb_samples);
-
- priv->output = priv->output_packed;
-}
-
static int decode_new_packet(struct sh_audio *sh)
{
struct priv *priv = sh->context;
AVCodecContext *avctx = priv->avctx;
+
+ priv->frame.samples = 0;
+
struct demux_packet *mpkt = priv->packet;
if (!mpkt)
mpkt = demux_read_packet(sh->gsh);
@@ -372,7 +336,7 @@ static int decode_new_packet(struct sh_audio *sh)
if (mpkt->pts != MP_NOPTS_VALUE) {
sh->pts = mpkt->pts;
- sh->pts_bytes = 0;
+ sh->pts_offset = 0;
}
int got_frame = 0;
int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt);
@@ -397,58 +361,39 @@ static int decode_new_packet(struct sh_audio *sh)
}
if (!got_frame)
return 0;
- uint64_t unitsize = (uint64_t)av_get_bytes_per_sample(avctx->sample_fmt) *
- avctx->channels;
- if (unitsize > 100000)
- abort();
- priv->unitsize = unitsize;
- uint64_t output_left = unitsize * priv->avframe->nb_samples;
- if (output_left > 500000000)
- abort();
- priv->output_left = output_left;
- if (av_sample_fmt_is_planar(avctx->sample_fmt) && avctx->channels > 1) {
- deplanarize(sh);
- } else {
- priv->output = priv->avframe->data[0];
- }
- mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", in_len,
- priv->output_left);
+
+ if (setup_format(sh) < 0)
+ return -1;
+
+ priv->frame.samples = priv->avframe->nb_samples;
+ mp_audio_set_format(&priv->frame, sh->sample_format);
+ mp_audio_set_channels(&priv->frame, &sh->channels);
+ priv->frame.rate = sh->samplerate;
+ for (int n = 0; n < priv->frame.num_planes; n++)
+ priv->frame.planes[n] = priv->avframe->data[n];
+
+ mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d samples\n", in_len,
+ priv->frame.samples);
return 0;
}
-
-static int decode_audio(sh_audio_t *sh_audio, unsigned char *buf, int minlen,
- int maxlen)
+static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen)
{
- struct priv *priv = sh_audio->context;
- AVCodecContext *avctx = priv->avctx;
+ struct priv *priv = sh->context;
- int len = -1;
- while (len < minlen) {
- if (!priv->output_left) {
- if (decode_new_packet(sh_audio) < 0)
- break;
- continue;
- }
- if (setup_format(sh_audio, avctx))
- return len;
- int size = (minlen - len + priv->unitsize - 1);
- size -= size % priv->unitsize;
- size = FFMIN(size, priv->output_left);
- if (size > maxlen)
- abort();
- memcpy(buf, priv->output, size);
- priv->output += size;
- priv->output_left -= size;
- if (len < 0)
- len = size;
- else
- len += size;
- buf += size;
- maxlen -= size;
- sh_audio->pts_bytes += size;
+ if (!priv->frame.samples) {
+ if (decode_new_packet(sh) < 0)
+ return -1;
}
- return len;
+
+ if (!mp_audio_config_equals(buffer, &priv->frame))
+ return 0;
+
+ buffer->samples = MPMIN(priv->frame.samples, maxlen);
+ mp_audio_copy(buffer, 0, &priv->frame, 0, buffer->samples);
+ mp_audio_skip_samples(&priv->frame, buffer->samples);
+ sh->pts_offset += buffer->samples;
+ return 0;
}
static void add_decoders(struct mp_decoder_list *list)