matroska: Adds support to muxing/demuxing WMA

Adds support for muxing wma audio family and fixes
demuxing of wma family in matroskademux. matroskademux
was broken because it missed codec_data.
This commit is contained in:
Thiago Santos 2009-08-08 00:47:48 -03:00
parent df442b4727
commit 08862850a7
3 changed files with 91 additions and 19 deletions

View file

@ -5554,21 +5554,25 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
caps = gst_caps_new_simple ("audio/x-speex", NULL);
context->send_speex_headers = TRUE;
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
gst_riff_strf_auds *auds = NULL;
gst_riff_strf_auds auds;
if (data) {
auds = (gst_riff_strf_auds *) data;
GstBuffer *codec_data = gst_buffer_new ();
/* little-endian -> byte-order */
auds->format = GUINT16_FROM_LE (auds->format);
auds->channels = GUINT16_FROM_LE (auds->channels);
auds->rate = GUINT32_FROM_LE (auds->rate);
auds->av_bps = GUINT32_FROM_LE (auds->av_bps);
auds->blockalign = GUINT16_FROM_LE (auds->blockalign);
auds->size = GUINT16_FROM_LE (auds->size);
auds.format = GST_READ_UINT16_LE (data);
auds.channels = GST_READ_UINT16_LE (data + 2);
auds.rate = GST_READ_UINT32_LE (data + 4);
auds.av_bps = GST_READ_UINT32_LE (data + 8);
auds.blockalign = GST_READ_UINT16_LE (data + 12);
auds.size = GST_READ_UINT16_LE (data + 16);
caps = gst_riff_create_audio_caps (auds->format, NULL, auds, NULL,
NULL, codec_name);
/* 18 is the waveformatex size */
gst_buffer_set_data (codec_data, data + 18, auds.size);
caps = gst_riff_create_audio_caps (auds.format, NULL, &auds, NULL,
codec_data, codec_name);
gst_buffer_unref (codec_data);
}
} else if (g_str_has_prefix (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC)) {
GstBuffer *priv = NULL;

View file

@ -48,6 +48,8 @@
#include <math.h>
#include <string.h>
#include <gst/riff/riff-media.h>
#include "matroska-mux.h"
#include "matroska-ids.h"
@ -176,7 +178,10 @@ static GstStaticPadTemplate audiosink_templ =
"width = (int) { 8, 16, 24 }, "
"channels = (int) { 1, 2 }, " "rate = (int) [ 8000, 96000 ]; "
"audio/x-pn-realaudio, "
"raversion = (int) { 1, 2, 8 }, " COMMON_AUDIO_CAPS ";")
"raversion = (int) { 1, 2, 8 }, " COMMON_AUDIO_CAPS "; "
"audio/x-wma, " "wmaversion = (int) [ 1, 3 ], "
"block_align = (int) [ 0, 65535 ], bitrate = (int) [ 0, 524288 ], "
COMMON_AUDIO_CAPS)
);
static GstStaticPadTemplate subtitlesink_templ =
@ -758,7 +763,6 @@ skip_details:
} else if (!strcmp (mimetype, "video/x-wmv")) {
gint wmvversion;
guint32 format;
GST_WARNING_OBJECT (mux, "WMV");
if (gst_structure_get_fourcc (structure, "format", &format)) {
fourcc = format;
} else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
@ -770,7 +774,6 @@ skip_details:
fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
}
}
GST_WARNING_OBJECT (mux, "fourcc=%u", fourcc);
}
if (!fourcc)
@ -1406,6 +1409,8 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
const gchar *mimetype;
gint samplerate = 0, channels = 0;
GstStructure *structure;
const GValue *codec_data = NULL;
const GstBuffer *buf = NULL;
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@ -1429,6 +1434,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
audiocontext->bitdepth = 0;
context->default_duration = 0;
codec_data = gst_structure_get_value (structure, "codec_data");
if (codec_data)
buf = gst_value_get_buffer (codec_data);
/* TODO: - check if we handle all codecs by the spec, i.e. codec private
* data and other settings
* - add new formats
@ -1436,12 +1445,6 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
if (!strcmp (mimetype, "audio/mpeg")) {
gint mpegversion = 0;
const GValue *codec_data;
const GstBuffer *buf = NULL;
codec_data = gst_structure_get_value (structure, "codec_data");
if (codec_data)
buf = gst_value_get_buffer (codec_data);
gst_structure_get_int (structure, "mpegversion", &mpegversion);
switch (mpegversion) {
@ -1660,6 +1663,69 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
context->codec_priv_size = priv_data_size;
}
return TRUE;
} else if (!strcmp (mimetype, "audio/x-wma")) {
guint8 *codec_priv;
guint codec_priv_size;
guint16 format;
gint block_align;
gint bitrate;
gint wmaversion;
gint depth;
if (!gst_structure_get_int (structure, "wmaversion", &wmaversion)
|| !gst_structure_get_int (structure, "block_align", &block_align)
|| !gst_structure_get_int (structure, "bitrate", &bitrate)
|| samplerate == 0 || channels == 0) {
GST_WARNING_OBJECT (mux, "Missing wmaversion/block_align/bitrate/"
"channels/rate on WMA caps");
return FALSE;
}
switch (wmaversion) {
case 1:
format = GST_RIFF_WAVE_FORMAT_WMAV1;
break;
case 2:
format = GST_RIFF_WAVE_FORMAT_WMAV2;
break;
case 3:
format = GST_RIFF_WAVE_FORMAT_WMAV3;
break;
default:
GST_WARNING_OBJECT (mux, "Unexpected WMA version: %d", wmaversion);
return FALSE;
}
if (gst_structure_get_int (structure, "depth", &depth))
audiocontext->bitdepth = depth;
codec_priv_size = WAVEFORMATEX_SIZE;
if (buf)
codec_priv_size += GST_BUFFER_SIZE (buf);
/* serialize waveformatex structure */
codec_priv = g_malloc0 (codec_priv_size);
GST_WRITE_UINT16_LE (codec_priv, format);
GST_WRITE_UINT16_LE (codec_priv + 2, channels);
GST_WRITE_UINT32_LE (codec_priv + 4, samplerate);
GST_WRITE_UINT32_LE (codec_priv + 8, bitrate / 8);
GST_WRITE_UINT16_LE (codec_priv + 12, block_align);
GST_WRITE_UINT16_LE (codec_priv + 14, 0);
if (buf)
GST_WRITE_UINT16_LE (codec_priv + 16, GST_BUFFER_SIZE (buf));
else
GST_WRITE_UINT16_LE (codec_priv + 16, 0);
/* process codec private/initialization data, if any */
if (buf) {
memcpy ((guint8 *) codec_priv + WAVEFORMATEX_SIZE,
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
}
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM);
context->codec_priv = (gpointer) codec_priv;
context->codec_priv_size = codec_priv_size;
return TRUE;
}

View file

@ -56,6 +56,8 @@ typedef struct _BITMAPINFOHEADER {
guint32 bi_clr_important;
} BITMAPINFOHEADER;
#define WAVEFORMATEX_SIZE 18
typedef enum {
GST_MATROSKA_MUX_STATE_START,
GST_MATROSKA_MUX_STATE_HEADER,