From 08862850a70674c3a2380a4f8232c0dee91dbd96 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sat, 8 Aug 2009 00:47:48 -0300 Subject: 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. --- gst/matroska/matroska-demux.c | 26 ++++++++------ gst/matroska/matroska-mux.c | 84 ++++++++++++++++++++++++++++++++++++++----- gst/matroska/matroska-mux.h | 2 ++ 3 files changed, 92 insertions(+), 20 deletions(-) (limited to 'gst/matroska') diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 1384ee4f..1ffe8c49 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -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); - - caps = gst_riff_create_audio_caps (auds->format, NULL, auds, NULL, - NULL, codec_name); + 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); + + /* 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; diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index a40cea32..7e21ad3a 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -48,6 +48,8 @@ #include #include +#include + #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; } diff --git a/gst/matroska/matroska-mux.h b/gst/matroska/matroska-mux.h index 22ee9352..e969f85e 100644 --- a/gst/matroska/matroska-mux.h +++ b/gst/matroska/matroska-mux.h @@ -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, -- cgit