@@ -81,7 +81,6 @@ void setDefaultChannelLayout(
81
81
AVChannelLayout channel_layout;
82
82
av_channel_layout_default (&channel_layout, numChannels);
83
83
avCodecContext->ch_layout = channel_layout;
84
-
85
84
#else
86
85
uint64_t channel_layout = av_get_default_channel_layout (numChannels);
87
86
avCodecContext->channel_layout = channel_layout;
@@ -106,32 +105,79 @@ void setChannelLayout(
106
105
#endif
107
106
}
108
107
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
109
144
void setChannelLayout (
110
145
UniqueAVFrame& dstAVFrame,
111
- const UniqueAVFrame& srcAVFrame) {
146
+ const UniqueAVFrame& srcAVFrame,
147
+ int desiredNumChannels) {
112
148
#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));
114
156
#else
115
- dstAVFrame->channel_layout = srcAVFrame->channel_layout ;
157
+ dstAVFrame->channel_layout =
158
+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
159
+ dstAVFrame->channels = desiredNumChannels;
116
160
#endif
117
161
}
118
162
119
163
SwrContext* createSwrContext (
120
- UniqueAVCodecContext& avCodecContext,
121
164
AVSampleFormat sourceSampleFormat,
122
165
AVSampleFormat desiredSampleFormat,
123
166
int sourceSampleRate,
124
- int desiredSampleRate) {
167
+ int desiredSampleRate,
168
+ const UniqueAVFrame& srcAVFrame,
169
+ int desiredNumChannels) {
125
170
SwrContext* swrContext = nullptr ;
126
171
int status = AVSUCCESS;
127
172
#if LIBAVFILTER_VERSION_MAJOR > 7 // FFmpeg > 4
128
- AVChannelLayout layout = avCodecContext->ch_layout ;
173
+ AVChannelLayout desiredLayout =
174
+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
129
175
status = swr_alloc_set_opts2 (
130
176
&swrContext,
131
- &layout ,
177
+ &desiredLayout ,
132
178
desiredSampleFormat,
133
179
desiredSampleRate,
134
- &layout ,
180
+ &srcAVFrame-> ch_layout ,
135
181
sourceSampleFormat,
136
182
sourceSampleRate,
137
183
0 ,
@@ -142,13 +188,14 @@ SwrContext* createSwrContext(
142
188
" Couldn't create SwrContext: " ,
143
189
getFFMPEGErrorStringFromErrorCode (status));
144
190
#else
145
- int64_t layout = static_cast <int64_t >(avCodecContext->channel_layout );
191
+ int64_t desiredLayout =
192
+ getDesiredChannelLayout (desiredNumChannels, srcAVFrame);
146
193
swrContext = swr_alloc_set_opts (
147
194
nullptr ,
148
- layout ,
195
+ desiredLayout ,
149
196
desiredSampleFormat,
150
197
desiredSampleRate,
151
- layout ,
198
+ srcAVFrame-> channel_layout ,
152
199
sourceSampleFormat,
153
200
sourceSampleRate,
154
201
0 ,
@@ -167,20 +214,21 @@ SwrContext* createSwrContext(
167
214
return swrContext;
168
215
}
169
216
170
- UniqueAVFrame convertAudioAVFrameSampleFormatAndSampleRate (
217
+ UniqueAVFrame convertAudioAVFrameSamples (
171
218
const UniqueSwrContext& swrContext,
172
219
const UniqueAVFrame& srcAVFrame,
173
220
AVSampleFormat desiredSampleFormat,
174
- int sourceSampleRate ,
175
- int desiredSampleRate ) {
221
+ int desiredSampleRate ,
222
+ int desiredNumChannels ) {
176
223
UniqueAVFrame convertedAVFrame (av_frame_alloc ());
177
224
TORCH_CHECK (
178
225
convertedAVFrame,
179
226
" Could not allocate frame for sample format conversion." );
180
227
181
- setChannelLayout (convertedAVFrame, srcAVFrame);
182
228
convertedAVFrame->format = static_cast <int >(desiredSampleFormat);
229
+
183
230
convertedAVFrame->sample_rate = desiredSampleRate;
231
+ int sourceSampleRate = srcAVFrame->sample_rate ;
184
232
if (sourceSampleRate != desiredSampleRate) {
185
233
// Note that this is an upper bound on the number of output samples.
186
234
// `swr_convert()` will likely not fill convertedAVFrame with that many
@@ -200,6 +248,8 @@ UniqueAVFrame convertAudioAVFrameSampleFormatAndSampleRate(
200
248
convertedAVFrame->nb_samples = srcAVFrame->nb_samples ;
201
249
}
202
250
251
+ setChannelLayout (convertedAVFrame, srcAVFrame, desiredNumChannels);
252
+
203
253
auto status = av_frame_get_buffer (convertedAVFrame.get (), 0 );
204
254
TORCH_CHECK (
205
255
status == AVSUCCESS,
0 commit comments