1 /* GStreamer Matroska muxer/demuxer
2 * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * matroska-demux.c: matroska file/stream demuxer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
29 /* For AVI compatibility mode... Who did that? */
30 #include <gst/riff/riff-ids.h>
31 #include <gst/riff/riff-media.h>
33 #include "matroska-demux.h"
34 #include "matroska-ids.h"
48 static GstStaticPadTemplate sink_templ =
49 GST_STATIC_PAD_TEMPLATE (
53 GST_STATIC_CAPS ( "video/x-matroska" )
56 /* gobject magic foo */
57 static void gst_matroska_demux_base_init (GstMatroskaDemuxClass *klass);
58 static void gst_matroska_demux_class_init (GstMatroskaDemuxClass *klass);
59 static void gst_matroska_demux_init (GstMatroskaDemux *demux);
61 /* element functions */
62 static void gst_matroska_demux_loop (GstElement *element);
63 static gboolean gst_matroska_demux_send_event (GstElement *element,
67 static const GstEventMask *
68 gst_matroska_demux_get_event_mask (GstPad *pad);
69 static gboolean gst_matroska_demux_handle_src_event (GstPad *pad,
71 static const GstFormat *
72 gst_matroska_demux_get_src_formats (GstPad *pad);
73 static const GstQueryType*
74 gst_matroska_demux_get_src_query_types(GstPad *pad);
75 static gboolean gst_matroska_demux_handle_src_query (GstPad *pad,
80 /* gst internal change state handler */
81 static GstElementStateReturn
82 gst_matroska_demux_change_state (GstElement *element);
83 static void gst_matroska_demux_set_clock (GstElement *element,
87 static void gst_matroska_demux_get_property (GObject *object,
93 static GstCaps *gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext
95 const gchar *codec_id,
98 GstMatroskaDemux *demux);
99 static GstCaps *gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext
101 const gchar *codec_id,
104 GstMatroskaDemux *demux);
105 static GstCaps *gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext
107 const gchar *codec_id,
110 static GstCaps *gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext
112 const gchar *codec_id,
117 static void gst_matroska_demux_reset (GstElement *element);
119 static GstEbmlReadClass *parent_class = NULL;
120 static GstPadTemplate *videosrctempl, *audiosrctempl, *subtitlesrctempl;
121 /*static guint gst_matroska_demux_signals[LAST_SIGNAL] = { 0 };*/
124 gst_matroska_demux_get_type (void)
126 static GType gst_matroska_demux_type = 0;
128 if (!gst_matroska_demux_type) {
129 static const GTypeInfo gst_matroska_demux_info = {
130 sizeof (GstMatroskaDemuxClass),
131 (GBaseInitFunc) gst_matroska_demux_base_init,
133 (GClassInitFunc) gst_matroska_demux_class_init,
136 sizeof (GstMatroskaDemux),
138 (GInstanceInitFunc) gst_matroska_demux_init,
141 gst_matroska_demux_type =
142 g_type_register_static (GST_TYPE_EBML_READ,
144 &gst_matroska_demux_info, 0);
147 return gst_matroska_demux_type;
151 gst_matroska_demux_base_init (GstMatroskaDemuxClass *klass)
153 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
154 static GstElementDetails gst_matroska_demux_details = {
157 "Demuxes a Matroska Stream into video/audio/subtitles",
158 "Ronald Bultje <rbultje@ronald.bitfreak.net>"
161 gst_element_class_add_pad_template (element_class, videosrctempl);
162 gst_element_class_add_pad_template (element_class, audiosrctempl);
163 gst_element_class_add_pad_template (element_class, subtitlesrctempl);
164 gst_element_class_add_pad_template (element_class,
165 gst_static_pad_template_get (&sink_templ));
166 gst_element_class_set_details (element_class,
167 &gst_matroska_demux_details);
171 gst_matroska_demux_class_init (GstMatroskaDemuxClass *klass)
173 GObjectClass *gobject_class;
174 GstElementClass *gstelement_class;
176 gobject_class = (GObjectClass *) klass;
177 gstelement_class = (GstElementClass *) klass;
179 g_object_class_install_property (gobject_class, ARG_METADATA,
180 g_param_spec_boxed ("metadata", "Metadata", "Metadata",
181 GST_TYPE_STRUCTURE, G_PARAM_READABLE));
182 g_object_class_install_property (gobject_class, ARG_STREAMINFO,
183 g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
184 GST_TYPE_STRUCTURE, G_PARAM_READABLE));
186 parent_class = g_type_class_ref (GST_TYPE_EBML_READ);
188 gobject_class->get_property = gst_matroska_demux_get_property;
190 gstelement_class->change_state = gst_matroska_demux_change_state;
191 gstelement_class->send_event = gst_matroska_demux_send_event;
192 gstelement_class->set_clock = gst_matroska_demux_set_clock;
196 gst_matroska_demux_init (GstMatroskaDemux *demux)
198 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
201 GST_FLAG_SET (GST_OBJECT (demux), GST_ELEMENT_EVENT_AWARE);
203 demux->sinkpad = gst_pad_new_from_template (
204 gst_element_class_get_pad_template (klass, "sink"), "sink");
205 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
206 GST_EBML_READ (demux)->sinkpad = demux->sinkpad;
208 gst_element_set_loop_function (GST_ELEMENT (demux),
209 gst_matroska_demux_loop);
211 /* initial stream no. */
212 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
213 demux->src[i] = NULL;
215 demux->streaminfo = demux->metadata = NULL;
216 demux->writing_app = demux->muxing_app = NULL;
220 gst_matroska_demux_reset (GST_ELEMENT (demux));
224 gst_matroska_demux_reset (GstElement *element)
226 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
230 demux->state = GST_MATROSKA_DEMUX_STATE_START;
232 /* clean up existing streams */
233 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
234 if (demux->src[i] != NULL) {
235 if (demux->src[i]->pad != NULL) {
236 gst_element_remove_pad (GST_ELEMENT (demux), demux->src[i]->pad);
238 g_free (demux->src[i]->codec_id);
239 g_free (demux->src[i]->codec_name);
240 g_free (demux->src[i]->name);
241 g_free (demux->src[i]->language);
242 g_free (demux->src[i]->codec_priv);
243 g_free (demux->src[i]);
244 demux->src[i] = NULL;
247 demux->num_streams = 0;
248 demux->num_a_streams = 0;
249 demux->num_t_streams = 0;
250 demux->num_v_streams = 0;
252 /* reset media info */
254 gst_caps_replace (&demux->metadata, NULL);
255 gst_caps_replace (&demux->streaminfo, NULL);
257 g_free (demux->writing_app);
258 demux->writing_app = NULL;
259 g_free (demux->muxing_app);
260 demux->muxing_app = NULL;
263 demux->num_indexes = 0;
264 g_free (demux->index);
269 demux->time_scale = 1000000;
272 demux->created = G_MININT64;
273 demux->seek_pending = GST_CLOCK_TIME_NONE;
275 demux->metadata_parsed = FALSE;
276 demux->index_parsed = FALSE;
280 gst_matroska_demux_set_clock (GstElement *element,
283 GST_MATROSKA_DEMUX (element)->clock = clock;
287 gst_matroska_demux_stream_from_num (GstMatroskaDemux *demux,
292 for (n = 0; n < demux->num_streams; n++) {
293 if (demux->src[n] != NULL &&
294 demux->src[n]->num == track_num) {
299 if (n == demux->num_streams) {
300 GST_WARNING ("Failed to find corresponding pad for tracknum %d",
308 gst_matroska_demux_src_getcaps (GstPad *pad)
310 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
313 for (n = 0; n < demux->num_streams; n++) {
314 if (demux->src[n] != NULL && demux->src[n]->pad == pad) {
319 if (n == demux->num_streams)
320 return gst_caps_new_empty();
322 return gst_caps_copy (demux->src[n]->caps);
326 gst_matroska_demux_add_stream (GstMatroskaDemux *demux)
328 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
329 GstEbmlRead *ebml = GST_EBML_READ (demux);
330 GstMatroskaTrackContext *context;
331 GstPadTemplate *templ = NULL;
332 GstCaps *caps = NULL;
333 gchar *padname = NULL;
337 if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) {
338 GST_WARNING ("Maximum number of streams (%d) exceeded, skipping",
339 GST_MATROSKA_DEMUX_MAX_STREAMS);
340 return gst_ebml_read_skip (ebml); /* skip-and-continue */
343 /* allocate generic... if we know the type, we'll g_renew()
344 * with the precise type */
345 context = g_new0 (GstMatroskaTrackContext, 1);
346 demux->src[demux->num_streams] = context;
347 context->index = demux->num_streams;
348 context->type = 0; /* no type yet */
349 demux->num_streams++;
351 /* start with the master */
352 if (!gst_ebml_read_master (ebml, &id))
355 /* try reading the trackentry headers */
357 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
360 } else if (demux->level_up > 0) {
366 /* track number (unique stream ID) */
367 case GST_MATROSKA_ID_TRACKNUMBER: {
369 if (!gst_ebml_read_uint (ebml, &id, &num)) {
377 /* track UID (unique identifier) */
378 case GST_MATROSKA_ID_TRACKUID: {
380 if (!gst_ebml_read_uint (ebml, &id, &num)) {
388 /* track type (video, audio, combined, subtitle, etc.) */
389 case GST_MATROSKA_ID_TRACKTYPE: {
391 if (context->type != 0) {
392 GST_WARNING ("More than one tracktype defined in a trackentry - skipping");
395 if (!gst_ebml_read_uint (ebml, &id, &num)) {
401 /* ok, so we're actually going to reallocate this thing */
402 switch (context->type) {
403 case GST_MATROSKA_TRACK_TYPE_VIDEO:
404 context = (GstMatroskaTrackContext *)
405 g_renew (GstMatroskaTrackVideoContext, context, 1);
407 case GST_MATROSKA_TRACK_TYPE_AUDIO:
408 context = (GstMatroskaTrackContext *)
409 g_renew (GstMatroskaTrackAudioContext, context, 1);
411 ((GstMatroskaTrackAudioContext *) context)->channels = 1;
412 ((GstMatroskaTrackAudioContext *) context)->samplerate = 8000;
414 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
415 context = (GstMatroskaTrackContext *)
416 g_renew (GstMatroskaTrackComplexContext, context, 1);
418 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
419 context = (GstMatroskaTrackContext *)
420 g_renew (GstMatroskaTrackSubtitleContext, context, 1);
422 case GST_MATROSKA_TRACK_TYPE_LOGO:
423 case GST_MATROSKA_TRACK_TYPE_CONTROL:
425 GST_WARNING ("Unknown or unsupported track type 0x%x",
430 demux->src[demux->num_streams-1] = context;
434 /* tracktype specific stuff for video */
435 case GST_MATROSKA_ID_TRACKVIDEO: {
436 GstMatroskaTrackVideoContext *videocontext;
437 if (context->type != GST_MATROSKA_TRACK_TYPE_VIDEO) {
438 GST_WARNING ("trackvideo EBML entry in non-video track - ignoring track");
441 } else if (!gst_ebml_read_master (ebml, &id)) {
445 videocontext = (GstMatroskaTrackVideoContext *) context;
448 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
451 } else if (demux->level_up > 0) {
457 /* fixme, this should be one-up, but I get it here (?) */
458 case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
460 if (!gst_ebml_read_uint (ebml, &id, &num)) {
464 context->default_duration = num;
468 /* video framerate */
469 case GST_MATROSKA_ID_VIDEOFRAMERATE: {
471 if (!gst_ebml_read_float (ebml, &id, &num)) {
475 context->default_duration = GST_SECOND * (1. / num);
479 /* width of the size to display the video at */
480 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH: {
482 if (!gst_ebml_read_uint (ebml, &id, &num)) {
486 videocontext->display_width = num;
490 /* height of the size to display the video at */
491 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT: {
493 if (!gst_ebml_read_uint (ebml, &id, &num)) {
497 videocontext->display_height = num;
501 /* width of the video in the file */
502 case GST_MATROSKA_ID_VIDEOPIXELWIDTH: {
504 if (!gst_ebml_read_uint (ebml, &id, &num)) {
508 videocontext->pixel_width = num;
512 /* height of the video in the file */
513 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT: {
515 if (!gst_ebml_read_uint (ebml, &id, &num)) {
519 videocontext->pixel_height = num;
523 /* whether the video is interlaced */
524 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED: {
526 if (!gst_ebml_read_uint (ebml, &id, &num)) {
531 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
533 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
537 /* stereo mode (whether the video has two streams, where
538 * one is for the left eye and the other for the right eye,
539 * which creates a 3D-like effect) */
540 case GST_MATROSKA_ID_VIDEOSTEREOMODE: {
542 if (!gst_ebml_read_uint (ebml, &id, &num)) {
546 if (num != GST_MATROSKA_EYE_MODE_MONO &&
547 num != GST_MATROSKA_EYE_MODE_LEFT &&
548 num != GST_MATROSKA_EYE_MODE_RIGHT &&
549 num != GST_MATROSKA_EYE_MODE_BOTH) {
550 GST_WARNING ("Unknown eye mode 0x%x - ignoring",
554 videocontext->eye_mode = num;
558 /* aspect ratio behaviour */
559 case GST_MATROSKA_ID_VIDEOASPECTRATIO: {
561 if (!gst_ebml_read_uint (ebml, &id, &num)) {
565 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
566 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
567 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
568 GST_WARNING ("Unknown aspect ratio mode 0x%x - ignoring",
572 videocontext->asr_mode = num;
576 /* colourspace (only matters for raw video) fourcc */
577 case GST_MATROSKA_ID_VIDEOCOLOURSPACE: {
579 if (!gst_ebml_read_uint (ebml, &id, &num)) {
583 videocontext->fourcc = num;
588 GST_WARNING ("Unknown video track header entry 0x%x - ignoring",
592 case GST_EBML_ID_VOID:
593 if (!gst_ebml_read_skip (ebml))
598 if (demux->level_up) {
606 /* tracktype specific stuff for audio */
607 case GST_MATROSKA_ID_TRACKAUDIO: {
608 GstMatroskaTrackAudioContext *audiocontext;
609 if (context->type != GST_MATROSKA_TRACK_TYPE_AUDIO) {
610 GST_WARNING ("trackaudio EBML entry in non-audio track - ignoring track");
613 } else if (!gst_ebml_read_master (ebml, &id)) {
617 audiocontext = (GstMatroskaTrackAudioContext *) context;
620 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
623 } else if (demux->level_up > 0) {
630 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ: {
632 if (!gst_ebml_read_float (ebml, &id, &num)) {
636 audiocontext->samplerate = num;
641 case GST_MATROSKA_ID_AUDIOBITDEPTH: {
643 if (!gst_ebml_read_uint (ebml, &id, &num)) {
647 audiocontext->bitdepth = num;
652 case GST_MATROSKA_ID_AUDIOCHANNELS: {
654 if (!gst_ebml_read_uint (ebml, &id, &num)) {
658 audiocontext->channels = num;
663 GST_WARNING ("Unknown audio track header entry 0x%x - ignoring",
667 case GST_EBML_ID_VOID:
668 if (!gst_ebml_read_skip (ebml))
673 if (demux->level_up) {
681 /* codec identifier */
682 case GST_MATROSKA_ID_CODECID: {
684 if (!gst_ebml_read_ascii (ebml, &id, &text)) {
688 context->codec_id = text;
692 /* codec private data */
693 case GST_MATROSKA_ID_CODECPRIVATE: {
696 if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
700 context->codec_priv = data;
701 context->codec_priv_size = size;
705 /* name of the codec */
706 case GST_MATROSKA_ID_CODECNAME: {
708 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
712 context->codec_name = text;
716 /* name of this track */
717 case GST_MATROSKA_ID_TRACKNAME: {
719 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
723 context->name = text;
727 /* language (matters for audio/subtitles, mostly) */
728 case GST_MATROSKA_ID_TRACKLANGUAGE: {
730 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
734 context->language = text;
738 /* whether this is actually used */
739 case GST_MATROSKA_ID_TRACKFLAGENABLED: {
741 if (!gst_ebml_read_uint (ebml, &id, &num)) {
746 context->flags |= GST_MATROSKA_TRACK_ENABLED;
748 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
752 /* whether it's the default for this track type */
753 case GST_MATROSKA_ID_TRACKFLAGDEFAULT: {
755 if (!gst_ebml_read_uint (ebml, &id, &num)) {
760 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
762 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
766 /* lacing (like MPEG, where blocks don't end/start on frame
768 case GST_MATROSKA_ID_TRACKFLAGLACING: {
770 if (!gst_ebml_read_uint (ebml, &id, &num)) {
775 context->flags |= GST_MATROSKA_TRACK_LACING;
777 context->flags &= ~GST_MATROSKA_TRACK_LACING;
781 /* default length (in time) of one data block in this track */
782 case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
784 if (!gst_ebml_read_uint (ebml, &id, &num)) {
788 context->default_duration = num;
793 GST_WARNING ("Unknown track header entry 0x%x - ignoring", id);
796 /* we ignore these because they're nothing useful (i.e. crap). */
797 case GST_MATROSKA_ID_CODECINFOURL:
798 case GST_MATROSKA_ID_CODECDOWNLOADURL:
799 case GST_MATROSKA_ID_TRACKMINCACHE:
800 case GST_MATROSKA_ID_TRACKMAXCACHE:
801 case GST_EBML_ID_VOID:
802 if (!gst_ebml_read_skip (ebml))
807 if (demux->level_up) {
813 if (context->type == 0 || context->codec_id == NULL || !res) {
815 GST_WARNING ("Unknown stream/codec in track entry header");
817 demux->num_streams--;
818 demux->src[demux->num_streams] = NULL;
820 g_free (context->codec_id);
821 g_free (context->codec_name);
822 g_free (context->name);
823 g_free (context->language);
824 g_free (context->codec_priv);
831 /* now create the GStreamer connectivity */
832 switch (context->type) {
833 case GST_MATROSKA_TRACK_TYPE_VIDEO: {
834 GstMatroskaTrackVideoContext *videocontext =
835 (GstMatroskaTrackVideoContext *) context;
836 padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
837 templ = gst_element_class_get_pad_template (klass, "video_%02d");
838 caps = gst_matroska_demux_video_caps (videocontext,
841 context->codec_priv_size,
846 case GST_MATROSKA_TRACK_TYPE_AUDIO: {
847 GstMatroskaTrackAudioContext *audiocontext =
848 (GstMatroskaTrackAudioContext *) context;
849 padname = g_strdup_printf ("audio_%02d", demux->num_a_streams++);
850 templ = gst_element_class_get_pad_template (klass, "audio_%02d");
851 caps = gst_matroska_demux_audio_caps (audiocontext,
854 context->codec_priv_size,
859 case GST_MATROSKA_TRACK_TYPE_COMPLEX: {
860 GstMatroskaTrackComplexContext *complexcontext =
861 (GstMatroskaTrackComplexContext *) context;
862 padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
863 templ = gst_element_class_get_pad_template (klass, "video_%02d");
864 caps = gst_matroska_demux_complex_caps (complexcontext,
867 context->codec_priv_size);
871 case GST_MATROSKA_TRACK_TYPE_SUBTITLE: {
872 GstMatroskaTrackSubtitleContext *subtitlecontext =
873 (GstMatroskaTrackSubtitleContext *) context;
874 padname = g_strdup_printf ("subtitle_%02d", demux->num_t_streams++);
875 templ = gst_element_class_get_pad_template (klass, "subtitle_%02d");
876 caps = gst_matroska_demux_subtitle_caps (subtitlecontext,
879 context->codec_priv_size);
883 case GST_MATROSKA_TRACK_TYPE_LOGO:
884 case GST_MATROSKA_TRACK_TYPE_CONTROL:
886 /* we should already have quit by now */
890 /* the pad in here */
891 context->pad = gst_pad_new_from_template (templ, padname);
892 context->caps = caps ? caps : gst_caps_new_empty ();
896 /* set some functions */
897 gst_pad_set_formats_function (context->pad,
898 gst_matroska_demux_get_src_formats);
899 gst_pad_set_event_mask_function (context->pad,
900 gst_matroska_demux_get_event_mask);
901 gst_pad_set_event_function (context->pad,
902 gst_matroska_demux_handle_src_event);
903 gst_pad_set_query_type_function (context->pad,
904 gst_matroska_demux_get_src_query_types);
905 gst_pad_set_query_function (context->pad,
906 gst_matroska_demux_handle_src_query);
907 gst_pad_set_getcaps_function (context->pad,
908 gst_matroska_demux_src_getcaps);
910 gst_element_add_pad (GST_ELEMENT (demux), context->pad);
916 static const GstFormat *
917 gst_matroska_demux_get_src_formats (GstPad *pad)
919 /*GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));*/
921 /* we could try to look for units (i.e. samples) in audio streams
922 * or video streams, but both samplerate and framerate are not
923 * always constant, and since we only have a time indication, we
924 * cannot guarantee anything here based purely on index. So, we
925 * only support time for now. */
926 static const GstFormat src_formats[] = {
934 static const GstQueryType *
935 gst_matroska_demux_get_src_query_types (GstPad *pad)
937 static const GstQueryType src_types[] = {
947 gst_matroska_demux_handle_src_query (GstPad *pad,
953 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
956 case GST_QUERY_TOTAL:
958 case GST_FORMAT_DEFAULT:
959 *format = GST_FORMAT_TIME;
961 case GST_FORMAT_TIME:
962 *value = demux->duration;
970 case GST_QUERY_POSITION:
972 case GST_FORMAT_DEFAULT:
973 *format = GST_FORMAT_TIME;
975 case GST_FORMAT_TIME:
992 static GstMatroskaIndex *
993 gst_matroskademux_seek (GstMatroskaDemux *demux)
995 guint entry = (guint) -1;
996 guint64 offset = demux->seek_pending;
999 /* make sure we don't seek twice */
1000 demux->seek_pending = GST_CLOCK_TIME_NONE;
1002 for (n = 0; n < demux->num_indexes; n++) {
1003 if (entry == (guint) -1) {
1006 gfloat diff_old = fabs (1. * (demux->index[entry].time - offset)),
1007 diff_new = fabs (1. * (demux->index[n].time - offset));
1009 if (diff_new < diff_old) {
1015 if (entry != (guint) -1) {
1016 return &demux->index[entry];
1023 gst_matroska_demux_send_event (GstElement *element,
1026 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
1027 gboolean res = TRUE;
1029 switch (GST_EVENT_TYPE (event)) {
1030 case GST_EVENT_SEEK:
1031 switch (GST_EVENT_SEEK_FORMAT (event)) {
1032 case GST_FORMAT_TIME:
1033 demux->seek_pending = GST_EVENT_SEEK_OFFSET (event);
1037 GST_WARNING ("Only time seek is supported");
1044 GST_WARNING ("Unhandled event of type %d",
1045 GST_EVENT_TYPE (event));
1050 gst_event_unref (event);
1055 static const GstEventMask *
1056 gst_matroska_demux_get_event_mask (GstPad *pad)
1058 static const GstEventMask masks[] = {
1059 { GST_EVENT_SEEK, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1060 (gint) GST_SEEK_FLAG_KEY_UNIT) },
1061 { GST_EVENT_SEEK_SEGMENT, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1062 (gint) GST_SEEK_FLAG_KEY_UNIT) },
1063 { (GstEventType) 0, (GstEventFlag) 0 }
1070 gst_matroska_demux_handle_src_event (GstPad *pad,
1073 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
1074 gboolean res = TRUE;
1076 switch (GST_EVENT_TYPE (event)) {
1077 case GST_EVENT_SEEK_SEGMENT:
1078 case GST_EVENT_SEEK:
1079 return gst_matroska_demux_send_event (GST_ELEMENT (demux), event);
1082 GST_WARNING ("Unhandled event of type %d",
1083 GST_EVENT_TYPE (event));
1088 gst_event_unref (event);
1094 gst_matroska_demux_handle_seek_event (GstMatroskaDemux *demux)
1096 GstEbmlRead *ebml = GST_EBML_READ (demux);
1097 GstMatroskaIndex *entry = gst_matroskademux_seek (demux);
1104 /* seek (relative to segment) */
1105 if (!(event = gst_ebml_read_seek (ebml,
1106 entry->pos + demux->segment_start)))
1108 gst_event_unref (event); /* byte - we want time */
1109 event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
1112 /* forward to all src pads */
1113 for (i = 0; i < demux->num_streams; i++) {
1114 if (GST_PAD_IS_USABLE (demux->src[i]->pad)) {
1115 gst_event_ref (event);
1116 gst_pad_push (demux->src[i]->pad, GST_DATA (event));
1120 gst_event_unref (event);
1126 gst_matroska_demux_init_stream (GstMatroskaDemux *demux)
1128 GstEbmlRead *ebml = GST_EBML_READ (demux);
1133 if (!gst_ebml_read_header (ebml, &doctype, &version))
1136 if (!doctype || strcmp (doctype, "matroska") != 0) {
1137 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1138 ("Input is not a matroska stream (doctype=%s)",
1139 doctype ? doctype : "none"));
1145 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1146 ("Demuxer version (1) is too old to read stream version %d",
1151 /* find segment, must be the next element */
1155 if (!(id = gst_ebml_peek_id (ebml, &last_level)))
1158 if (id == GST_MATROSKA_ID_SEGMENT)
1162 GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
1163 GST_MATROSKA_ID_SEGMENT, id);
1164 if (!gst_ebml_read_skip (ebml))
1168 /* we now have a EBML segment */
1169 if (!gst_ebml_read_master (ebml, &id))
1171 /* seeks are from the beginning of the segment,
1172 * after the segment ID/length */
1173 demux->segment_start = gst_bytestream_tell (ebml->bs);
1179 gst_matroska_demux_parse_tracks (GstMatroskaDemux *demux)
1181 GstEbmlRead *ebml = GST_EBML_READ (demux);
1182 gboolean res = TRUE;
1186 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1189 } else if (demux->level_up) {
1195 /* one track within the "all-tracks" header */
1196 case GST_MATROSKA_ID_TRACKENTRY:
1197 if (!gst_matroska_demux_add_stream (demux))
1202 GST_WARNING ("Unknown entry 0x%x in track header", id);
1205 case GST_EBML_ID_VOID:
1206 if (!gst_ebml_read_skip (ebml))
1211 if (demux->level_up) {
1221 gst_matroska_demux_parse_index (GstMatroskaDemux *demux,
1222 gboolean prevent_eos)
1224 GstEbmlRead *ebml = GST_EBML_READ (demux);
1225 gboolean res = TRUE;
1227 GstMatroskaIndex idx;
1231 length = gst_bytestream_length (ebml->bs);
1235 /* We're an element that can be seeked to. If we are, then
1236 * we want to prevent EOS, since that'll kill us. So we cache
1237 * file size and seek until there, and don't call EOS upon os. */
1238 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1241 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1244 } else if (demux->level_up) {
1250 /* one single index entry ('point') */
1251 case GST_MATROSKA_ID_POINTENTRY:
1252 if (!gst_ebml_read_master (ebml, &id)) {
1257 /* in the end, we hope to fill one entry with a
1258 * timestamp, a file position and a tracknum */
1259 idx.pos = (guint64) -1;
1260 idx.time = (guint64) -1;
1261 idx.track = (guint16) -1;
1264 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1267 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1270 } else if (demux->level_up) {
1276 /* one single index entry ('point') */
1277 case GST_MATROSKA_ID_CUETIME: {
1279 if (!gst_ebml_read_uint (ebml, &id, &time)) {
1283 idx.time = time * demux->time_scale;
1287 /* position in the file + track to which it belongs */
1288 case GST_MATROSKA_ID_CUETRACKPOSITION:
1289 if (!gst_ebml_read_master (ebml, &id)) {
1295 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1298 } else if (!(id = gst_ebml_peek_id (ebml,
1299 &demux->level_up))) {
1302 } else if (demux->level_up) {
1309 case GST_MATROSKA_ID_CUETRACK: {
1311 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1319 /* position in file */
1320 case GST_MATROSKA_ID_CUECLUSTERPOSITION: {
1322 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1331 GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions", id);
1334 case GST_EBML_ID_VOID:
1335 if (!gst_ebml_read_skip (ebml))
1340 if (demux->level_up) {
1349 GST_WARNING ("Unknown entry 0x%x in cuespoint index", id);
1352 case GST_EBML_ID_VOID:
1353 if (!gst_ebml_read_skip (ebml))
1358 if (demux->level_up) {
1364 /* so let's see if we got what we wanted */
1365 if (idx.pos != (guint64) -1 &&
1366 idx.time != (guint64) -1 &&
1367 idx.track != (guint16) -1) {
1368 if (demux->num_indexes % 32 == 0) {
1369 /* re-allocate bigger index */
1370 demux->index = g_renew (GstMatroskaIndex, demux->index,
1371 demux->num_indexes + 32);
1373 demux->index[demux->num_indexes].pos = idx.pos;
1374 demux->index[demux->num_indexes].time = idx.time;
1375 demux->index[demux->num_indexes].track = idx.track;
1376 demux->num_indexes++;
1382 GST_WARNING ("Unknown entry 0x%x in cues header", id);
1385 case GST_EBML_ID_VOID:
1386 if (!gst_ebml_read_skip (ebml))
1391 if (demux->level_up) {
1401 gst_matroska_demux_parse_info (GstMatroskaDemux *demux)
1403 GstEbmlRead *ebml = GST_EBML_READ (demux);
1404 gboolean res = TRUE;
1408 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1411 } else if (demux->level_up) {
1417 /* cluster timecode */
1418 case GST_MATROSKA_ID_TIMECODESCALE: {
1420 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1424 demux->time_scale = num;
1428 case GST_MATROSKA_ID_DURATION: {
1430 if (!gst_ebml_read_float (ebml, &id, &num)) {
1434 demux->duration = num * demux->time_scale;
1438 case GST_MATROSKA_ID_WRITINGAPP: {
1440 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1444 demux->writing_app = text;
1448 case GST_MATROSKA_ID_MUXINGAPP: {
1450 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1454 demux->muxing_app = text;
1458 case GST_MATROSKA_ID_DATEUTC: {
1460 if (!gst_ebml_read_date (ebml, &id, &time)) {
1464 demux->created = time;
1469 GST_WARNING ("Unknown entry 0x%x in info header", id);
1472 case GST_EBML_ID_VOID:
1473 if (!gst_ebml_read_skip (ebml))
1478 if (demux->level_up) {
1488 gst_matroska_demux_parse_metadata (GstMatroskaDemux *demux,
1489 gboolean prevent_eos)
1491 GstEbmlRead *ebml = GST_EBML_READ (demux);
1492 gboolean res = TRUE;
1497 length = gst_bytestream_length (ebml->bs);
1501 /* We're an element that can be seeked to. If we are, then
1502 * we want to prevent EOS, since that'll kill us. So we cache
1503 * file size and seek until there, and don't call EOS upon os. */
1504 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1507 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1510 } else if (demux->level_up) {
1517 GST_WARNING ("metadata unimplemented");
1520 case GST_EBML_ID_VOID:
1521 if (!gst_ebml_read_skip (ebml))
1526 if (demux->level_up) {
1536 * Read signed/unsigned "EBML" numbers.
1537 * Return: number of bytes processed.
1541 gst_matroska_ebmlnum_uint (guint8 *data,
1545 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1553 while (read <= 8 && !(total & len_mask)) {
1560 if ((total &= (len_mask - 1)) == len_mask - 1)
1565 if (data[n] == 0xff)
1567 total = (total << 8) | data[n];
1574 if (read == num_ffs)
1583 gst_matroska_ebmlnum_sint (guint8 *data,
1590 /* read as unsigned number first */
1591 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1595 if (unum == G_MAXUINT64)
1598 *num = unum - ((1 << ((7 * res) - 1)) - 1);
1604 gst_matroska_demux_parse_blockgroup (GstMatroskaDemux *demux,
1605 guint64 cluster_time)
1607 GstEbmlRead *ebml = GST_EBML_READ (demux);
1608 gboolean res = TRUE;
1612 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1615 } else if (demux->level_up) {
1621 /* one block inside the group. Note, block parsing is one
1622 * of the harder things, so this code is a bit complicated.
1623 * See http://www.matroska.org/ for documentation. */
1624 case GST_MATROSKA_ID_BLOCK: {
1628 guint size, *lace_size = NULL;
1629 gint n, stream, flags, laces = 0;
1632 if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
1636 data = GST_BUFFER_DATA (buf);
1637 size = GST_BUFFER_SIZE (buf);
1639 /* first byte(s): blocknum */
1640 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1641 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1642 gst_buffer_unref (buf);
1646 data += n; size -= n;
1648 /* fetch stream from num */
1649 stream = gst_matroska_demux_stream_from_num (demux, num);
1650 if (size <= 3 || stream < 0 || stream >= demux->num_streams) {
1651 gst_buffer_unref (buf);
1652 GST_WARNING ("Invalid stream %d or size %u", stream, size);
1655 if (!GST_PAD_IS_USABLE (demux->src[stream]->pad)) {
1656 gst_buffer_unref (buf);
1660 /* time (relative to cluster time) */
1661 time = (GINT16_FROM_BE (* (gint16 *) data)) * demux->time_scale;
1662 data += 2; size -= 2;
1663 flags = * (guint8 *) data;
1664 data += 1; size -= 1;
1665 switch ((flags & 0x06) >> 1) {
1666 case 0x0: /* no lacing */
1668 lace_size = g_new (gint, 1);
1669 lace_size[0] = size;
1672 case 0x1: /* xiph lacing */
1673 case 0x2: /* fixed-size lacing */
1674 case 0x3: /* EBML lacing */
1679 laces = (* (guint8 *) data) + 1;
1680 data += 1; size -= 1;
1681 lace_size = g_new0 (gint, laces);
1683 switch ((flags & 0x06) >> 1) {
1684 case 0x1: /* xiph lacing */ {
1685 guint temp, total = 0;
1686 for (n = 0; res && n < laces - 1; n++) {
1692 temp = * (guint8 *) data;
1693 lace_size[n] += temp;
1694 data += 1; size -= 1;
1698 total += lace_size[n];
1700 lace_size[n] = size - total;
1704 case 0x2: /* fixed-size lacing */
1705 for (n = 0; n < laces; n++)
1706 lace_size[n] = size / laces;
1709 case 0x3: /* EBML lacing */ {
1711 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1712 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1716 data += n; size -= n;
1717 total = lace_size[0] = num;
1718 for (n = 1; res && n < laces - 1; n++) {
1721 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
1722 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1726 data += r; size -= r;
1727 lace_size[n] = lace_size[n - 1] + snum;
1728 total += lace_size[n];
1730 lace_size[n] = size - total;
1738 for (n = 0; n < laces; n++) {
1739 GstBuffer *sub = gst_buffer_create_sub (buf,
1740 GST_BUFFER_SIZE (buf) - size,
1743 if (cluster_time != GST_CLOCK_TIME_NONE) {
1744 if (time < 0 && (-time) > cluster_time)
1745 GST_BUFFER_TIMESTAMP (sub) = cluster_time;
1747 GST_BUFFER_TIMESTAMP (sub) = cluster_time + time;
1749 /* FIXME: duration */
1751 gst_pad_push (demux->src[stream]->pad, GST_DATA (sub));
1753 size -= lace_size[n];
1758 gst_buffer_unref (buf);
1762 case GST_MATROSKA_ID_BLOCKDURATION: {
1764 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1768 GST_WARNING ("FIXME: implement support for BlockDuration");
1773 GST_WARNING ("Unknown entry 0x%x in blockgroup data", id);
1776 case GST_EBML_ID_VOID:
1777 if (!gst_ebml_read_skip (ebml))
1782 if (demux->level_up) {
1792 gst_matroska_demux_parse_cluster (GstMatroskaDemux *demux)
1794 GstEbmlRead *ebml = GST_EBML_READ (demux);
1795 gboolean res = TRUE;
1797 guint64 cluster_time = GST_CLOCK_TIME_NONE;
1799 /* We seek after index/header parsing before doing a new
1800 * buffer. So here. */
1801 if (demux->seek_pending != GST_CLOCK_TIME_NONE) {
1802 if (!gst_matroska_demux_handle_seek_event (demux))
1804 demux->seek_pending = GST_CLOCK_TIME_NONE;
1808 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1811 } else if (demux->level_up) {
1817 /* cluster timecode */
1818 case GST_MATROSKA_ID_CLUSTERTIMECODE: {
1820 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1824 cluster_time = num * demux->time_scale;
1828 /* a group of blocks inside a cluster */
1829 case GST_MATROSKA_ID_BLOCKGROUP:
1830 if (!gst_ebml_read_master (ebml, &id)) {
1834 res = gst_matroska_demux_parse_blockgroup (demux, cluster_time);
1838 GST_WARNING ("Unknown entry 0x%x in cluster data", id);
1841 case GST_EBML_ID_VOID:
1842 if (!gst_ebml_read_skip (ebml))
1847 if (demux->level_up) {
1857 gst_matroska_demux_parse_contents (GstMatroskaDemux *demux)
1859 GstEbmlRead *ebml = GST_EBML_READ (demux);
1860 gboolean res = TRUE;
1864 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1867 } else if (demux->level_up) {
1873 case GST_MATROSKA_ID_SEEKENTRY: {
1874 guint32 seek_id = 0;
1875 guint64 seek_pos = (guint64) -1, t;
1877 if (!gst_ebml_read_master (ebml, &id)) {
1883 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1886 } else if (demux->level_up) {
1892 case GST_MATROSKA_ID_SEEKID:
1893 if (!gst_ebml_read_uint (ebml, &id, &t))
1898 case GST_MATROSKA_ID_SEEKPOSITION:
1899 if (!gst_ebml_read_uint (ebml, &id, &seek_pos))
1904 GST_WARNING ("Unknown seekhead ID 0x%x", id);
1907 case GST_EBML_ID_VOID:
1908 if (!gst_ebml_read_skip (ebml))
1913 if (demux->level_up) {
1919 if (!seek_id || seek_pos == (guint64) -1) {
1920 GST_WARNING ("Incomplete seekhead entry (0x%x/%"
1921 G_GUINT64_FORMAT ")", seek_id, seek_pos);
1926 case GST_MATROSKA_ID_CUES:
1927 case GST_MATROSKA_ID_TAGS: {
1928 guint level_up = demux->level_up;
1929 guint64 before_pos, length;
1930 GstEbmlLevel *level;
1934 length = gst_bytestream_length (ebml->bs);
1935 before_pos = gst_bytestream_tell (ebml->bs);
1937 /* check for validity */
1938 if (seek_pos + demux->segment_start + 12 >= length) {
1939 g_warning ("Seekhead reference lies outside file!");
1944 if (!(event = gst_ebml_read_seek (ebml,
1945 seek_pos + demux->segment_start)))
1947 gst_event_unref (event);
1949 /* we don't want to lose our seekhead level, so we add
1950 * a dummy. This is a crude hack. */
1951 level = g_new (GstEbmlLevel, 1);
1953 level->length = G_MAXUINT64;
1954 ebml->level = g_list_append (ebml->level, level);
1957 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1961 if (id != seek_id) {
1962 g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%llu)",
1963 seek_id, id, seek_pos + demux->segment_start);
1967 /* read master + parse */
1969 case GST_MATROSKA_ID_CUES:
1970 if (!gst_ebml_read_master (ebml, &id))
1972 else if (!gst_matroska_demux_parse_index (demux, TRUE) &&
1973 gst_bytestream_length (ebml->bs) !=
1974 gst_bytestream_tell (ebml->bs))
1977 demux->index_parsed = TRUE;
1979 case GST_MATROSKA_ID_TAGS:
1980 if (!gst_ebml_read_master (ebml, &id))
1982 else if (!gst_matroska_demux_parse_metadata (demux, TRUE) &&
1983 gst_bytestream_length (ebml->bs) !=
1984 gst_bytestream_tell (ebml->bs))
1987 demux->metadata_parsed = TRUE;
1994 /* remove dummy level */
1995 while (ebml->level) {
1997 level = g_list_last (ebml->level)->data;
1998 ebml->level = g_list_remove (ebml->level, level);
1999 length = level->length;
2001 if (length == G_MAXUINT64)
2006 if (!(event = gst_ebml_read_seek (ebml, before_pos)))
2008 gst_event_unref (event);
2009 demux->level_up = level_up;
2014 GST_INFO ("Ignoring seekhead entry for ID=0x%x", seek_id);
2022 GST_WARNING ("Unknown seekhead ID 0x%x", id);
2025 case GST_EBML_ID_VOID:
2026 if (!gst_ebml_read_skip (ebml))
2031 if (demux->level_up) {
2041 gst_matroska_demux_loop_stream (GstMatroskaDemux *demux)
2043 GstEbmlRead *ebml = GST_EBML_READ (demux);
2044 gboolean res = TRUE;
2047 /* we've found our segment, start reading the different contents in here */
2049 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2052 } else if (demux->level_up) {
2059 case GST_MATROSKA_ID_INFO: {
2060 if (!gst_ebml_read_master (ebml, &id)) {
2064 res = gst_matroska_demux_parse_info (demux);
2068 /* track info headers */
2069 case GST_MATROSKA_ID_TRACKS: {
2070 if (!gst_ebml_read_master (ebml, &id)) {
2074 res = gst_matroska_demux_parse_tracks (demux);
2079 case GST_MATROSKA_ID_CUES: {
2080 if (!demux->index_parsed) {
2081 if (!gst_ebml_read_master (ebml, &id)) {
2085 res = gst_matroska_demux_parse_index (demux, FALSE);
2087 res = gst_ebml_read_skip (ebml);
2092 case GST_MATROSKA_ID_TAGS: {
2093 if (!demux->index_parsed) {
2094 if (!gst_ebml_read_master (ebml, &id)) {
2098 res = gst_matroska_demux_parse_metadata (demux, FALSE);
2100 res = gst_ebml_read_skip (ebml);
2104 /* file index (if seekable, seek to Cues/Tags to parse it) */
2105 case GST_MATROSKA_ID_SEEKHEAD: {
2106 if (!gst_ebml_read_master (ebml, &id)) {
2110 res = gst_matroska_demux_parse_contents (demux);
2114 case GST_MATROSKA_ID_CLUSTER: {
2115 if (!gst_ebml_read_master (ebml, &id)) {
2119 /* The idea is that we parse one cluster per loop and
2120 * then break out of the loop here. In the next call
2121 * of the loopfunc, we will get back here with the
2122 * next cluster. If an error occurs, we didn't
2123 * actually push a buffer, but we still want to break
2124 * out of the loop to handle a possible error. We'll
2125 * get back here if it's recoverable. */
2126 gst_matroska_demux_parse_cluster (demux);
2127 demux->state = GST_MATROSKA_DEMUX_STATE_DATA;
2133 GST_WARNING ("Unknown matroska file header ID 0x%x", id);
2136 case GST_EBML_ID_VOID:
2137 if (!gst_ebml_read_skip (ebml))
2142 if (demux->level_up) {
2152 gst_matroska_demux_loop (GstElement *element)
2154 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2156 /* first, if we're to start, let's actually get starting */
2157 if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
2158 if (!gst_matroska_demux_init_stream (demux)) {
2161 demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
2164 gst_matroska_demux_loop_stream (demux);
2168 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *videocontext,
2169 const gchar *codec_id,
2172 GstMatroskaDemux *demux)
2174 GstMatroskaTrackContext *context =
2175 (GstMatroskaTrackContext *) videocontext;
2176 GstCaps *caps = NULL;
2178 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
2179 gst_riff_strf_vids *vids = NULL;
2182 char *codec_name = NULL;
2183 GstTagList *list = gst_tag_list_new ();
2185 vids = (gst_riff_strf_vids *) data;
2187 /* assure size is big enough */
2189 GST_WARNING ("Too small BITMAPINFOHEADER (%d bytes)", size);
2192 if (size < sizeof (gst_riff_strf_vids)) {
2193 vids = (gst_riff_strf_vids *) g_realloc (vids, sizeof (gst_riff_strf_vids));
2196 /* little-endian -> byte-order */
2197 vids->size = GUINT32_FROM_LE (vids->size);
2198 vids->width = GUINT32_FROM_LE (vids->width);
2199 vids->height = GUINT32_FROM_LE (vids->height);
2200 vids->planes = GUINT16_FROM_LE (vids->planes);
2201 vids->bit_cnt = GUINT16_FROM_LE (vids->bit_cnt);
2202 vids->compression = GUINT32_FROM_LE (vids->compression);
2203 vids->image_size = GUINT32_FROM_LE (vids->image_size);
2204 vids->xpels_meter = GUINT32_FROM_LE (vids->xpels_meter);
2205 vids->ypels_meter = GUINT32_FROM_LE (vids->ypels_meter);
2206 vids->num_colors = GUINT32_FROM_LE (vids->num_colors);
2207 vids->imp_colors = GUINT32_FROM_LE (vids->imp_colors);
2209 caps = gst_riff_create_video_caps (vids->compression, NULL, vids,
2211 gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
2213 if (GST_IS_ELEMENT (demux))
2214 gst_element_found_tags (GST_ELEMENT (demux), list);
2215 gst_tag_list_free (list);
2216 if (codec_name) g_free (codec_name);
2218 caps = gst_riff_create_video_template_caps ();
2220 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
2221 /* how nice, this is undocumented... */
2222 if (videocontext != NULL) {
2225 switch (videocontext->fourcc) {
2226 case GST_MAKE_FOURCC ('I','4','2','0'):
2227 case GST_MAKE_FOURCC ('Y','U','Y','2'):
2228 fourcc = videocontext->fourcc;
2232 GST_DEBUG ("Unknown fourcc " GST_FOURCC_FORMAT,
2233 GST_FOURCC_ARGS (videocontext->fourcc));
2237 caps = gst_caps_new_simple ("video/x-raw-yuv",
2238 "format", GST_TYPE_FOURCC, fourcc, NULL);
2240 caps = gst_caps_from_string ("video/x-raw-yuv, "
2241 "format = (fourcc) { I420, YUY2, YV12 }");
2243 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) {
2244 caps = gst_caps_new_simple ("video/x-divx",
2245 "divxversion", G_TYPE_INT, 4, NULL);
2246 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) ||
2247 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) {
2248 caps = gst_caps_new_full (
2249 gst_structure_new ("video/x-divx",
2250 "divxversion", G_TYPE_INT, 5, NULL),
2251 gst_structure_new ("video/x-xvid", NULL),
2252 gst_structure_new ("video/mpeg",
2253 "mpegversion", G_TYPE_INT, 4,
2254 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL),
2256 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) {
2257 caps = gst_caps_new_full (
2258 gst_structure_new ("video/x-divx",
2259 "divxversion", G_TYPE_INT, 3, NULL),
2260 gst_structure_new ("video/x-msmpeg",
2261 "msmpegversion", G_TYPE_INT, 43, NULL),
2263 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1) ||
2264 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2)) {
2265 gint mpegversion = -1;
2267 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1))
2269 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2))
2274 caps = gst_caps_new_simple ("video/mpeg",
2275 "systemstream", G_TYPE_BOOLEAN, FALSE,
2276 "mpegversion", G_TYPE_INT, mpegversion, NULL);
2277 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) {
2278 caps = gst_caps_new_simple ("video/x-jpeg", NULL);
2280 GST_WARNING ("Unknown codec '%s', cannot build Caps",
2287 GstStructure *structure;
2289 for (i=0;i<gst_caps_get_size(caps);i++){
2290 structure = gst_caps_get_structure (caps, i);
2291 if (videocontext != NULL) {
2292 if (videocontext->pixel_width > 0 &&
2293 videocontext->pixel_height > 0) {
2294 gint w = videocontext->pixel_width;
2295 gint h = videocontext->pixel_height;
2297 gst_structure_set (structure,
2298 "width", G_TYPE_INT, w,
2299 "height", G_TYPE_INT, h, NULL);
2301 gst_structure_set (structure,
2302 "width", GST_TYPE_INT_RANGE, 16, 4096,
2303 "height", GST_TYPE_INT_RANGE, 16, 4096,
2307 if (videocontext->display_width > 0 &&
2308 videocontext->display_height > 0) {
2309 gint w = 100 * videocontext->display_width / videocontext->pixel_width;
2310 gint h = 100 * videocontext->display_height / videocontext->pixel_height;
2312 gst_structure_set (structure,
2313 "pixel_width", G_TYPE_INT, w,
2314 "pixel_height", G_TYPE_INT, h,
2318 if (context->default_duration > 0) {
2319 gfloat framerate = 1. * GST_SECOND / context->default_duration;
2321 gst_structure_set (structure,
2322 "framerate", G_TYPE_DOUBLE, framerate, NULL);
2324 /* sort of a hack to get most codecs to support,
2325 * even if the default_duration is missing */
2326 gst_structure_set (structure,
2327 "framerate", G_TYPE_DOUBLE, 25.0, NULL);
2330 gst_structure_set (structure,
2331 "width", GST_TYPE_INT_RANGE, 16, 4096,
2332 "height", GST_TYPE_INT_RANGE, 16, 4096,
2333 "pixel_width", GST_TYPE_INT_RANGE, 0, 255,
2334 "pixel_height", GST_TYPE_INT_RANGE, 0, 255,
2335 "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE,
2345 gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *audiocontext,
2346 const gchar *codec_id,
2349 GstMatroskaDemux *demux)
2351 GstMatroskaTrackContext *context =
2352 (GstMatroskaTrackContext *) audiocontext;
2353 GstCaps *caps = NULL;
2355 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
2356 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
2357 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
2360 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1))
2362 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2))
2364 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3))
2369 caps = gst_caps_new_simple ("audio/mpeg",
2370 "mpegversion", G_TYPE_INT, 1,
2371 "layer", G_TYPE_INT, layer, NULL);
2372 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) ||
2373 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) {
2374 gint endianness = -1;
2376 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE))
2377 endianness = G_BIG_ENDIAN;
2378 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE))
2379 endianness = G_LITTLE_ENDIAN;
2383 if (context != NULL) {
2384 caps = gst_caps_new_simple ("audio/x-raw-int",
2385 "width", G_TYPE_INT, audiocontext->bitdepth,
2386 "depth", G_TYPE_INT, audiocontext->bitdepth,
2387 "signed", G_TYPE_BOOLEAN, audiocontext->bitdepth == 8, NULL);
2389 caps = gst_caps_from_string ("audio/x-raw-int, "
2390 "signed = (boolean) { TRUE, FALSE }, "
2391 "depth = (int) { 8, 16 }, "
2392 "width = (int) { 8, 16 }");
2394 gst_caps_set_simple (caps, "endianness", G_TYPE_INT, endianness, NULL);
2395 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
2396 caps = gst_caps_new_simple ("audio/x-raw-float",
2397 "endianness", G_TYPE_INT, G_BYTE_ORDER,
2398 "buffer-frames", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
2399 if (audiocontext != NULL) {
2400 gst_caps_set_simple (caps,
2401 "width", G_TYPE_INT, audiocontext->bitdepth, NULL);
2403 gst_caps_set_simple (caps,
2404 "width", GST_TYPE_INT_RANGE, 32, 64, NULL);
2406 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AC3) ||
2407 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) {
2408 caps = gst_caps_new_simple ("audio/x-ac3", NULL);
2409 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
2410 caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
2411 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
2412 gst_riff_strf_auds *auds = NULL;
2415 char *codec_name = NULL;
2416 GstTagList *list = gst_tag_list_new ();
2418 auds = (gst_riff_strf_auds *) data;
2420 /* little-endian -> byte-order */
2421 auds->format = GUINT16_FROM_LE (auds->format);
2422 auds->channels = GUINT16_FROM_LE (auds->channels);
2423 auds->rate = GUINT32_FROM_LE (auds->rate);
2424 auds->av_bps = GUINT32_FROM_LE (auds->av_bps);
2425 auds->blockalign = GUINT16_FROM_LE (auds->blockalign);
2426 auds->size = GUINT16_FROM_LE (auds->size);
2428 caps = gst_riff_create_audio_caps (auds->format, NULL, auds, &codec_name);
2429 gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_AUDIO_CODEC,
2431 if (GST_IS_ELEMENT (demux))
2432 gst_element_found_tags (GST_ELEMENT (demux), list);
2433 gst_tag_list_free (list);
2434 if (codec_name) g_free (codec_name);
2436 caps = gst_riff_create_audio_template_caps ();
2438 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2439 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)) ||
2440 !strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2441 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4))) {
2442 gint mpegversion = -1;
2444 if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2445 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)))
2447 else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2448 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4)))
2453 caps = gst_caps_new_simple ("audio/mpeg",
2454 "mpegversion", G_TYPE_INT, mpegversion, NULL);
2456 GST_WARNING ("Unknown codec '%s', cannot build Caps",
2462 GstStructure *structure;
2465 for (i=0; i<gst_caps_get_size(caps); i++){
2466 structure = gst_caps_get_structure (caps, i);
2467 if (audiocontext != NULL) {
2468 if (audiocontext->samplerate > 0 &&
2469 audiocontext->channels > 0) {
2470 gst_structure_set (structure,
2471 "channels", G_TYPE_INT, audiocontext->channels,
2472 "rate", G_TYPE_INT, audiocontext->samplerate,
2476 gst_structure_set (structure,
2477 "channels", GST_TYPE_INT_RANGE, 1, 6,
2478 "rate", GST_TYPE_INT_RANGE, 4000, 96000,
2488 gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext *complexcontext,
2489 const gchar *codec_id,
2493 GstCaps *caps = NULL;
2501 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *subtitlecontext,
2502 const gchar *codec_id,
2506 GstCaps *caps = NULL;
2513 static GstElementStateReturn
2514 gst_matroska_demux_change_state (GstElement *element)
2516 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2518 switch (GST_STATE_TRANSITION (element)) {
2519 case GST_STATE_PAUSED_TO_READY:
2520 gst_matroska_demux_reset (GST_ELEMENT (demux));
2526 if (((GstElementClass *) parent_class)->change_state)
2527 return ((GstElementClass *) parent_class)->change_state (element);
2529 return GST_STATE_SUCCESS;
2533 gst_matroska_demux_get_property (GObject *object,
2538 GstMatroskaDemux *demux;
2540 g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
2541 demux = GST_MATROSKA_DEMUX (object);
2544 case ARG_STREAMINFO:
2545 g_value_set_boxed (value, demux->streaminfo);
2548 g_value_set_boxed (value, demux->metadata);
2551 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2557 gst_matroska_demux_plugin_init (GstPlugin *plugin)
2560 GstCaps *videosrccaps, *audiosrccaps, *subtitlesrccaps, *temp;
2561 const gchar *video_id[] = {
2562 GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC,
2563 GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED,
2564 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP,
2565 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP,
2566 GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3,
2567 GST_MATROSKA_CODEC_ID_VIDEO_MPEG1,
2568 GST_MATROSKA_CODEC_ID_VIDEO_MPEG2,
2569 GST_MATROSKA_CODEC_ID_VIDEO_MJPEG,
2570 /* TODO: Real/Quicktime */
2574 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1,
2575 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2,
2576 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3,
2577 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE,
2578 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE,
2579 GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT,
2580 GST_MATROSKA_CODEC_ID_AUDIO_AC3,
2581 GST_MATROSKA_CODEC_ID_AUDIO_ACM,
2582 GST_MATROSKA_CODEC_ID_AUDIO_VORBIS,
2583 GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2584 GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2585 /* TODO: AC3-9/10, Real, Musepack, Quicktime */
2588 }, *complex_id[] = {
2591 }, *subtitle_id[] = {
2596 /* this filter needs the riff parser */
2597 if (!gst_library_load ("gstbytestream") ||
2598 !gst_library_load ("riff")) /* for fourcc stuff */
2601 /* video src template */
2602 videosrccaps = gst_caps_new_empty ();
2603 for (i = 0; video_id[i] != NULL; i++) {
2604 temp = gst_matroska_demux_video_caps (NULL, video_id[i], NULL, 0, NULL);
2605 gst_caps_append (videosrccaps, temp);
2607 for (i = 0; complex_id[i] != NULL; i++) {
2608 temp = gst_matroska_demux_complex_caps (NULL, video_id[i], NULL, 0);
2609 gst_caps_append (videosrccaps, temp);
2611 videosrctempl = gst_pad_template_new ("video_%02d",
2616 audiosrccaps = gst_caps_new_empty ();
2617 /* audio src template */
2618 for (i = 0; audio_id[i] != NULL; i++) {
2619 temp = gst_matroska_demux_audio_caps (NULL, audio_id[i], NULL, 0, NULL);
2620 gst_caps_append (audiosrccaps, temp);
2622 audiosrctempl = gst_pad_template_new ("audio_%02d",
2627 subtitlesrccaps = gst_caps_new_empty ();
2628 /* subtitle src template */
2629 for (i = 0; subtitle_id[i] != NULL; i++) {
2630 temp = gst_matroska_demux_subtitle_caps (NULL, subtitle_id[i], NULL, 0);
2631 gst_caps_append (subtitlesrccaps, temp);
2633 subtitlesrctempl = gst_pad_template_new ("subtitle_%02d",
2638 /* create an elementfactory for the matroska_demux element */
2639 if (!gst_element_register (plugin, "matroskademux",
2640 GST_RANK_PRIMARY, GST_TYPE_MATROSKA_DEMUX))