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.)
This commit is contained in:
wm4 2017-01-18 10:19:29 +01:00
parent da8011c5df
commit c522d0dfbd
1 changed files with 28 additions and 7 deletions

View File

@ -93,13 +93,34 @@ static int init(struct dec_audio *da, const char *decoder)
return spdif_ctx->codec_id != AV_CODEC_ID_NONE; 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; struct spdifContext *spdif_ctx = da->priv;
int profile = FF_PROFILE_UNKNOWN; int profile = FF_PROFILE_UNKNOWN;
AVCodecContext *ctx = NULL; AVCodecContext *ctx = NULL;
AVFrame *frame = 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); AVCodec *codec = avcodec_find_decoder(spdif_ctx->codec_id);
if (!codec) if (!codec)
goto done; goto done;
@ -123,7 +144,8 @@ static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt)
if (avcodec_receive_frame(ctx, frame) < 0) if (avcodec_receive_frame(ctx, frame) < 0)
goto done; goto done;
profile = ctx->profile; *out_profile = profile = ctx->profile;
*out_rate = ctx->sample_rate;
done: done:
av_frame_free(&frame); av_frame_free(&frame);
@ -133,8 +155,6 @@ done:
if (profile == FF_PROFILE_UNKNOWN) if (profile == FF_PROFILE_UNKNOWN)
MP_WARN(da, "Failed to parse codec profile.\n"); MP_WARN(da, "Failed to parse codec profile.\n");
return profile;
} }
static int init_filter(struct dec_audio *da, AVPacket *pkt) 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; struct spdifContext *spdif_ctx = da->priv;
int profile = FF_PROFILE_UNKNOWN; int profile = FF_PROFILE_UNKNOWN;
if (spdif_ctx->codec_id == AV_CODEC_ID_DTS) int c_rate = 0;
profile = determine_codec_profile(da, pkt); 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(); AVFormatContext *lavf_ctx = avformat_alloc_context();
if (!lavf_ctx) if (!lavf_ctx)
@ -189,7 +210,7 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
break; break;
case AV_CODEC_ID_AC3: case AV_CODEC_ID_AC3:
sample_format = AF_FORMAT_S_AC3; sample_format = AF_FORMAT_S_AC3;
samplerate = 48000; samplerate = c_rate > 0 ? c_rate : 48000;
num_channels = 2; num_channels = 2;
break; break;
case AV_CODEC_ID_DTS: { case AV_CODEC_ID_DTS: {