From c522d0dfbd9b9663c4e084261a353ee45991fd86 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 18 Jan 2017 10:19:29 +0100 Subject: ad_spdif: fix obscure cases of AC3 passthrough Apparently you set the native sample rate when passing through AC3. This fixes passthrough with 44100 Hz AC3. Avoid opening a decoder for this and only open the parser. (Hopefully DTS will also support this some time in the future or so - having to open a decoder just to get the profile is dumb.) --- audio/decode/ad_spdif.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'audio/decode') diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 5ab76e677a..775834ecba 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -93,13 +93,34 @@ static int init(struct dec_audio *da, const char *decoder) return spdif_ctx->codec_id != AV_CODEC_ID_NONE; } -static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt) +static void determine_codec_params(struct dec_audio *da, AVPacket *pkt, + int *out_profile, int *out_rate) { struct spdifContext *spdif_ctx = da->priv; int profile = FF_PROFILE_UNKNOWN; AVCodecContext *ctx = NULL; AVFrame *frame = NULL; + AVCodecParserContext *parser = av_parser_init(spdif_ctx->codec_id); + if (parser) { + // Don't make it wait for the next frame. + parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + + ctx = avcodec_alloc_context3(NULL); + + uint8_t *d = NULL; + int s = 0; + av_parser_parse2(parser, ctx, &d, &s, pkt->data, pkt->size, 0, 0, 0); + *out_profile = profile = ctx->profile; + *out_rate = ctx->sample_rate; + + av_free(ctx); + av_parser_close(parser); + } + + if (profile != FF_PROFILE_UNKNOWN || spdif_ctx->codec_id != AV_CODEC_ID_DTS) + return; + AVCodec *codec = avcodec_find_decoder(spdif_ctx->codec_id); if (!codec) goto done; @@ -123,7 +144,8 @@ static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt) if (avcodec_receive_frame(ctx, frame) < 0) goto done; - profile = ctx->profile; + *out_profile = profile = ctx->profile; + *out_rate = ctx->sample_rate; done: av_frame_free(&frame); @@ -133,8 +155,6 @@ done: if (profile == FF_PROFILE_UNKNOWN) MP_WARN(da, "Failed to parse codec profile.\n"); - - return profile; } static int init_filter(struct dec_audio *da, AVPacket *pkt) @@ -142,8 +162,9 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt) struct spdifContext *spdif_ctx = da->priv; int profile = FF_PROFILE_UNKNOWN; - if (spdif_ctx->codec_id == AV_CODEC_ID_DTS) - profile = determine_codec_profile(da, pkt); + int c_rate = 0; + determine_codec_params(da, pkt, &profile, &c_rate); + MP_VERBOSE(da, "In: profile=%d samplerate=%d\n", profile, c_rate); AVFormatContext *lavf_ctx = avformat_alloc_context(); if (!lavf_ctx) @@ -189,7 +210,7 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt) break; case AV_CODEC_ID_AC3: sample_format = AF_FORMAT_S_AC3; - samplerate = 48000; + samplerate = c_rate > 0 ? c_rate : 48000; num_channels = 2; break; case AV_CODEC_ID_DTS: { -- cgit v1.2.3