From 4e012bac91ced714fee133f527a802acb9ce4486 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 23 May 2006 13:44:11 +0000 Subject: [PATCH] gst/matroska/: Add support for muxing/demuxing theora video (#342448; too bad none of the usual linux players can act... Original commit message from CVS: * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream), (gst_matroska_demux_push_xiph_codec_priv_data), (gst_matroska_demux_parse_blockgroup_or_simpleblock), (gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps): * gst/matroska/matroska-ids.h: * gst/matroska/matroska-mux.c: (gst_matroska_mux_base_init), (gst_matroska_mux_video_pad_setcaps), (xiph3_streamheader_to_codecdata), (vorbis_streamheader_to_codecdata), (theora_streamheader_to_codecdata), (gst_matroska_mux_audio_pad_setcaps), (gst_matroska_mux_write_data): Add support for muxing/demuxing theora video (#342448; too bad none of the usual linux players can actually play this). Playback in GStreamer will require additional changes to theoradec in -base. Refactor streamheaders <=> CodecPrivateData code a bit; some small cleanups. --- ChangeLog | 20 +++ gst/matroska/matroska-demux.c | 34 ++-- gst/matroska/matroska-ids.h | 15 +- gst/matroska/matroska-mux.c | 349 +++++++++++++++++++++++++++--------------- 4 files changed, 272 insertions(+), 146 deletions(-) diff --git a/ChangeLog b/ChangeLog index faad4fa..1537de1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2006-05-23 Tim-Philipp Müller + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream), + (gst_matroska_demux_push_xiph_codec_priv_data), + (gst_matroska_demux_parse_blockgroup_or_simpleblock), + (gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps): + * gst/matroska/matroska-ids.h: + * gst/matroska/matroska-mux.c: (gst_matroska_mux_base_init), + (gst_matroska_mux_video_pad_setcaps), + (xiph3_streamheader_to_codecdata), + (vorbis_streamheader_to_codecdata), + (theora_streamheader_to_codecdata), + (gst_matroska_mux_audio_pad_setcaps), + (gst_matroska_mux_write_data): + Add support for muxing/demuxing theora video (#342448; too bad + none of the usual linux players can actually play this). Playback + in GStreamer will require additional changes to theoradec in -base. + Refactor streamheaders <=> CodecPrivateData code a bit; some small + cleanups. + 2006-05-22 Tim-Philipp Müller * ext/jpeg/gstjpegdec.c: (hresamplecpy1), diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index fff021c..34a4407 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -853,7 +853,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) caps = gst_matroska_demux_audio_caps (audiocontext, context->codec_id, context->codec_priv, context->codec_priv_size, &codec); - audiocontext->first_frame = TRUE; if (codec) { list = gst_tag_list_new (); gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, @@ -2024,18 +2023,7 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) } static gboolean -gst_matroska_demux_stream_is_first_vorbis_frame (GstMatroskaDemux * demux, - GstMatroskaTrackContext * stream) -{ - if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO - && ((GstMatroskaTrackAudioContext *) stream)->first_frame == TRUE) { - return (strcmp (stream->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS) == 0); - } - return FALSE; -} - -static gboolean -gst_matroska_demux_push_vorbis_codec_priv_data (GstMatroskaDemux * demux, +gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux, GstMatroskaTrackContext * stream) { GstFlowReturn ret; @@ -2044,9 +2032,8 @@ gst_matroska_demux_push_vorbis_codec_priv_data (GstMatroskaDemux * demux, guchar *p; gint i; - /* start of the stream and vorbis audio, need to send the codec_priv - * data as first three packets */ - ((GstMatroskaTrackAudioContext *) stream)->first_frame = FALSE; + /* start of the stream and vorbis audio or theora video, need to + * send the codec_priv data as first three packets */ p = (guchar *) stream->codec_priv; offset = 3; @@ -2292,9 +2279,11 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, break; } - if (gst_matroska_demux_stream_is_first_vorbis_frame (demux, stream)) { - if (!gst_matroska_demux_push_vorbis_codec_priv_data (demux, stream)) + if (stream->send_xiph_headers) { + if (!gst_matroska_demux_push_xiph_codec_priv_data (demux, stream)) { got_error = TRUE; + } + stream->send_xiph_headers = FALSE; } if (got_error) @@ -2962,6 +2951,8 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * g_assert (videocontext != NULL); g_assert (codec_name != NULL); + context->send_xiph_headers = FALSE; + if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) { gst_riff_strf_vids *vids = NULL; @@ -3107,6 +3098,9 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * caps = gst_caps_new_simple ("video/x-pn-realvideo", "rmversion", G_TYPE_INT, rmversion, NULL); *codec_name = g_strdup_printf ("RealVideo %d.0", rmversion); + } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_THEORA)) { + caps = gst_caps_new_simple ("video/x-theora", NULL); + context->send_xiph_headers = TRUE; } else { GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id); return NULL; @@ -3232,11 +3226,14 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * audiocontext, const gchar * codec_id, gpointer data, guint size, gchar ** codec_name) { + GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) audiocontext; GstCaps *caps = NULL; g_assert (audiocontext != NULL); g_assert (codec_name != NULL); + context->send_xiph_headers = FALSE; + if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) || !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) || !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) { @@ -3288,6 +3285,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * *codec_name = g_strdup ("DTS audio"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) { caps = gst_caps_new_simple ("audio/x-vorbis", NULL); + context->send_xiph_headers = TRUE; /* vorbis decoder does tags */ } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) { gst_riff_strf_auds *auds = NULL; diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index 4a00ba1..0016b654 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -144,6 +144,7 @@ #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2 "V_REAL/RV20" #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3 "V_REAL/RV30" #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4 "V_REAL/RV40" +#define GST_MATROSKA_CODEC_ID_VIDEO_THEORA "V_THEORA" /* TODO: Quicktime */ #define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1 "A_MPEG/L1" @@ -247,6 +248,15 @@ typedef struct _GstMatroskaTrackContext { guint64 pos; gboolean set_discont; /* TRUE = set DISCONT flag on next buffer */ + + /* Special flag for Vorbis and Theora, for which we need to send + * codec_priv first before sending any data, and just testing + * for time == 0 is not enough to detect that. Used by demuxer */ + gboolean send_xiph_headers; + + /* Special counter for muxer to skip the first N vorbis/theora headers - + * they are put into codec private data, not muxed into the stream */ + guint xiph_headers_to_skip; } GstMatroskaTrackContext; typedef struct _GstMatroskaTrackVideoContext { @@ -263,11 +273,6 @@ typedef struct _GstMatroskaTrackAudioContext { GstMatroskaTrackContext parent; guint samplerate, channels, bitdepth; - - /* Special flag for Vorbis, we need to send codec_priv first before - * sending any data, and just testing for time == 0 is not enough - * to detect that */ - gboolean first_frame; } GstMatroskaTrackAudioContext; typedef struct _GstMatroskaTrackComplexContext { diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 96d2e1a..2b76df0 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -35,16 +35,9 @@ GST_DEBUG_CATEGORY_STATIC (matroskamux_debug); enum { - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ ARG_0, ARG_WRITING_APP, ARG_MATROSKA_VERSION - /* FILL ME */ }; static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", @@ -82,6 +75,7 @@ static GstStaticPadTemplate videosink_templ = COMMON_VIDEO_CAPS "; " "image/jpeg, " COMMON_VIDEO_CAPS "; " + "video/x-theora; " "video/x-raw-yuv, " "format = (fourcc) { YUY2, I420 }, " COMMON_VIDEO_CAPS) ); @@ -127,15 +121,8 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%d", static GArray *used_uids; -static void -_do_init (GType matroskamux_type) -{ - GST_DEBUG_CATEGORY_INIT (matroskamux_debug, "matroskamux", 0, - "Matroska muxer"); -} - -GST_BOILERPLATE_FULL (GstMatroskaMux, gst_matroska_mux, GstElement, - GST_TYPE_ELEMENT, _do_init); +GST_BOILERPLATE (GstMatroskaMux, gst_matroska_mux, GstElement, + GST_TYPE_ELEMENT); /* Matroska muxer destructor */ static void gst_matroska_mux_finalize (GObject * object); @@ -166,7 +153,10 @@ static void gst_matroska_mux_reset (GstElement * element); /* uid generation */ static guint32 gst_matroska_mux_create_uid (); -/*static guint gst_matroska_mux_signals[LAST_SIGNAL] = { 0 };*/ +static gboolean theora_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context); +static gboolean vorbis_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context); static void gst_matroska_mux_base_init (gpointer g_class) @@ -187,6 +177,9 @@ gst_matroska_mux_base_init (gpointer g_class) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_templ)); gst_element_class_set_details (element_class, &gst_matroska_mux_details); + + GST_DEBUG_CATEGORY_INIT (matroskamux_debug, "matroskamux", 0, + "Matroska muxer"); } static void @@ -427,12 +420,15 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) { GstMatroskaTrackContext *context = NULL; GstMatroskaTrackVideoContext *videocontext; + GstMatroskaMux *mux; GstMatroskaPad *collect_pad; const gchar *mimetype; gint width, height, pixel_width, pixel_height; const GValue *framerate; GstStructure *structure; + mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad)); + /* find context */ collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad); g_assert (collect_pad); @@ -446,6 +442,11 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) mimetype = gst_structure_get_name (structure); + if (!strcmp (mimetype, "video/x-theora")) { + /* we'll extract the details later from the theora identification header */ + goto skip_details; + } + /* get general properties */ gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); @@ -476,6 +477,8 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) videocontext->display_height = 0; } +skip_details: + videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE; videocontext->eye_mode = GST_MATROSKA_EYE_MODE_MONO; videocontext->fourcc = 0; @@ -582,6 +585,24 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) } return TRUE; + } else if (!strcmp (mimetype, "video/x-theora")) { + const GValue *streamheader; + + context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_THEORA); + + 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 (!theora_streamheader_to_codecdata (streamheader, context)) { + GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL), + ("theora stream headers missing or malformed")); + return FALSE; + } + return TRUE; } else if (!strcmp (mimetype, "video/mpeg")) { gint mpegversion; @@ -610,6 +631,182 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) return FALSE; } +static gboolean +xiph3_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context, GstBuffer ** p_buf0) +{ + GstBuffer *buf[3]; + GArray *bufarr; + guint8 *priv_data; + guint i, offset, priv_data_size; + + if (streamheader == NULL) + goto no_stream_headers; + + if (G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) + goto wrong_type; + + bufarr = g_value_peek_pointer (streamheader); + if (bufarr->len != 3) + goto wrong_count; + + context->xiph_headers_to_skip = bufarr->len; + + for (i = 0; i < 3; i++) { + GValue *bufval = &g_array_index (bufarr, GValue, i); + + if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) + goto wrong_content_type; + + buf[i] = g_value_peek_pointer (bufval); + } + + priv_data_size = 1; + priv_data_size += GST_BUFFER_SIZE (buf[0]) / 0xff + 1; + priv_data_size += GST_BUFFER_SIZE (buf[1]) / 0xff + 1; + + for (i = 0; i < 3; ++i) { + priv_data_size += GST_BUFFER_SIZE (buf[i]); + } + + priv_data = g_malloc0 (priv_data_size); + + priv_data[0] = 2; + offset = 1; + + for (i = 0; i < GST_BUFFER_SIZE (buf[0]) / 0xff; ++i) { + priv_data[offset++] = 0xff; + } + priv_data[offset++] = GST_BUFFER_SIZE (buf[0]) % 0xff; + + for (i = 0; i < GST_BUFFER_SIZE (buf[1]) / 0xff; ++i) { + priv_data[offset++] = 0xff; + } + priv_data[offset++] = GST_BUFFER_SIZE (buf[1]) % 0xff; + + for (i = 0; i < 3; ++i) { + memcpy (priv_data + offset, GST_BUFFER_DATA (buf[i]), + GST_BUFFER_SIZE (buf[i])); + offset += GST_BUFFER_SIZE (buf[i]); + } + + context->codec_priv = priv_data; + context->codec_priv_size = priv_data_size; + + if (p_buf0) + *p_buf0 = gst_buffer_ref (buf[0]); + + return TRUE; + +/* ERRORS */ +no_stream_headers: + { + GST_WARNING ("required streamheaders missing in sink caps!"); + return FALSE; + } +wrong_type: + { + GST_WARNING ("streamheaders are not a GST_TYPE_ARRAY, but a %s", + G_VALUE_TYPE_NAME (streamheader)); + return FALSE; + } +wrong_count: + { + GST_WARNING ("got %u streamheaders, not 3 as expected", bufarr->len); + return FALSE; + } +wrong_content_type: + { + GST_WARNING ("streamheaders array does not contain GstBuffers"); + return FALSE; + } +} + +static gboolean +vorbis_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context) +{ + GstBuffer *buf0 = NULL; + + if (!xiph3_streamheader_to_codecdata (streamheader, context, &buf0)) + return FALSE; + + if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 4) { + GST_WARNING ("First vorbis header too small, ignoring"); + } else { + if (memcmp (GST_BUFFER_DATA (buf0) + 1, "vorbis", 6) == 0) { + GstMatroskaTrackAudioContext *audiocontext; + guint8 *hdr; + + hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 4; + audiocontext = (GstMatroskaTrackAudioContext *) context; + audiocontext->channels = GST_READ_UINT8 (hdr); + audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1); + } + } + + if (buf0) + gst_buffer_unref (buf0); + + return TRUE; +} + +static gboolean +theora_streamheader_to_codecdata (const GValue * streamheader, + GstMatroskaTrackContext * context) +{ + GstBuffer *buf0 = NULL; + + if (!xiph3_streamheader_to_codecdata (streamheader, context, &buf0)) + return FALSE; + + if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 26) { + GST_WARNING ("First theora header too small, ignoring"); + } else if (memcmp (GST_BUFFER_DATA (buf0), "\200theora\003\002", 9) != 0) { + GST_WARNING ("First header not a theora identification header, ignoring"); + } else { + GstMatroskaTrackVideoContext *videocontext; + guint fps_num, fps_denom, par_num, par_denom; + guint8 *hdr; + + hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 3 + 2 + 2; + + videocontext = (GstMatroskaTrackVideoContext *) context; + videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8; + videocontext->pixel_height = GST_READ_UINT32_BE (hdr + 3) >> 8; + hdr += 3 + 3 + 1 + 1; + fps_num = GST_READ_UINT32_BE (hdr); + fps_denom = GST_READ_UINT32_BE (hdr + 4); + context->default_duration = gst_util_uint64_scale_int (GST_SECOND, + fps_denom, fps_num); + hdr += 4 + 4; + par_num = GST_READ_UINT32_BE (hdr) >> 8; + par_denom = GST_READ_UINT32_BE (hdr + 3) >> 8; + if (par_num > 0 && par_num > 0) { + if (par_num > par_denom) { + videocontext->display_width = + videocontext->pixel_width * par_num / par_denom; + videocontext->display_height = videocontext->pixel_height; + } else if (par_num < par_denom) { + videocontext->display_width = videocontext->pixel_width; + videocontext->display_height = + videocontext->pixel_height * par_denom / par_num; + } else { + videocontext->display_width = 0; + videocontext->display_height = 0; + } + } else { + videocontext->display_width = 0; + videocontext->display_height = 0; + } + hdr += 3 + 3; + } + + if (buf0) + gst_buffer_unref (buf0); + + return TRUE; +} /** * gst_matroska_mux_audio_pad_setcaps: @@ -625,11 +822,14 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) { GstMatroskaTrackContext *context = NULL; GstMatroskaTrackAudioContext *audiocontext; + GstMatroskaMux *mux; GstMatroskaPad *collect_pad; const gchar *mimetype; gint samplerate = 0, channels = 0; GstStructure *structure; + mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad)); + /* find context */ collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad); g_assert (collect_pad); @@ -716,8 +916,6 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) /* FIXME: endianness is undefined */ } else if (!strcmp (mimetype, "audio/x-vorbis")) { const GValue *streamheader; - guint8 *priv_data = NULL; - guint priv_data_size = 0; context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_VORBIS); @@ -726,81 +924,14 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) context->codec_priv = NULL; context->codec_priv_size = 0; } - streamheader = gst_structure_get_value (structure, "streamheader"); - - if (streamheader != NULL) { - if (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) { - GArray *bufarr = g_value_peek_pointer (streamheader); - gint i; - gint offset; - - if (bufarr->len == 3) { - GstBuffer *buf[3]; - - for (i = 0; i < bufarr->len; i++) { - GValue *bufval = &g_array_index (bufarr, GValue, i); - - if (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER) { - buf[i] = g_value_peek_pointer (bufval); - } - } - - priv_data_size = 1; - priv_data_size += GST_BUFFER_SIZE (buf[0]) / 0xff + 1; - priv_data_size += GST_BUFFER_SIZE (buf[1]) / 0xff + 1; - - for (i = 0; i < 3; ++i) { - priv_data_size += GST_BUFFER_SIZE (buf[i]); - } - - priv_data = g_malloc0 (priv_data_size); - - priv_data[0] = 2; - offset = 1; - - for (i = 0; i < GST_BUFFER_SIZE (buf[0]) / 0xff; ++i) { - priv_data[offset++] = 0xff; - } - priv_data[offset++] = GST_BUFFER_SIZE (buf[0]) % 0xff; - - for (i = 0; i < GST_BUFFER_SIZE (buf[1]) / 0xff; ++i) { - priv_data[offset++] = 0xff; - } - priv_data[offset++] = GST_BUFFER_SIZE (buf[1]) % 0xff; - - for (i = 0; i < 3; ++i) { - memcpy (priv_data + offset, GST_BUFFER_DATA (buf[i]), - GST_BUFFER_SIZE (buf[i])); - offset += GST_BUFFER_SIZE (buf[i]); - } - - if (GST_BUFFER_SIZE (buf[0]) < 1 + 6 + 4) { - GST_WARNING ("First vorbis header too small, ignoring"); - } else { - if (memcmp (GST_BUFFER_DATA (buf[0]) + 1, "vorbis", 6) == 0) { - guint8 *hdr = GST_BUFFER_DATA (buf[0]) + 1 + 6 + 4; - - audiocontext->channels = GST_READ_UINT8 (hdr); - audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1); - } - } - } else { - GST_WARNING ("Vorbis header does not contain " - "three buffers (found %d buffers), Ignoring.", bufarr->len); - } - } - } - if (priv_data == NULL) { - GST_WARNING ("Could not write Vorbis header into codec private data. " - "You will probably not be able to play the stream."); + streamheader = gst_structure_get_value (structure, "streamheader"); + if (!vorbis_streamheader_to_codecdata (streamheader, context)) { + GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL), + ("vorbis stream headers missing or malformed")); + return FALSE; } - - context->codec_priv_size = priv_data_size; - context->codec_priv = (gpointer) priv_data; - return TRUE; - } else if (!strcmp (mimetype, "audio/x-ac3")) { context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AC3); @@ -1304,35 +1435,6 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped) return best; } -static gboolean -gst_matroska_mux_stream_is_vorbis_header (GstMatroskaMux * mux, - GstMatroskaPad * collect_pad) -{ - GstMatroskaTrackAudioContext *audio_ctx; - - audio_ctx = (GstMatroskaTrackAudioContext *) collect_pad->track; - - if (collect_pad->track->type != GST_MATROSKA_TRACK_TYPE_AUDIO) - return FALSE; - - if (audio_ctx->first_frame != FALSE) - return FALSE; - - if (collect_pad->track->codec_id == NULL || - strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) - return FALSE; - - /* HACK: three frame headers are counted using pos */ - if (++collect_pad->track->pos <= 3) - return TRUE; - - /* 4th vorbis packet => skipped all headers */ - collect_pad->track->pos = 0; - audio_ctx->first_frame = TRUE; - return FALSE; -} - - /** * gst_matroska_mux_buffer_header: * @track: Track context. @@ -1386,10 +1488,11 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad) buf = collect_pad->buffer; collect_pad->buffer = NULL; - /* vorbis header are retrieved from caps and placed in CodecPrivate */ - if (gst_matroska_mux_stream_is_vorbis_header (mux, collect_pad)) { - GST_LOG_OBJECT (collect_pad->collect.pad, "dropping vorbis header buffer"); + /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */ + if (collect_pad->track->xiph_headers_to_skip > 0) { + GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer"); gst_buffer_unref (buf); + --collect_pad->track->xiph_headers_to_skip; return GST_FLOW_OK; } -- 2.7.4