gst-libs/gst/audio/multichannel.c: Minor docs fix.

Original commit message from CVS:
* gst-libs/gst/audio/multichannel.c:
Minor docs fix.
* gst-libs/gst/riff/Makefile.am:
* gst-libs/gst/riff/riff-ids.h:
* gst-libs/gst/riff/riff-media.c:
(gst_riff_wavext_add_channel_layout), (gst_riff_create_audio_caps):
Add support for WAVEFORMATEX, eg. PCM audio with more than two
channels and a channel layout map.
This commit is contained in:
Tim-Philipp Müller 2006-02-16 19:18:46 +00:00
parent ced6e8445a
commit 9490d413c0
5 changed files with 167 additions and 3 deletions

View file

@ -1,3 +1,15 @@
2006-02-16 Tim-Philipp Müller <tim at centricular dot net>
* gst-libs/gst/audio/multichannel.c:
Minor docs fix.
* gst-libs/gst/riff/Makefile.am:
* gst-libs/gst/riff/riff-ids.h:
* gst-libs/gst/riff/riff-media.c:
(gst_riff_wavext_add_channel_layout), (gst_riff_create_audio_caps):
Add support for WAVEFORMATEX, eg. PCM audio with more than two
channels and a channel layout map.
2006-02-16 Mathieu Garcia <b0nk at free dot fr>
Reviewed by Edward Hervey <edward@fluendo.com>

View file

@ -265,7 +265,7 @@ gst_audio_get_channel_positions (GstStructure * str)
/**
* gst_audio_set_channel_positions:
* @str: A #GstStructure to retrieve channel positions from.
* @str: A #GstStructure to set channel positions on.
* @pos: an array of channel positions. The number of members
* in this array should be equal to the (fixed!) number
* of the "channels" property in the given #GstStructure.

View file

@ -11,6 +11,7 @@ libgstriff_@GST_MAJORMINOR@include_HEADERS = \
riff-media.h \
riff-read.h
libgstriff_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS)
libgstriff_@GST_MAJORMINOR@_la_CFLAGS = $(GST_CFLAGS)
libgstriff_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) \
$(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la
libgstriff_@GST_MAJORMINOR@_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS)
libgstriff_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)

View file

@ -298,6 +298,7 @@ typedef struct _gst_riff_strf_auds { /* == WaveHeader (?) */
#define GST_RIFF_WAVE_FORMAT_VORBIS3PLUS (0x6771)
#define GST_RIFF_WAVE_FORMAT_GSM_AMR_CBR (0x7A21)
#define GST_RIFF_WAVE_FORMAT_GSM_AMR_VBR (0x7A22)
#define GST_RIFF_WAVE_FORMAT_EXTENSIBLE (0xFFFE)
guint16 channels;
guint32 rate;
guint32 av_bps;

View file

@ -26,6 +26,13 @@
#include "riff-ids.h"
#include "riff-media.h"
#include <gst/audio/multichannel.h>
#include <string.h>
GST_DEBUG_CATEGORY_EXTERN (riff_debug);
#define GST_CAT_DEFAULT riff_debug
/**
* gst_riff_create_video_caps_with_data:
* @codec_fcc: fourCC codec for this codec.
@ -550,6 +557,85 @@ gst_riff_create_video_caps (guint32 codec_fcc,
return caps;
}
static const struct
{
const guint32 ms_mask;
const GstAudioChannelPosition gst_pos;
} layout_mapping[] = {
{
0x00001, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
0x00002, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
0x00004, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
0x00008, GST_AUDIO_CHANNEL_POSITION_LFE}, {
0x00010, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
0x00020, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
0x00040, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
0x00080, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
0x00100, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
0x00200, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
0x00400, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
0x00800, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_CENTER */
{
0x01000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_LEFT */
{
0x02000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_CENTER */
{
0x04000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_RIGHT */
{
0x08000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_LEFT */
{
0x10000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_CENTER */
{
0x20000, GST_AUDIO_CHANNEL_POSITION_INVALID} /* TOP_BACK_RIGHT */
};
#define MAX_CHANNEL_POSITIONS G_N_ELEMENTS (layout_mapping)
static gboolean
gst_riff_wavext_add_channel_layout (GstCaps * caps, guint32 layout)
{
GstAudioChannelPosition pos[MAX_CHANNEL_POSITIONS];
GstStructure *s;
gint num_channels, i, p;
s = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (s, "channels", &num_channels))
g_return_val_if_reached (FALSE);
if (num_channels < 2 || num_channels > MAX_CHANNEL_POSITIONS) {
GST_DEBUG ("invalid number of channels: %d", num_channels);
return FALSE;
}
p = 0;
for (i = 0; i < MAX_CHANNEL_POSITIONS; ++i) {
if ((layout & layout_mapping[i].ms_mask) != 0) {
if (p >= num_channels) {
GST_WARNING ("More bits set in the channel layout map than there "
"are channels! Broken file");
return FALSE;
}
if (layout_mapping[i].gst_pos == GST_AUDIO_CHANNEL_POSITION_INVALID) {
GST_WARNING ("Unsupported channel position (mask 0x%08x) in channel "
"layout map - ignoring those channels", layout_mapping[i].ms_mask);
/* what to do? just ignore it and let downstream deal with a channel
* layout that has INVALID positions in it for now ... */
}
pos[p] = layout_mapping[i].gst_pos;
++p;
}
}
if (p != num_channels) {
GST_WARNING ("Only %d bits set in the channel layout map, but there are "
"supposed to be %d channels! Broken file", p, num_channels);
return FALSE;
}
gst_audio_set_channel_positions (s, pos);
return TRUE;
}
GstCaps *
gst_riff_create_audio_caps (guint16 codec_id,
gst_riff_strh * strh, gst_riff_strf_auds * strf,
@ -586,6 +672,7 @@ gst_riff_create_audio_caps (guint16 codec_id,
"width", G_TYPE_INT, (int) (ba * 8 / ch),
"depth", G_TYPE_INT, ws, "signed", G_TYPE_BOOLEAN, ws != 8, NULL);
} else {
/* FIXME: this is pretty useless - we need fixed caps */
caps = gst_caps_from_string ("audio/x-raw-int, "
"endianness = (int) LITTLE_ENDIAN, "
"signed = (boolean) { true, false }, "
@ -699,6 +786,69 @@ gst_riff_create_audio_caps (guint16 codec_id,
*codec_name = g_strdup ("Sony ATRAC3");
break;
case GST_RIFF_WAVE_FORMAT_EXTENSIBLE:{
guint16 valid_bits_per_sample;
guint32 channel_mask;
guint32 subformat_guid[4];
const guint8 *data;
if (GST_BUFFER_SIZE (strf_data) != 22) {
GST_WARNING ("WAVE_FORMAT_EXTENSIBLE data size is %d (expected: 22)",
GST_BUFFER_SIZE (strf_data));
return NULL;
}
data = GST_BUFFER_DATA (strf_data);
valid_bits_per_sample = GST_READ_UINT16_LE (data);
channel_mask = GST_READ_UINT32_LE (data + 2);
subformat_guid[0] = GST_READ_UINT32_LE (data + 6);
subformat_guid[1] = GST_READ_UINT32_LE (data + 10);
subformat_guid[2] = GST_READ_UINT32_LE (data + 14);
subformat_guid[3] = GST_READ_UINT32_LE (data + 18);
GST_DEBUG ("valid bps = %u", valid_bits_per_sample);
GST_DEBUG ("channel mask = 0x%08x", channel_mask);
GST_DEBUG ("GUID = %08x-%08x-%08x-%08x", subformat_guid[0],
subformat_guid[1], subformat_guid[2], subformat_guid[3]);
if (subformat_guid[1] == 0x00100000 &&
subformat_guid[2] == 0xaa000080 && subformat_guid[3] == 0x719b3800) {
if (subformat_guid[0] == 0x00000001) {
GST_DEBUG ("PCM");
if (strf != NULL) {
gint ba = strf->blockalign;
gint ws = strf->size;
gint depth = ws;
if (valid_bits_per_sample != 0)
depth = valid_bits_per_sample;
caps = gst_caps_new_simple ("audio/x-raw-int",
"endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
"channels", G_TYPE_INT, strf->channels,
"width", G_TYPE_INT, (int) (ba * 8 / strf->channels),
"depth", G_TYPE_INT, depth,
"rate", G_TYPE_INT, strf->rate,
"signed", G_TYPE_BOOLEAN, (depth > 8) ? TRUE : FALSE, NULL);
if (!gst_riff_wavext_add_channel_layout (caps, channel_mask)) {
GST_WARNING ("failed to add channel layout");
gst_caps_unref (caps);
caps = NULL;
}
rate_chan = FALSE;
}
} else if (subformat_guid[0] == 0x00000003) {
GST_DEBUG ("FIXME: handle IEEE float format");
}
if (caps == NULL) {
GST_WARNING ("Unknown WAVE_FORMAT_EXTENSIBLE audio format");
return NULL;
}
}
break;
}
default:
GST_WARNING ("Unknown audio tag 0x%04x", codec_id);
return NULL;