From 5fd8a1e04c725329435e3bead5f11ee3ffb9f1c1 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 10 Nov 2014 22:01:23 +0100 Subject: audio: make decoders output refcounted frames This rewrites the audio decode loop to some degree. Audio filters don't do refcounted frames yet, so af.c contains a hacky "emulation". Remove some of the weird heuristic-heavy code in dec_audio.c. Instead of estimating how much audio we need to filter, we always filter full frames. Maybe this should be adjusted later: in case filtering increases the volume of the audio data, we should try not to buffer too much filter output by reducing the input that is fed at once. For ad_spdif.c and ad_mpg123.c, we don't avoid extra copying yet - it doesn't seem worth the trouble. --- audio/decode/ad_lavc.c | 92 ++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 55 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 31ac5f71ba..8825172123 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -73,55 +73,6 @@ const struct m_sub_options ad_lavc_conf = { }, }; -static void set_data_from_avframe(struct dec_audio *da) -{ - struct priv *priv = da->priv; - AVCodecContext *lavc_context = priv->avctx; - - // Note: invalid parameters are rejected by dec_audio.c - - int fmt = lavc_context->sample_fmt; - mp_audio_set_format(&da->decoded, af_from_avformat(fmt)); - if (!da->decoded.format) - MP_FATAL(da, "unsupported lavc format %s", av_get_sample_fmt_name(fmt)); - - da->decoded.rate = lavc_context->sample_rate; - - struct mp_chmap lavc_chmap; - mp_chmap_from_lavc(&lavc_chmap, lavc_context->channel_layout); - // No channel layout or layout disagrees with channel count - if (lavc_chmap.num != lavc_context->channels) - mp_chmap_from_channels(&lavc_chmap, lavc_context->channels); - if (priv->force_channel_map) { - struct sh_audio *sh_audio = da->header->audio; - if (lavc_chmap.num == sh_audio->channels.num) - lavc_chmap = sh_audio->channels; - } - mp_audio_set_channels(&da->decoded, &lavc_chmap); - - da->decoded.samples = priv->avframe->nb_samples; - for (int n = 0; n < da->decoded.num_planes; n++) - da->decoded.planes[n] = priv->avframe->data[n]; - -#if HAVE_AVFRAME_SKIP_SAMPLES - AVFrameSideData *sd = - av_frame_get_side_data(priv->avframe, AV_FRAME_DATA_SKIP_SAMPLES); - if (sd && sd->size >= 10) { - char *d = sd->data; - priv->skip_samples += AV_RL32(d + 0); - uint32_t pad = AV_RL32(d + 4); - uint32_t skip = MPMIN(priv->skip_samples, da->decoded.samples); - if (skip) { - mp_audio_skip_samples(&da->decoded, skip); - da->pts_offset += skip; - priv->skip_samples -= skip; - } - if (pad <= da->decoded.samples) - da->decoded.samples -= pad; - } -#endif -} - static int init(struct dec_audio *da, const char *decoder) { struct MPOpts *mpopts = da->opts; @@ -222,7 +173,6 @@ static int control(struct dec_audio *da, int cmd, void *arg) switch (cmd) { case ADCTRL_RESET: avcodec_flush_buffers(ctx->avctx); - mp_audio_set_null_data(&da->decoded); talloc_free(ctx->packet); ctx->packet = NULL; ctx->skip_samples = 0; @@ -231,13 +181,11 @@ static int control(struct dec_audio *da, int cmd, void *arg) return CONTROL_UNKNOWN; } -static int decode_packet(struct dec_audio *da) +static int decode_packet(struct dec_audio *da, struct mp_audio **out) { struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; - mp_audio_set_null_data(&da->decoded); - struct demux_packet *mpkt = priv->packet; if (!mpkt) { if (demux_read_packet_async(da->header, &mpkt) == 0) @@ -290,9 +238,43 @@ static int decode_packet(struct dec_audio *da) da->pts_offset = 0; } - set_data_from_avframe(da); + struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe); + if (!mpframe) + return AD_ERR; + + struct mp_chmap lavc_chmap = mpframe->channels; + if (lavc_chmap.num != avctx->channels) + mp_chmap_from_channels(&lavc_chmap, avctx->channels); + if (priv->force_channel_map) { + struct sh_audio *sh_audio = da->header->audio; + if (lavc_chmap.num == sh_audio->channels.num) + lavc_chmap = sh_audio->channels; + } + mp_audio_set_channels(mpframe, &lavc_chmap); + +#if HAVE_AVFRAME_SKIP_SAMPLES + AVFrameSideData *sd = + av_frame_get_side_data(priv->avframe, AV_FRAME_DATA_SKIP_SAMPLES); + if (sd && sd->size >= 10) { + char *d = sd->data; + priv->skip_samples += AV_RL32(d + 0); + uint32_t pad = AV_RL32(d + 4); + uint32_t skip = MPMIN(priv->skip_samples, mpframe->samples); + if (skip) { + mp_audio_skip_samples(mpframe, skip); + da->pts_offset += skip; + priv->skip_samples -= skip; + } + if (pad <= mpframe->samples) + mpframe->samples -= pad; + } +#endif + + *out = mpframe; + + av_frame_unref(priv->avframe); - MP_DBG(da, "Decoded %d -> %d samples\n", in_len, da->decoded.samples); + MP_DBG(da, "Decoded %d -> %d samples\n", in_len, mpframe->samples); return 0; } -- cgit v1.2.3