@@ -81,7 +81,6 @@ void setDefaultChannelLayout(
8181 AVChannelLayout channel_layout;
8282 av_channel_layout_default (&channel_layout, numChannels);
8383 avCodecContext->ch_layout = channel_layout;
84-
8584#else
8685 uint64_t channel_layout = av_get_default_channel_layout (numChannels);
8786 avCodecContext->channel_layout = channel_layout;
@@ -106,32 +105,79 @@ void setChannelLayout(
106105#endif
107106}
108107
108+ namespace {
109+ #if LIBAVFILTER_VERSION_MAJOR > 7 // FFmpeg > 4
110+
111+ // Returns:
112+ // - the srcAVFrame's channel layout if srcAVFrame has desiredNumChannels
113+ // - the default channel layout with desiredNumChannels otherwise.
114+ AVChannelLayout getDesiredChannelLayout (
115+ int desiredNumChannels,
116+ const UniqueAVFrame& srcAVFrame) {
117+ AVChannelLayout desiredLayout;
118+ if (desiredNumChannels == getNumChannels (srcAVFrame)) {
119+ desiredLayout = srcAVFrame->ch_layout ;
120+ } else {
121+ av_channel_layout_default (&desiredLayout, desiredNumChannels);
122+ }
123+ return desiredLayout;
124+ }
125+
126+ #else
127+
128+ // Same as above
129+ int64_t getDesiredChannelLayout (
130+ int desiredNumChannels,
131+ const UniqueAVFrame& srcAVFrame) {
132+ int64_t desiredLayout;
133+ if (desiredNumChannels == getNumChannels (srcAVFrame)) {
134+ desiredLayout = srcAVFrame->channel_layout ;
135+ } else {
136+ desiredLayout = av_get_default_channel_layout (desiredNumChannels);
137+ }
138+ return desiredLayout;
139+ }
140+ #endif
141+ } // namespace
142+
143+ // Sets dstAVFrame' channel layout to getDesiredChannelLayout(): see doc above
109144void setChannelLayout (
110145 UniqueAVFrame& dstAVFrame,
111- const UniqueAVFrame& srcAVFrame) {
146+ const UniqueAVFrame& srcAVFrame,
147+ int desiredNumChannels) {
112148#if LIBAVFILTER_VERSION_MAJOR > 7 // FFmpeg > 4
113- dstAVFrame->ch_layout = srcAVFrame->ch_layout ;
149+ AVChannelLayout desiredLayout =
150+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
151+ auto status = av_channel_layout_copy (&dstAVFrame->ch_layout , &desiredLayout);
152+ TORCH_CHECK (
153+ status == AVSUCCESS,
154+ " Couldn't copy channel layout to avFrame: " ,
155+ getFFMPEGErrorStringFromErrorCode (status));
114156#else
115- dstAVFrame->channel_layout = srcAVFrame->channel_layout ;
157+ dstAVFrame->channel_layout =
158+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
159+ dstAVFrame->channels = desiredNumChannels;
116160#endif
117161}
118162
119163SwrContext* createSwrContext (
120- UniqueAVCodecContext& avCodecContext,
121164 AVSampleFormat sourceSampleFormat,
122165 AVSampleFormat desiredSampleFormat,
123166 int sourceSampleRate,
124- int desiredSampleRate) {
167+ int desiredSampleRate,
168+ const UniqueAVFrame& srcAVFrame,
169+ int desiredNumChannels) {
125170 SwrContext* swrContext = nullptr ;
126171 int status = AVSUCCESS;
127172#if LIBAVFILTER_VERSION_MAJOR > 7 // FFmpeg > 4
128- AVChannelLayout layout = avCodecContext->ch_layout ;
173+ AVChannelLayout desiredLayout =
174+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
129175 status = swr_alloc_set_opts2 (
130176 &swrContext,
131- &layout ,
177+ &desiredLayout ,
132178 desiredSampleFormat,
133179 desiredSampleRate,
134- &layout ,
180+ &srcAVFrame-> ch_layout ,
135181 sourceSampleFormat,
136182 sourceSampleRate,
137183 0 ,
@@ -142,13 +188,14 @@ SwrContext* createSwrContext(
142188 " Couldn't create SwrContext: " ,
143189 getFFMPEGErrorStringFromErrorCode (status));
144190#else
145- int64_t layout = static_cast <int64_t >(avCodecContext->channel_layout );
191+ int64_t desiredLayout =
192+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
146193 swrContext = swr_alloc_set_opts (
147194 nullptr ,
148- layout ,
195+ desiredLayout ,
149196 desiredSampleFormat,
150197 desiredSampleRate,
151- layout ,
198+ srcAVFrame-> channel_layout ,
152199 sourceSampleFormat,
153200 sourceSampleRate,
154201 0 ,
@@ -167,20 +214,21 @@ SwrContext* createSwrContext(
167214 return swrContext;
168215}
169216
170- UniqueAVFrame convertAudioAVFrameSampleFormatAndSampleRate (
217+ UniqueAVFrame convertAudioAVFrameSamples (
171218 const UniqueSwrContext& swrContext,
172219 const UniqueAVFrame& srcAVFrame,
173220 AVSampleFormat desiredSampleFormat,
174- int sourceSampleRate ,
175- int desiredSampleRate ) {
221+ int desiredSampleRate ,
222+ int desiredNumChannels ) {
176223 UniqueAVFrame convertedAVFrame (av_frame_alloc ());
177224 TORCH_CHECK (
178225 convertedAVFrame,
179226 " Could not allocate frame for sample format conversion." );
180227
181- setChannelLayout (convertedAVFrame, srcAVFrame);
182228 convertedAVFrame->format = static_cast <int >(desiredSampleFormat);
229+
183230 convertedAVFrame->sample_rate = desiredSampleRate;
231+ int sourceSampleRate = srcAVFrame->sample_rate ;
184232 if (sourceSampleRate != desiredSampleRate) {
185233 // Note that this is an upper bound on the number of output samples.
186234 // `swr_convert()` will likely not fill convertedAVFrame with that many
@@ -200,6 +248,8 @@ UniqueAVFrame convertAudioAVFrameSampleFormatAndSampleRate(
200248 convertedAVFrame->nb_samples = srcAVFrame->nb_samples ;
201249 }
202250
251+ setChannelLayout (convertedAVFrame, srcAVFrame, desiredNumChannels);
252+
203253 auto status = av_frame_get_buffer (convertedAVFrame.get (), 0 );
204254 TORCH_CHECK (
205255 status == AVSUCCESS,
0 commit comments