diff --git a/src/media/audio/resampler.cpp b/src/media/audio/resampler.cpp index 6409287a66cc30c6b664ebeb412b8972a5c71391..e5dd554d418ce21b69a61a19f8b2a9eea5ea0dd0 100644 --- a/src/media/audio/resampler.cpp +++ b/src/media/audio/resampler.cpp @@ -44,15 +44,55 @@ void Resampler::reinit(const AVFrame* in, const AVFrame* out) { av_opt_set_int(swrCtx_, "ich", in->channels, 0); - av_opt_set_int(swrCtx_, "icl", av_get_default_channel_layout(in->channels), 0); + av_opt_set_int(swrCtx_, "icl", in->channel_layout, 0); av_opt_set_int(swrCtx_, "isr", in->sample_rate, 0); av_opt_set_sample_fmt(swrCtx_, "isf", static_cast<AVSampleFormat>(in->format), 0); av_opt_set_int(swrCtx_, "och", out->channels, 0); - av_opt_set_int(swrCtx_, "ocl", av_get_default_channel_layout(out->channels), 0); + av_opt_set_int(swrCtx_, "ocl", out->channel_layout, 0); av_opt_set_int(swrCtx_, "osr", out->sample_rate, 0); av_opt_set_sample_fmt(swrCtx_, "osf", static_cast<AVSampleFormat>(out->format), 0); + /** + * Downmixing from 5.1 requires extra setup, since libswresample can't do it automatically + * (not yet implemented). + * + * Source: https://www.atsc.org/wp-content/uploads/2015/03/A52-201212-17.pdf + * Section 7.8.2 for the algorithm + * Tables 5.9 and 5.10 for the coefficients clev and slev + * + * LFE downmixing is optional, so any coefficient can be used, we use +6dB for mono and + * +0dB in each channel for stereo. + */ + if (in->channel_layout == AV_CH_LAYOUT_5POINT1 || in->channels == 6) { + double matrix[out->channels][in->channels]; + if (out->channels == 2) { + // L = 1.0*FL + 0.707*FC + 0.707*BL + 1.0*LFE + matrix[0][0] = 1; + matrix[0][1] = 0; + matrix[0][2] = 0.707; + matrix[0][3] = 1; + matrix[0][4] = 0.707; + matrix[0][5] = 0; + // R = 1.0*FR + 0.707*FC + 0.707*BR + 1.0*LFE + matrix[1][0] = 0; + matrix[1][1] = 1; + matrix[1][2] = 0.707; + matrix[1][3] = 1; + matrix[1][4] = 0; + matrix[1][5] = 0.707; + } else { + // M = 1.0*FL + 1.414*FC + 1.0*FR + 0.707*BL + 0.707*BR + 2.0*LFE + matrix[0][0] = 1; + matrix[0][1] = 1; + matrix[0][2] = 1.414; + matrix[0][3] = 2; + matrix[0][4] = 0.707; + matrix[0][5] = 0.707; + } + swr_set_matrix(swrCtx_, matrix[0], in->channels); + } + swr_init(swrCtx_); ++initCount_; } diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index 75c3a51d05c08b2e5ecd8f743545553201f7adf4..1a0681e494320b3546e7f446a40f336975db0339 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -153,23 +153,7 @@ int MediaDecoder::setupFromAudioData() int MediaDecoder::selectStream(AVMediaType type) { - int idx = -1; - if (type == AVMEDIA_TYPE_AUDIO) { - for (unsigned i = 0; i < inputCtx_->nb_streams; ++ i) { - auto par = inputCtx_->streams[i]->codecpar; - if (par->codec_type != type) - continue; - // NOTE libswresample does not support resampling from Dolby 5.1, so skip over it - if (par->channel_layout == AV_CH_LAYOUT_5POINT1) - continue; - if ((inputDecoder_ = avcodec_find_decoder(par->codec_id))) - idx = i; - } - } else { - // grab the first video stream - idx = av_find_best_stream(inputCtx_, type, -1, -1, &inputDecoder_, 0); - } - return idx; + return av_find_best_stream(inputCtx_, type, -1, -1, &inputDecoder_, 0); } int