From 30031edce3bb79051a125183c8dc152ba4e78e66 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 19 Jan 2016 22:24:26 +0100 Subject: audio: move direct packet reading from decoders to common code Another bit of preparation. --- audio/decode/ad_lavc.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 7e5c8d5aa5..f7304353af 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -42,7 +42,6 @@ struct priv { AVFrame *avframe; struct mp_audio frame; bool force_channel_map; - struct demux_packet *packet; uint32_t skip_samples; }; @@ -165,27 +164,18 @@ static int control(struct dec_audio *da, int cmd, void *arg) switch (cmd) { case ADCTRL_RESET: avcodec_flush_buffers(ctx->avctx); - talloc_free(ctx->packet); - ctx->packet = NULL; ctx->skip_samples = 0; return CONTROL_TRUE; } return CONTROL_UNKNOWN; } -static int decode_packet(struct dec_audio *da, struct mp_audio **out) +static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, + struct mp_audio **out) { struct priv *priv = da->priv; AVCodecContext *avctx = priv->avctx; - struct demux_packet *mpkt = priv->packet; - if (!mpkt) { - if (demux_read_packet_async(da->header, &mpkt) == 0) - return AD_WAIT; - } - - priv->packet = talloc_steal(priv, mpkt); - int in_len = mpkt ? mpkt->len : 0; AVPacket pkt; @@ -203,13 +193,11 @@ static int decode_packet(struct dec_audio *da, struct mp_audio **out) 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)) + if (ret == AVERROR(EAGAIN)) { + mpkt->len = 0; return AD_OK; + } } if (ret < 0) { MP_ERR(da, "Error decoding audio.\n"); -- cgit v1.2.3 From fef8b7984be5a6244612d346bd60d2badd4a2e63 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Jan 2016 22:10:15 +0100 Subject: audio: refactor: work towards unentangling audio decoding and filtering Similar to the video path. dec_audio.c now handles decoding only. It also looks very similar to dec_video.c, and actually contains some of the rewritten code from it. (A further goal might be unifying the decoders, I guess.) High potential for regressions. --- audio/decode/ad_lavc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index f7304353af..3c17d0d9bb 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -196,21 +196,21 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, // LATM may need many packets to find mux info if (ret == AVERROR(EAGAIN)) { mpkt->len = 0; - return AD_OK; + return 0; } } if (ret < 0) { MP_ERR(da, "Error decoding audio.\n"); - return AD_ERR; + return -1; } if (!got_frame) - return mpkt ? AD_OK : AD_EOF; + return 0; double out_pts = mp_pts_from_av(priv->avframe->pkt_pts, NULL); struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe); if (!mpframe) - return AD_ERR; + return -1; struct mp_chmap lavc_chmap = mpframe->channels; if (lavc_chmap.num != avctx->channels) -- cgit v1.2.3 From 6eae6a785c5060587517197ab05f7e19b54972df Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Feb 2016 22:06:58 +0100 Subject: ad_lavc: fix --ad-lavc-threads range The code is shared with the --vd-lavc-threads option, so using 0 for auto-detection just works. But no, this is not useful. Just change it for orthogonality. --- audio/decode/ad_lavc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 3c17d0d9bb..edc9f3c0f0 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -59,7 +59,7 @@ const struct m_sub_options ad_lavc_conf = { .opts = (const m_option_t[]) { OPT_FLOATRANGE("ac3drc", ac3drc, 0, 0, 6), OPT_FLAG("downmix", downmix, 0), - OPT_INTRANGE("threads", threads, 0, 1, 16), + OPT_INTRANGE("threads", threads, 0, 0, 16), OPT_KEYVALUELIST("o", avopts, 0), {0} }, -- cgit v1.2.3 From f2b039da77fc66119d556e575822c2b8d328cdaf Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 15 Feb 2016 20:34:45 +0100 Subject: audio/video: expose codec info as separate field Preparation for the timeline rewrite. The codec will be able to change, the stream header not. --- audio/decode/ad_lavc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index edc9f3c0f0..eeb4526f13 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -77,8 +77,7 @@ static int init(struct dec_audio *da, const char *decoder) struct ad_lavc_params *opts = mpopts->ad_lavc_params; AVCodecContext *lavc_context; AVCodec *lavc_codec; - struct sh_stream *sh = da->header; - struct mp_codec_params *c = sh->codec; + struct mp_codec_params *c = da->codec; struct priv *ctx = talloc_zero(NULL, struct priv); da->priv = ctx; @@ -216,8 +215,8 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (lavc_chmap.num != avctx->channels) mp_chmap_from_channels(&lavc_chmap, avctx->channels); if (priv->force_channel_map) { - if (lavc_chmap.num == da->header->codec->channels.num) - lavc_chmap = da->header->codec->channels; + if (lavc_chmap.num == da->codec->channels.num) + lavc_chmap = da->codec->channels; } mp_audio_set_channels(mpframe, &lavc_chmap); -- cgit v1.2.3 From 65b858f7d34d07a3e11ef22406015b027145b5b6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 22 Feb 2016 13:08:08 +0100 Subject: ad_lavc: interpolate missing timestamps This is actually already done by dec_audio.c. But if AV_FRAME_DATA_SKIP_SAMPLES is applied, this happens too late here. The problem is that this will slice off samples, and make it impossible for later code to reconstruct the timestamp properly. Missing timestamps can still happen with some demuxers, e.g. demux_mkv.c with Opus tracks. (Although libavformat interpolates these itself.) --- audio/decode/ad_lavc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index eeb4526f13..5cd335b44c 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -43,6 +43,7 @@ struct priv { struct mp_audio frame; bool force_channel_map; uint32_t skip_samples; + double next_pts; }; static void uninit(struct dec_audio *da); @@ -138,6 +139,8 @@ static int init(struct dec_audio *da, const char *decoder) return 0; } + ctx->next_pts = MP_NOPTS_VALUE; + return 1; } @@ -164,6 +167,7 @@ static int control(struct dec_audio *da, int cmd, void *arg) case ADCTRL_RESET: avcodec_flush_buffers(ctx->avctx); ctx->skip_samples = 0; + ctx->next_pts = MP_NOPTS_VALUE; return CONTROL_TRUE; } return CONTROL_UNKNOWN; @@ -222,6 +226,11 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, mpframe->pts = out_pts; + if (mpframe->pts == MP_NOPTS_VALUE) + mpframe->pts = priv->next_pts; + if (mpframe->pts != MP_NOPTS_VALUE) + priv->next_pts = mpframe->pts + mpframe->samples / (double)mpframe->rate; + #if HAVE_AVFRAME_SKIP_SAMPLES AVFrameSideData *sd = av_frame_get_side_data(priv->avframe, AV_FRAME_DATA_SKIP_SAMPLES); -- cgit v1.2.3 From d52b2981c0cdc88c6679262f26dd097c2eb4df83 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 22 Feb 2016 19:50:09 +0100 Subject: ad_lavc: move skipping logic out of the HAVE_AVFRAME_SKIP_SAMPLES block --- audio/decode/ad_lavc.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 5cd335b44c..96625cae2f 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -231,25 +231,28 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (mpframe->pts != MP_NOPTS_VALUE) priv->next_pts = mpframe->pts + mpframe->samples / (double)mpframe->rate; + uint32_t pad = 0; + #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); - if (mpframe->pts != MP_NOPTS_VALUE) - mpframe->pts += skip / (double)mpframe->rate; - priv->skip_samples -= skip; - } - if (pad <= mpframe->samples) - mpframe->samples -= pad; + pad = AV_RL32(d + 4); } #endif + uint32_t skip = MPMIN(priv->skip_samples, mpframe->samples); + if (skip) { + mp_audio_skip_samples(mpframe, skip); + if (mpframe->pts != MP_NOPTS_VALUE) + mpframe->pts += skip / (double)mpframe->rate; + priv->skip_samples -= skip; + } + if (pad <= mpframe->samples) + mpframe->samples -= pad; + *out = mpframe; av_frame_unref(priv->avframe); -- cgit v1.2.3 From 289edadb8d28a3a73bf6930306dd2cb9a6777470 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 22 Feb 2016 19:58:11 +0100 Subject: ad_lavc: make sample trimming symmetric to skipping I'm not quite sure what the FFmpeg AV_FRAME_DATA_SKIP_SAMPLES API demands here. The code so far assumed that skipping can be more than a frame, but not trimming. Extend it to trimming too. --- audio/decode/ad_lavc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 96625cae2f..93c297b009 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -42,7 +42,7 @@ struct priv { AVFrame *avframe; struct mp_audio frame; bool force_channel_map; - uint32_t skip_samples; + uint32_t skip_samples, trim_samples; double next_pts; }; @@ -167,6 +167,7 @@ static int control(struct dec_audio *da, int cmd, void *arg) case ADCTRL_RESET: avcodec_flush_buffers(ctx->avctx); ctx->skip_samples = 0; + ctx->trim_samples = 0; ctx->next_pts = MP_NOPTS_VALUE; return CONTROL_TRUE; } @@ -231,15 +232,13 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (mpframe->pts != MP_NOPTS_VALUE) priv->next_pts = mpframe->pts + mpframe->samples / (double)mpframe->rate; - uint32_t pad = 0; - #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); - pad = AV_RL32(d + 4); + priv->trim_samples += AV_RL32(d + 4); } #endif @@ -250,8 +249,11 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, mpframe->pts += skip / (double)mpframe->rate; priv->skip_samples -= skip; } - if (pad <= mpframe->samples) - mpframe->samples -= pad; + uint32_t trim = MPMIN(priv->trim_samples, mpframe->samples); + if (trim) { + mpframe->samples -= trim; + priv->trim_samples -= trim; + } *out = mpframe; -- cgit v1.2.3 From 9ee340c3af5c23c2ac877b6559e11bd70c3052ac Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 22 Feb 2016 20:10:38 +0100 Subject: ad_lavc: skip AVCodecContext.delay samples at beginning Fixes correctness_trimming_nobeeps.opus. One nasty thing is that this mechanism interferes with the container-signalled mechanism with AV_FRAME_DATA_SKIP_SAMPLES. So apply it only if that is apparently not present. It's a mess, and it's still broken in FFmpeg CLI, so I'm sure this will get fucked up later again. --- audio/decode/ad_lavc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 93c297b009..64095b0018 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -43,6 +43,7 @@ struct priv { struct mp_audio frame; bool force_channel_map; uint32_t skip_samples, trim_samples; + bool preroll_done; double next_pts; }; @@ -168,6 +169,7 @@ static int control(struct dec_audio *da, int cmd, void *arg) avcodec_flush_buffers(ctx->avctx); ctx->skip_samples = 0; ctx->trim_samples = 0; + ctx->preroll_done = false; ctx->next_pts = MP_NOPTS_VALUE; return CONTROL_TRUE; } @@ -242,6 +244,13 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, } #endif + if (!priv->preroll_done) { + // Skip only if this isn't already handled by AV_FRAME_DATA_SKIP_SAMPLES. + if (!priv->skip_samples) + priv->skip_samples = avctx->delay; + priv->preroll_done = true; + } + uint32_t skip = MPMIN(priv->skip_samples, mpframe->samples); if (skip) { mp_audio_skip_samples(mpframe, skip); -- cgit v1.2.3 From 7c181e5b9b3e429d3202a6d28264a36cbd7d9699 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 22 Feb 2016 20:13:31 +0100 Subject: audio: make mp_audio_skip_samples() adjust the PTS Slight simplification/cleanup. --- audio/decode/ad_lavc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'audio/decode/ad_lavc.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 64095b0018..c30aff7fd5 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -254,8 +254,6 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, uint32_t skip = MPMIN(priv->skip_samples, mpframe->samples); if (skip) { mp_audio_skip_samples(mpframe, skip); - if (mpframe->pts != MP_NOPTS_VALUE) - mpframe->pts += skip / (double)mpframe->rate; priv->skip_samples -= skip; } uint32_t trim = MPMIN(priv->trim_samples, mpframe->samples); -- cgit v1.2.3