I googled quite a bit to find patches for ffmpeg that will allow conversion from 5.1 audio channels into stereo. This is necessary if you want to convert all sorts of videos into FLVs with mp3 audio channel (eg. if you operate a video streaming service), since mp3 supports only mono and stereo channels.
Here're the patches:
Unfortunately neither of these two are as sophisticated as the algorithms in various media players (like Quicktime, VLC, Mplayer, etc.).
P.S.: I'm aware of the fact that Flash Player supports AAC audio codec (and H.264 video codec), but only since v9.0.115 (see the
respective article in Adobe's Wiki). There're still many computers (at the moment of writing) that run a lower version of the Flash Player. So depending on your goal (on percentage of supported clients), you might want to choose to encode your FLVs with H.264 and AAC (which supports 5.1 audio).
Comments
Link change
Anyway, thanks for posting this. Just tried this patch, and it works brilliantly.
Re: Link change
The world changes
diff -rupN ffmpeg/libavcodec/resample.c ffmpegMod/libavcodec/resample.c
--- ffmpeg/libavcodec/resample.c 2011-05-01 03:31:32.897900334 -0400
+++ ffmpegMod/libavcodec/resample.c 2011-05-01 03:32:03.097900335 -0400
@@ -53,6 +53,14 @@ struct ReSampleContext {
unsigned buffer_size[2]; ///< sizes of allocated buffers
};
+static short clip_short(int v) {
+ if (v < -32768)
+ v = -32768;
+ else if (v > 32767)
+ v = 32767;
+ return (short) v;
+}
+
/* n1: number of samples */
static void stereo_to_mono(short *output, short *input, int n1)
{
@@ -104,14 +112,43 @@ static void mono_to_stereo(short *output
}
}
-/* XXX: should use more abstract 'N' channels system */
-static void stereo_split(short *output1, short *output2, short *input, int n)
-{
+/* XXX: make this better. channels will always be >= 2.
+ - Left = front_left + rear_gain * rear_left + center_gain * center
+ - Right = front_right + rear_gain * rear_right + center_gain * center
+ where rear_gain is usually around 0.5-1.0 and center_gain is almost always 0.7 (-3 dB) if I recall correctly. */
+static void multi_to_stereo_split(short *output1, short *output2, short *input, int n, int channels) {
int i;
+ short l,r;
for(i=0;i<n;i++) {
- *output1++ = *input++;
- *output2++ = *input++;
+ if (channels == 2) {
+ /* simple stereo to stereo. Input is: l, r */
+ l = input[0];
+ r = input[1];
+ } else if (channels == 6) {
+ /* 5.1 to stereo. l, c, r, ls, rs, sw */
+ int fl,fr,c,rl,rr,lfe;
+ fl = input[0];
+ c = input[1];
+ fr = input[2];
+ rl = input[3];
+ rr = input[4];
+ lfe = input[5];
+
+ l = clip_short(fl + (0.5 * rl) + (0.7 * c));
+ r = clip_short(fr + (0.5 * rr) + (0.7 * c));
+ } else {
+ /* channels must be 3-5, or >= 7. l, c, r, ? */
+ l = input[0];
+ r = input[2];
+ }
+
+ /* output l & r. */
+ *output1++ = l;
+ *output2++ = r;
+
+ /* increment input. */
+ input += channels;
}
}
@@ -151,9 +188,9 @@ ReSampleContext *av_audio_resample_init(
{
ReSampleContext *s;
- if ( input_channels > 2)
+ if ((input_channels > 2) && (input_channels != 6))
{
- av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.\n");
+ av_log(NULL, AV_LOG_ERROR, "Resampling with input channels other than 1,2, or 6 is unsupported.\n");
return NULL;
}
@@ -302,7 +339,7 @@ int audio_resample(ReSampleContext *s, s
} else if (s->output_channels >= 2) {
buftmp3[0] = bufout[0];
buftmp3[1] = bufout[1];
- stereo_split(buftmp2[0], buftmp2[1], input, nb_samples);
+ multi_to_stereo_split(buftmp2[0], buftmp2[1], input, nb_samples, s->input_channels);
} else {
buftmp3[0] = output;
memcpy(buftmp2[0], input, nb_samples*sizeof(short));
Re: The world changes
Not sure, and good point
I do want to thank you, while I'm here. Without your post, and the links to the original patches I'd never have been able to make the new one. Considering that I know absolutely nothing about audio, let alone that tidbit about the proper way to calculate left and right on stereo with the correct gains, it was actually pretty cool, ^_^. All I did was seek, cut and paste... yet it was still fun, and made me feel accomplished, ^_^.... *squees like the anime fanboy I am*
Have a good evening, and one last time... Thanks. If it wasn't for you keeping this post, and keeping these links up to date I'd still be figuratively beating my head against a wall, trying every ffmpeg switch combination known to man in an attempt to get it to work. ^_^
Re: Not sure, and good point
Sync