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