No subject

bogus at does.not.exist.com bogus at does.not.exist.com
Tue Aug 25 22:50:44 CEST 2009


const uint8_t vorbis_channel_map[8][8] = {
    { },                        // mono
    { },                        // stereo
    { 0, 2, 1,               }, // L C R
    { },                        // quad
    { 0, 2, 1, 3, 4,         }, // 5.0
    { 0, 2, 1, 4, 5, 3,      }, // 5.1
    { 0, 2, 1, 5, 6, 4, 3    }, // 6.1
    { 0, 2, 1, 6, 7, 4, 5, 3 }  // 7.1
};

what is different from your original patch for 5.1:

const uint8_t vorbis_channel_map[6][6] = {
    { },                  // mono
    { },                  // stereo
    { 0, 2, 1,         }, // L C R
    { },                  // quad
    { 0, 2, 1, 3, 4,   }, // 5.0
    { 0, 2, 1, 5, 3, 4 }  // 5.1
};

But yours works, mine do not. I doesn't make sense to me, since I
created the original wav following that spec: L R C LFE SL SR...

My patch, which is _wrong_, goes attached.

-- 
Lucas Clemente Vella
lvella at gmail.com

--------------030106030503030606010404
Content-Type: text/x-patch;
 name="libvorbis_multichannel_7.1.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="libvorbis_multichannel_7.1.patch"

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index e66691f..692c1d8 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -408,6 +408,7 @@ enum SampleFormat {
 #define CH_LAYOUT_5POINT1           (CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY)
 #define CH_LAYOUT_5POINT0_BACK      (CH_LAYOUT_SURROUND|CH_BACK_LEFT|CH_BACK_RIGHT)
 #define CH_LAYOUT_5POINT1_BACK      (CH_LAYOUT_5POINT0_BACK|CH_LOW_FREQUENCY)
+#define CH_LAYOUT_6POINT1           (CH_LAYOUT_5POINT1|CH_BACK_CENTER)
 #define CH_LAYOUT_7POINT0           (CH_LAYOUT_5POINT0|CH_BACK_LEFT|CH_BACK_RIGHT)
 #define CH_LAYOUT_7POINT1           (CH_LAYOUT_5POINT1|CH_BACK_LEFT|CH_BACK_RIGHT)
 #define CH_LAYOUT_7POINT1_WIDE      (CH_LAYOUT_5POINT1_BACK|\
diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c
index 530db5c..425db12 100644
--- a/libavcodec/libvorbis.c
+++ b/libavcodec/libvorbis.c
@@ -28,6 +28,7 @@
 
 #include "avcodec.h"
 #include "bytestream.h"
+#include "audioconvert.h"
 
 #undef NDEBUG
 #include <assert.h>
@@ -43,6 +44,8 @@ typedef struct OggVorbisContext {
     uint8_t buffer[BUFFER_SIZE];
     int buffer_index;
     int eof;
+    int need_channel_remap;
+    const uint8_t *channel_map;
 
     /* decoder */
     vorbis_comment vc ;
@@ -50,6 +53,77 @@ typedef struct OggVorbisContext {
 } OggVorbisContext ;
 
 
+/**
+ * Table to remap channels from SMPTE order to Vorbis order.
+ */
+const uint8_t vorbis_channel_map[8][8] = {
+    { },                        // mono
+    { },                        // stereo
+    { 0, 2, 1,               }, // L C R
+    { },                        // quad
+    { 0, 2, 1, 3, 4,         }, // 5.0
+    { 0, 2, 1, 4, 5, 3,      }, // 5.1
+    { 0, 2, 1, 5, 6, 4, 3    }, // 6.1
+    { 0, 2, 1, 6, 7, 4, 5, 3 }  // 7.1
+};
+
+static av_cold int set_channel_info(OggVorbisContext *s, AVCodecContext *avctx)
+{
+    if (avctx->channels < 1 || avctx->channels > 255)
+        return -1;
+
+    if (avctx->channels > 8) {
+        av_log(avctx, AV_LOG_WARNING, "Warning: Channel layout with number of "
+                                      "channels greater than 8 is undefined.  "
+                                      "Channels will not be reordered.\n");
+        s->need_channel_remap = 0;
+        return 0;
+    }
+
+    if (!avctx->channel_layout) {
+        av_log(avctx, AV_LOG_WARNING, "Warning: No channel layout specified. "
+                                      "The layout will be guessed, but it "
+                                      "might be incorrect.\n");
+        avctx->channel_layout = avcodec_guess_channel_layout(avctx->channels,
+                                                             CODEC_ID_VORBIS,
+                                                             NULL);
+    }
+    if (avcodec_channel_layout_num_channels(avctx->channel_layout) != avctx->channels)
+        return -1;
+
+    /* The channel order is the same as in AC-3, but the Vorbis specification
+       is limited in that it only gives a 1:1 mapping between number of
+       channels and channel layout rather than allowing more flexibility.  We
+       bend the rules a little bit here in favor of usability by allowing
+       either back speakers or side speakers in the 4, 5, and 6 channel layouts
+       since this does not affect the channel order when remapping. */
+    switch (avctx->channel_layout) {
+    case CH_LAYOUT_MONO:
+    case CH_LAYOUT_STEREO:
+    case CH_LAYOUT_QUAD:
+    case CH_LAYOUT_2_2:
+        s->need_channel_remap = 0;
+        break;
+    case CH_LAYOUT_SURROUND:
+    case CH_LAYOUT_5POINT0:
+    case CH_LAYOUT_5POINT0_BACK:
+    case CH_LAYOUT_5POINT1:
+    case CH_LAYOUT_5POINT1_BACK:
+    case CH_LAYOUT_6POINT1:
+    case CH_LAYOUT_7POINT1:
+        s->need_channel_remap = 1;
+        s->channel_map = vorbis_channel_map[avctx->channels-1];
+        break;
+    default:
+        av_log(avctx, AV_LOG_WARNING, "Warning: Specified channel layout is "
+                                      "not standard for Vorbis.  Channels will "
+                                      "not be reordered.\n");
+        break;
+    }
+
+    return 0;
+}
+
 static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
     double cfreq;
 
@@ -88,6 +162,11 @@ static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext) {
     uint8_t *p;
     unsigned int offset, len;
 
+    if (set_channel_info(context, avccontext)) {
+        av_log(avccontext, AV_LOG_ERROR, "invalid channel layout\n");
+        return -1;
+    }
+
     vorbis_info_init(&context->vi) ;
     if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
         av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed\n") ;
@@ -142,18 +221,19 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
     int l;
 
     if(data) {
+        int ch, i;
         int samples = OGGVORBIS_FRAME_SIZE;
         float **buffer ;
 
         buffer = vorbis_analysis_buffer(&context->vd, samples) ;
-        if(context->vi.channels == 1) {
-            for(l = 0 ; l < samples ; l++)
-                buffer[0][l]=audio[l]/32768.f;
+        if (context->need_channel_remap) {
+            for(i = 0, l = 0; l < samples; l++)
+                for(ch = 0; ch < avccontext->channels; ch++)
+                    buffer[context->channel_map[ch]][l]=audio[i++]/32768.f;
         } else {
-            for(l = 0 ; l < samples ; l++){
-                buffer[0][l]=audio[l*2]/32768.f;
-                buffer[1][l]=audio[l*2+1]/32768.f;
-            }
+            for(i = 0, l = 0; l < samples; l++)
+                for(ch = 0; ch < avccontext->channels; ch++)
+                    buffer[ch][l]=audio[i++]/32768.f;
         }
         vorbis_analysis_wrote(&context->vd, samples) ;
     } else {

--------------030106030503030606010404--



More information about the ffmpeg-devel mailing list