summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-01-18 10:19:29 +0100
committerwm4 <wm4@nowhere>2017-01-18 10:22:28 +0100
commitc522d0dfbd9b9663c4e084261a353ee45991fd86 (patch)
tree15f704cdf1b218ba604b717ae2bccac8de1bbc11
parentda8011c5df76ea79d939aaa4f6f4ddd927f51b5d (diff)
downloadmpv-c522d0dfbd9b9663c4e084261a353ee45991fd86.tar.bz2
mpv-c522d0dfbd9b9663c4e084261a353ee45991fd86.tar.xz
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.)
-rw-r--r--audio/decode/ad_spdif.c35
1 files changed, 28 insertions, 7 deletions
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: {