diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2008-08-09 13:48:22 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2008-08-09 13:48:22 +0000 |
commit | b6f5226f0415f1068f09d99ca4fc5cd4d819b175 (patch) | |
tree | 2204ea494ec57f6fa999a0dc55416dd86d647a99 /gst/matroska/matroska-mux.c | |
parent | 530c36d9e7177463a00d74cb840f415eaa0f1fab (diff) |
gst/matroska/matroska-mux.c: Add support for muxing FLAC into Matroska containers.
Original commit message from CVS:
* gst/matroska/matroska-mux.c: (flac_streamheader_to_codecdata),
(gst_matroska_mux_audio_pad_setcaps):
Add support for muxing FLAC into Matroska containers.
Fixes bug #311586.
Diffstat (limited to 'gst/matroska/matroska-mux.c')
-rw-r--r-- | gst/matroska/matroska-mux.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index c2a73453..044504d6 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -118,6 +118,8 @@ static GstStaticPadTemplate audiosink_templ = COMMON_AUDIO_CAPS "; " "audio/x-vorbis, " COMMON_AUDIO_CAPS "; " + "audio/x-flac, " + COMMON_AUDIO_CAPS "; " "audio/x-raw-int, " "width = (int) 8, " "depth = (int) 8, " @@ -198,6 +200,8 @@ static gboolean theora_streamheader_to_codecdata (const GValue * streamheader, GstMatroskaTrackContext * context); static gboolean vorbis_streamheader_to_codecdata (const GValue * streamheader, GstMatroskaTrackContext * context); +static gboolean flac_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context); static void gst_matroska_mux_add_interfaces (GType type) @@ -924,6 +928,74 @@ theora_streamheader_to_codecdata (const GValue * streamheader, return TRUE; } +static gboolean +flac_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context) +{ + GArray *bufarr; + gint i; + GValue *bufval; + GstBuffer *buffer; + + if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) { + GST_WARNING ("No or invalid streamheader field in the caps"); + return FALSE; + } + + bufarr = g_value_peek_pointer (streamheader); + if (bufarr->len < 2) { + GST_WARNING ("Too few headers in streamheader field"); + return FALSE; + } + + context->xiph_headers_to_skip = bufarr->len; + + bufval = &g_array_index (bufarr, GValue, 0); + if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) { + GST_WARNING ("streamheaders array does not contain GstBuffers"); + return FALSE; + } + + buffer = g_value_peek_pointer (bufval); + + /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */ + if (GST_BUFFER_SIZE (buffer) < 9 + 4 + 4 + 34 + || memcmp (GST_BUFFER_DATA (buffer) + 1, "FLAC", 4) != 0 + || memcmp (GST_BUFFER_DATA (buffer) + 9, "fLaC", 4) != 0) { + GST_WARNING ("Invalid streamheader for FLAC"); + return FALSE; + } + + context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer) - 9); + context->codec_priv_size = GST_BUFFER_SIZE (buffer) - 9; + memcpy (context->codec_priv, GST_BUFFER_DATA (buffer) + 9, + GST_BUFFER_SIZE (buffer) - 9); + + for (i = 1; i < bufarr->len; i++) { + bufval = &g_array_index (bufarr, GValue, i); + + if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) { + g_free (context->codec_priv); + context->codec_priv = NULL; + context->codec_priv_size = 0; + GST_WARNING ("streamheaders array does not contain GstBuffers"); + return FALSE; + } + + buffer = g_value_peek_pointer (bufval); + + context->codec_priv = + g_realloc (context->codec_priv, + context->codec_priv_size + GST_BUFFER_SIZE (buffer)); + memcpy (context->codec_priv + context->codec_priv_size, + GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); + context->codec_priv_size = + context->codec_priv_size + GST_BUFFER_SIZE (buffer); + } + + return TRUE; +} + /** * gst_matroska_mux_audio_pad_setcaps: * @pad: Pad which got the caps. @@ -1094,6 +1166,23 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) return FALSE; } return TRUE; + } else if (!strcmp (mimetype, "audio/x-flac")) { + const GValue *streamheader; + + context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_FLAC); + if (context->codec_priv != NULL) { + g_free (context->codec_priv); + context->codec_priv = NULL; + context->codec_priv_size = 0; + } + + streamheader = gst_structure_get_value (structure, "streamheader"); + if (!flac_streamheader_to_codecdata (streamheader, context)) { + GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL), + ("flac stream headers missing or malformed")); + return FALSE; + } + return TRUE; } else if (!strcmp (mimetype, "audio/x-ac3")) { context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AC3); |