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 static GstCaps *gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext
100 const gchar *codec_id,
103 static GstCaps *gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext
105 const gchar *codec_id,
108 static GstCaps *gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext
110 const gchar *codec_id,
115 static void gst_matroska_demux_reset (GstElement *element);
117 static GstEbmlReadClass *parent_class = NULL;
118 static GstPadTemplate *videosrctempl, *audiosrctempl, *subtitlesrctempl;
119 /*static guint gst_matroska_demux_signals[LAST_SIGNAL] = { 0 };*/
122 gst_matroska_demux_get_type (void)
124 static GType gst_matroska_demux_type = 0;
126 if (!gst_matroska_demux_type) {
127 static const GTypeInfo gst_matroska_demux_info = {
128 sizeof (GstMatroskaDemuxClass),
129 (GBaseInitFunc) gst_matroska_demux_base_init,
131 (GClassInitFunc) gst_matroska_demux_class_init,
134 sizeof (GstMatroskaDemux),
136 (GInstanceInitFunc) gst_matroska_demux_init,
139 gst_matroska_demux_type =
140 g_type_register_static (GST_TYPE_EBML_READ,
142 &gst_matroska_demux_info, 0);
145 return gst_matroska_demux_type;
149 gst_matroska_demux_base_init (GstMatroskaDemuxClass *klass)
151 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
152 static GstElementDetails gst_matroska_demux_details = {
155 "Demuxes a Matroska Stream into video/audio/subtitles",
156 "Ronald Bultje <rbultje@ronald.bitfreak.net>"
159 gst_element_class_add_pad_template (element_class, videosrctempl);
160 gst_element_class_add_pad_template (element_class, audiosrctempl);
161 gst_element_class_add_pad_template (element_class, subtitlesrctempl);
162 gst_element_class_add_pad_template (element_class,
163 gst_static_pad_template_get (&sink_templ));
164 gst_element_class_set_details (element_class,
165 &gst_matroska_demux_details);
169 gst_matroska_demux_class_init (GstMatroskaDemuxClass *klass)
171 GObjectClass *gobject_class;
172 GstElementClass *gstelement_class;
174 gobject_class = (GObjectClass *) klass;
175 gstelement_class = (GstElementClass *) klass;
177 g_object_class_install_property (gobject_class, ARG_METADATA,
178 g_param_spec_boxed ("metadata", "Metadata", "Metadata",
179 GST_TYPE_STRUCTURE, G_PARAM_READABLE));
180 g_object_class_install_property (gobject_class, ARG_STREAMINFO,
181 g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
182 GST_TYPE_STRUCTURE, G_PARAM_READABLE));
184 parent_class = g_type_class_ref (GST_TYPE_EBML_READ);
186 gobject_class->get_property = gst_matroska_demux_get_property;
188 gstelement_class->change_state = gst_matroska_demux_change_state;
189 gstelement_class->send_event = gst_matroska_demux_send_event;
190 gstelement_class->set_clock = gst_matroska_demux_set_clock;
194 gst_matroska_demux_init (GstMatroskaDemux *demux)
196 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
199 GST_FLAG_SET (GST_OBJECT (demux), GST_ELEMENT_EVENT_AWARE);
201 demux->sinkpad = gst_pad_new_from_template (
202 gst_element_class_get_pad_template (klass, "sink"), "sink");
203 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
204 GST_EBML_READ (demux)->sinkpad = demux->sinkpad;
206 gst_element_set_loop_function (GST_ELEMENT (demux),
207 gst_matroska_demux_loop);
209 /* initial stream no. */
210 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
211 demux->src[i] = NULL;
213 demux->streaminfo = demux->metadata = NULL;
214 demux->writing_app = demux->muxing_app = NULL;
218 gst_matroska_demux_reset (GST_ELEMENT (demux));
222 gst_matroska_demux_reset (GstElement *element)
224 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
228 demux->state = GST_MATROSKA_DEMUX_STATE_START;
230 /* clean up existing streams */
231 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
232 if (demux->src[i] != NULL) {
233 if (demux->src[i]->pad != NULL) {
234 gst_element_remove_pad (GST_ELEMENT (demux), demux->src[i]->pad);
236 g_free (demux->src[i]->codec_id);
237 g_free (demux->src[i]->codec_name);
238 g_free (demux->src[i]->name);
239 g_free (demux->src[i]->language);
240 g_free (demux->src[i]->codec_priv);
241 g_free (demux->src[i]);
242 demux->src[i] = NULL;
245 demux->num_streams = 0;
246 demux->num_a_streams = 0;
247 demux->num_t_streams = 0;
248 demux->num_v_streams = 0;
250 /* reset media info */
252 gst_caps_replace (&demux->metadata, NULL);
253 gst_caps_replace (&demux->streaminfo, NULL);
255 g_free (demux->writing_app);
256 demux->writing_app = NULL;
257 g_free (demux->muxing_app);
258 demux->muxing_app = NULL;
261 demux->num_indexes = 0;
262 g_free (demux->index);
267 demux->time_scale = 1000000;
270 demux->created = G_MININT64;
271 demux->seek_pending = GST_CLOCK_TIME_NONE;
273 demux->metadata_parsed = FALSE;
274 demux->index_parsed = FALSE;
278 gst_matroska_demux_set_clock (GstElement *element,
281 GST_MATROSKA_DEMUX (element)->clock = clock;
285 gst_matroska_demux_stream_from_num (GstMatroskaDemux *demux,
290 for (n = 0; n < demux->num_streams; n++) {
291 if (demux->src[n] != NULL &&
292 demux->src[n]->num == track_num) {
297 if (n == demux->num_streams) {
298 GST_WARNING ("Failed to find corresponding pad for tracknum %d",
306 gst_matroska_demux_src_getcaps (GstPad *pad)
308 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
311 for (n = 0; n < demux->num_streams; n++) {
312 if (demux->src[n] != NULL && demux->src[n]->pad == pad) {
317 if (n == demux->num_streams)
318 return gst_caps_new_empty();
320 return gst_caps_copy (demux->src[n]->caps);
324 gst_matroska_demux_add_stream (GstMatroskaDemux *demux)
326 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
327 GstEbmlRead *ebml = GST_EBML_READ (demux);
328 GstMatroskaTrackContext *context;
329 GstPadTemplate *templ = NULL;
330 GstCaps *caps = NULL;
331 gchar *padname = NULL;
335 if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) {
336 GST_WARNING ("Maximum number of streams (%d) exceeded, skipping",
337 GST_MATROSKA_DEMUX_MAX_STREAMS);
338 return gst_ebml_read_skip (ebml); /* skip-and-continue */
341 /* allocate generic... if we know the type, we'll g_renew()
342 * with the precise type */
343 context = g_new0 (GstMatroskaTrackContext, 1);
344 demux->src[demux->num_streams] = context;
345 context->index = demux->num_streams;
346 context->type = 0; /* no type yet */
347 demux->num_streams++;
349 /* start with the master */
350 if (!gst_ebml_read_master (ebml, &id))
353 /* try reading the trackentry headers */
355 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
358 } else if (demux->level_up > 0) {
364 /* track number (unique stream ID) */
365 case GST_MATROSKA_ID_TRACKNUMBER: {
367 if (!gst_ebml_read_uint (ebml, &id, &num)) {
375 /* track UID (unique identifier) */
376 case GST_MATROSKA_ID_TRACKUID: {
378 if (!gst_ebml_read_uint (ebml, &id, &num)) {
386 /* track type (video, audio, combined, subtitle, etc.) */
387 case GST_MATROSKA_ID_TRACKTYPE: {
389 if (context->type != 0) {
390 GST_WARNING ("More than one tracktype defined in a trackentry - skipping");
393 if (!gst_ebml_read_uint (ebml, &id, &num)) {
399 /* ok, so we're actually going to reallocate this thing */
400 switch (context->type) {
401 case GST_MATROSKA_TRACK_TYPE_VIDEO:
402 context = (GstMatroskaTrackContext *)
403 g_renew (GstMatroskaTrackVideoContext, context, 1);
405 case GST_MATROSKA_TRACK_TYPE_AUDIO:
406 context = (GstMatroskaTrackContext *)
407 g_renew (GstMatroskaTrackAudioContext, context, 1);
409 ((GstMatroskaTrackAudioContext *) context)->channels = 1;
410 ((GstMatroskaTrackAudioContext *) context)->samplerate = 8000;
412 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
413 context = (GstMatroskaTrackContext *)
414 g_renew (GstMatroskaTrackComplexContext, context, 1);
416 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
417 context = (GstMatroskaTrackContext *)
418 g_renew (GstMatroskaTrackSubtitleContext, context, 1);
420 case GST_MATROSKA_TRACK_TYPE_LOGO:
421 case GST_MATROSKA_TRACK_TYPE_CONTROL:
423 GST_WARNING ("Unknown or unsupported track type 0x%x",
428 demux->src[demux->num_streams-1] = context;
432 /* tracktype specific stuff for video */
433 case GST_MATROSKA_ID_TRACKVIDEO: {
434 GstMatroskaTrackVideoContext *videocontext;
435 if (context->type != GST_MATROSKA_TRACK_TYPE_VIDEO) {
436 GST_WARNING ("trackvideo EBML entry in non-video track - ignoring track");
439 } else if (!gst_ebml_read_master (ebml, &id)) {
443 videocontext = (GstMatroskaTrackVideoContext *) context;
446 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
449 } else if (demux->level_up > 0) {
455 /* fixme, this should be one-up, but I get it here (?) */
456 case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
458 if (!gst_ebml_read_uint (ebml, &id, &num)) {
462 context->default_duration = num;
466 /* video framerate */
467 case GST_MATROSKA_ID_VIDEOFRAMERATE: {
469 if (!gst_ebml_read_float (ebml, &id, &num)) {
473 context->default_duration = GST_SECOND * (1. / num);
477 /* width of the size to display the video at */
478 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH: {
480 if (!gst_ebml_read_uint (ebml, &id, &num)) {
484 videocontext->display_width = num;
488 /* height of the size to display the video at */
489 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT: {
491 if (!gst_ebml_read_uint (ebml, &id, &num)) {
495 videocontext->display_height = num;
499 /* width of the video in the file */
500 case GST_MATROSKA_ID_VIDEOPIXELWIDTH: {
502 if (!gst_ebml_read_uint (ebml, &id, &num)) {
506 videocontext->pixel_width = num;
510 /* height of the video in the file */
511 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT: {
513 if (!gst_ebml_read_uint (ebml, &id, &num)) {
517 videocontext->pixel_height = num;
521 /* whether the video is interlaced */
522 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED: {
524 if (!gst_ebml_read_uint (ebml, &id, &num)) {
529 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
531 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
535 /* stereo mode (whether the video has two streams, where
536 * one is for the left eye and the other for the right eye,
537 * which creates a 3D-like effect) */
538 case GST_MATROSKA_ID_VIDEOSTEREOMODE: {
540 if (!gst_ebml_read_uint (ebml, &id, &num)) {
544 if (num != GST_MATROSKA_EYE_MODE_MONO &&
545 num != GST_MATROSKA_EYE_MODE_LEFT &&
546 num != GST_MATROSKA_EYE_MODE_RIGHT &&
547 num != GST_MATROSKA_EYE_MODE_BOTH) {
548 GST_WARNING ("Unknown eye mode 0x%x - ignoring",
552 videocontext->eye_mode = num;
556 /* aspect ratio behaviour */
557 case GST_MATROSKA_ID_VIDEOASPECTRATIO: {
559 if (!gst_ebml_read_uint (ebml, &id, &num)) {
563 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
564 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
565 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
566 GST_WARNING ("Unknown aspect ratio mode 0x%x - ignoring",
570 videocontext->asr_mode = num;
574 /* colourspace (only matters for raw video) fourcc */
575 case GST_MATROSKA_ID_VIDEOCOLOURSPACE: {
577 if (!gst_ebml_read_uint (ebml, &id, &num)) {
581 videocontext->fourcc = num;
586 GST_WARNING ("Unknown video track header entry 0x%x - ignoring",
590 case GST_EBML_ID_VOID:
591 if (!gst_ebml_read_skip (ebml))
596 if (demux->level_up) {
604 /* tracktype specific stuff for audio */
605 case GST_MATROSKA_ID_TRACKAUDIO: {
606 GstMatroskaTrackAudioContext *audiocontext;
607 if (context->type != GST_MATROSKA_TRACK_TYPE_AUDIO) {
608 GST_WARNING ("trackaudio EBML entry in non-audio track - ignoring track");
611 } else if (!gst_ebml_read_master (ebml, &id)) {
615 audiocontext = (GstMatroskaTrackAudioContext *) context;
618 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
621 } else if (demux->level_up > 0) {
628 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ: {
630 if (!gst_ebml_read_float (ebml, &id, &num)) {
634 audiocontext->samplerate = num;
639 case GST_MATROSKA_ID_AUDIOBITDEPTH: {
641 if (!gst_ebml_read_uint (ebml, &id, &num)) {
645 audiocontext->bitdepth = num;
650 case GST_MATROSKA_ID_AUDIOCHANNELS: {
652 if (!gst_ebml_read_uint (ebml, &id, &num)) {
656 audiocontext->channels = num;
661 GST_WARNING ("Unknown audio track header entry 0x%x - ignoring",
665 case GST_EBML_ID_VOID:
666 if (!gst_ebml_read_skip (ebml))
671 if (demux->level_up) {
679 /* codec identifier */
680 case GST_MATROSKA_ID_CODECID: {
682 if (!gst_ebml_read_ascii (ebml, &id, &text)) {
686 context->codec_id = text;
690 /* codec private data */
691 case GST_MATROSKA_ID_CODECPRIVATE: {
694 if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
698 context->codec_priv = data;
699 context->codec_priv_size = size;
703 /* name of the codec */
704 case GST_MATROSKA_ID_CODECNAME: {
706 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
710 context->codec_name = text;
714 /* name of this track */
715 case GST_MATROSKA_ID_TRACKNAME: {
717 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
721 context->name = text;
725 /* language (matters for audio/subtitles, mostly) */
726 case GST_MATROSKA_ID_TRACKLANGUAGE: {
728 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
732 context->language = text;
736 /* whether this is actually used */
737 case GST_MATROSKA_ID_TRACKFLAGENABLED: {
739 if (!gst_ebml_read_uint (ebml, &id, &num)) {
744 context->flags |= GST_MATROSKA_TRACK_ENABLED;
746 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
750 /* whether it's the default for this track type */
751 case GST_MATROSKA_ID_TRACKFLAGDEFAULT: {
753 if (!gst_ebml_read_uint (ebml, &id, &num)) {
758 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
760 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
764 /* lacing (like MPEG, where blocks don't end/start on frame
766 case GST_MATROSKA_ID_TRACKFLAGLACING: {
768 if (!gst_ebml_read_uint (ebml, &id, &num)) {
773 context->flags |= GST_MATROSKA_TRACK_LACING;
775 context->flags &= ~GST_MATROSKA_TRACK_LACING;
779 /* default length (in time) of one data block in this track */
780 case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
782 if (!gst_ebml_read_uint (ebml, &id, &num)) {
786 context->default_duration = num;
791 GST_WARNING ("Unknown track header entry 0x%x - ignoring", id);
794 /* we ignore these because they're nothing useful (i.e. crap). */
795 case GST_MATROSKA_ID_CODECINFOURL:
796 case GST_MATROSKA_ID_CODECDOWNLOADURL:
797 case GST_MATROSKA_ID_TRACKMINCACHE:
798 case GST_MATROSKA_ID_TRACKMAXCACHE:
799 case GST_EBML_ID_VOID:
800 if (!gst_ebml_read_skip (ebml))
805 if (demux->level_up) {
811 if (context->type == 0 || context->codec_id == NULL || !res) {
813 GST_WARNING ("Unknown stream/codec in track entry header");
815 demux->num_streams--;
816 demux->src[demux->num_streams] = NULL;
818 g_free (context->codec_id);
819 g_free (context->codec_name);
820 g_free (context->name);
821 g_free (context->language);
822 g_free (context->codec_priv);
829 /* now create the GStreamer connectivity */
830 switch (context->type) {
831 case GST_MATROSKA_TRACK_TYPE_VIDEO: {
832 GstMatroskaTrackVideoContext *videocontext =
833 (GstMatroskaTrackVideoContext *) context;
834 padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
835 templ = gst_element_class_get_pad_template (klass, "video_%02d");
836 caps = gst_matroska_demux_video_caps (videocontext,
839 context->codec_priv_size);
843 case GST_MATROSKA_TRACK_TYPE_AUDIO: {
844 GstMatroskaTrackAudioContext *audiocontext =
845 (GstMatroskaTrackAudioContext *) context;
846 padname = g_strdup_printf ("audio_%02d", demux->num_a_streams++);
847 templ = gst_element_class_get_pad_template (klass, "audio_%02d");
848 caps = gst_matroska_demux_audio_caps (audiocontext,
851 context->codec_priv_size);
855 case GST_MATROSKA_TRACK_TYPE_COMPLEX: {
856 GstMatroskaTrackComplexContext *complexcontext =
857 (GstMatroskaTrackComplexContext *) context;
858 padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
859 templ = gst_element_class_get_pad_template (klass, "video_%02d");
860 caps = gst_matroska_demux_complex_caps (complexcontext,
863 context->codec_priv_size);
867 case GST_MATROSKA_TRACK_TYPE_SUBTITLE: {
868 GstMatroskaTrackSubtitleContext *subtitlecontext =
869 (GstMatroskaTrackSubtitleContext *) context;
870 padname = g_strdup_printf ("subtitle_%02d", demux->num_t_streams++);
871 templ = gst_element_class_get_pad_template (klass, "subtitle_%02d");
872 caps = gst_matroska_demux_subtitle_caps (subtitlecontext,
875 context->codec_priv_size);
879 case GST_MATROSKA_TRACK_TYPE_LOGO:
880 case GST_MATROSKA_TRACK_TYPE_CONTROL:
882 /* we should already have quit by now */
886 /* the pad in here */
887 context->pad = gst_pad_new_from_template (templ, padname);
888 context->caps = caps ? caps : gst_caps_new_empty ();
892 /* set some functions */
893 gst_pad_set_formats_function (context->pad,
894 gst_matroska_demux_get_src_formats);
895 gst_pad_set_event_mask_function (context->pad,
896 gst_matroska_demux_get_event_mask);
897 gst_pad_set_event_function (context->pad,
898 gst_matroska_demux_handle_src_event);
899 gst_pad_set_query_type_function (context->pad,
900 gst_matroska_demux_get_src_query_types);
901 gst_pad_set_query_function (context->pad,
902 gst_matroska_demux_handle_src_query);
903 gst_pad_set_getcaps_function (context->pad,
904 gst_matroska_demux_src_getcaps);
906 gst_element_add_pad (GST_ELEMENT (demux), context->pad);
912 static const GstFormat *
913 gst_matroska_demux_get_src_formats (GstPad *pad)
915 /*GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));*/
917 /* we could try to look for units (i.e. samples) in audio streams
918 * or video streams, but both samplerate and framerate are not
919 * always constant, and since we only have a time indication, we
920 * cannot guarantee anything here based purely on index. So, we
921 * only support time for now. */
922 static const GstFormat src_formats[] = {
930 static const GstQueryType *
931 gst_matroska_demux_get_src_query_types (GstPad *pad)
933 static const GstQueryType src_types[] = {
943 gst_matroska_demux_handle_src_query (GstPad *pad,
949 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
952 case GST_QUERY_TOTAL:
954 case GST_FORMAT_DEFAULT:
955 *format = GST_FORMAT_TIME;
957 case GST_FORMAT_TIME:
958 *value = demux->duration;
966 case GST_QUERY_POSITION:
968 case GST_FORMAT_DEFAULT:
969 *format = GST_FORMAT_TIME;
971 case GST_FORMAT_TIME:
988 static GstMatroskaIndex *
989 gst_matroskademux_seek (GstMatroskaDemux *demux)
991 guint entry = (guint) -1;
992 guint64 offset = demux->seek_pending;
995 /* make sure we don't seek twice */
996 demux->seek_pending = GST_CLOCK_TIME_NONE;
998 for (n = 0; n < demux->num_indexes; n++) {
999 if (entry == (guint) -1) {
1002 gfloat diff_old = fabs (1. * (demux->index[entry].time - offset)),
1003 diff_new = fabs (1. * (demux->index[n].time - offset));
1005 if (diff_new < diff_old) {
1011 if (entry != (guint) -1) {
1012 return &demux->index[entry];
1019 gst_matroska_demux_send_event (GstElement *element,
1022 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
1023 gboolean res = TRUE;
1025 switch (GST_EVENT_TYPE (event)) {
1026 case GST_EVENT_SEEK:
1027 switch (GST_EVENT_SEEK_FORMAT (event)) {
1028 case GST_FORMAT_TIME:
1029 demux->seek_pending = GST_EVENT_SEEK_OFFSET (event);
1033 GST_WARNING ("Only time seek is supported");
1040 GST_WARNING ("Unhandled event of type %d",
1041 GST_EVENT_TYPE (event));
1046 gst_event_unref (event);
1051 static const GstEventMask *
1052 gst_matroska_demux_get_event_mask (GstPad *pad)
1054 static const GstEventMask masks[] = {
1055 { GST_EVENT_SEEK, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1056 (gint) GST_SEEK_FLAG_KEY_UNIT) },
1057 { GST_EVENT_SEEK_SEGMENT, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1058 (gint) GST_SEEK_FLAG_KEY_UNIT) },
1059 { (GstEventType) 0, (GstEventFlag) 0 }
1066 gst_matroska_demux_handle_src_event (GstPad *pad,
1069 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
1070 gboolean res = TRUE;
1072 switch (GST_EVENT_TYPE (event)) {
1073 case GST_EVENT_SEEK_SEGMENT:
1074 case GST_EVENT_SEEK:
1075 return gst_matroska_demux_send_event (GST_ELEMENT (demux), event);
1078 GST_WARNING ("Unhandled event of type %d",
1079 GST_EVENT_TYPE (event));
1084 gst_event_unref (event);
1090 gst_matroska_demux_handle_seek_event (GstMatroskaDemux *demux)
1092 GstEbmlRead *ebml = GST_EBML_READ (demux);
1093 GstMatroskaIndex *entry = gst_matroskademux_seek (demux);
1100 /* seek (relative to segment) */
1101 if (!(event = gst_ebml_read_seek (ebml,
1102 entry->pos + demux->segment_start)))
1104 gst_event_unref (event); /* byte - we want time */
1105 event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
1108 /* forward to all src pads */
1109 for (i = 0; i < demux->num_streams; i++) {
1110 if (GST_PAD_IS_USABLE (demux->src[i]->pad)) {
1111 gst_event_ref (event);
1112 gst_pad_push (demux->src[i]->pad, GST_DATA (event));
1116 gst_event_unref (event);
1122 gst_matroska_demux_init_stream (GstMatroskaDemux *demux)
1124 GstEbmlRead *ebml = GST_EBML_READ (demux);
1129 if (!gst_ebml_read_header (ebml, &doctype, &version))
1132 if (!doctype || strcmp (doctype, "matroska") != 0) {
1133 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1134 ("Input is not a matroska stream (doctype=%s)",
1135 doctype ? doctype : "none"));
1141 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1142 ("Demuxer version (1) is too old to read stream version %d",
1147 /* find segment, must be the next element */
1151 if (!(id = gst_ebml_peek_id (ebml, &last_level)))
1154 if (id == GST_MATROSKA_ID_SEGMENT)
1158 GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
1159 GST_MATROSKA_ID_SEGMENT, id);
1160 if (!gst_ebml_read_skip (ebml))
1164 /* we now have a EBML segment */
1165 if (!gst_ebml_read_master (ebml, &id))
1167 /* seeks are from the beginning of the segment,
1168 * after the segment ID/length */
1169 demux->segment_start = gst_bytestream_tell (ebml->bs);
1175 gst_matroska_demux_parse_tracks (GstMatroskaDemux *demux)
1177 GstEbmlRead *ebml = GST_EBML_READ (demux);
1178 gboolean res = TRUE;
1182 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1185 } else if (demux->level_up) {
1191 /* one track within the "all-tracks" header */
1192 case GST_MATROSKA_ID_TRACKENTRY:
1193 if (!gst_matroska_demux_add_stream (demux))
1198 GST_WARNING ("Unknown entry 0x%x in track header", id);
1201 case GST_EBML_ID_VOID:
1202 if (!gst_ebml_read_skip (ebml))
1207 if (demux->level_up) {
1217 gst_matroska_demux_parse_index (GstMatroskaDemux *demux,
1218 gboolean prevent_eos)
1220 GstEbmlRead *ebml = GST_EBML_READ (demux);
1221 gboolean res = TRUE;
1223 GstMatroskaIndex idx;
1227 length = gst_bytestream_length (ebml->bs);
1231 /* We're an element that can be seeked to. If we are, then
1232 * we want to prevent EOS, since that'll kill us. So we cache
1233 * file size and seek until there, and don't call EOS upon os. */
1234 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1237 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1240 } else if (demux->level_up) {
1246 /* one single index entry ('point') */
1247 case GST_MATROSKA_ID_POINTENTRY:
1248 if (!gst_ebml_read_master (ebml, &id)) {
1253 /* in the end, we hope to fill one entry with a
1254 * timestamp, a file position and a tracknum */
1255 idx.pos = (guint64) -1;
1256 idx.time = (guint64) -1;
1257 idx.track = (guint16) -1;
1260 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1263 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1266 } else if (demux->level_up) {
1272 /* one single index entry ('point') */
1273 case GST_MATROSKA_ID_CUETIME: {
1275 if (!gst_ebml_read_uint (ebml, &id, &time)) {
1279 idx.time = time * demux->time_scale;
1283 /* position in the file + track to which it belongs */
1284 case GST_MATROSKA_ID_CUETRACKPOSITION:
1285 if (!gst_ebml_read_master (ebml, &id)) {
1291 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1294 } else if (!(id = gst_ebml_peek_id (ebml,
1295 &demux->level_up))) {
1298 } else if (demux->level_up) {
1305 case GST_MATROSKA_ID_CUETRACK: {
1307 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1315 /* position in file */
1316 case GST_MATROSKA_ID_CUECLUSTERPOSITION: {
1318 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1327 GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions", id);
1330 case GST_EBML_ID_VOID:
1331 if (!gst_ebml_read_skip (ebml))
1336 if (demux->level_up) {
1345 GST_WARNING ("Unknown entry 0x%x in cuespoint index", id);
1348 case GST_EBML_ID_VOID:
1349 if (!gst_ebml_read_skip (ebml))
1354 if (demux->level_up) {
1360 /* so let's see if we got what we wanted */
1361 if (idx.pos != (guint64) -1 &&
1362 idx.time != (guint64) -1 &&
1363 idx.track != (guint16) -1) {
1364 if (demux->num_indexes % 32 == 0) {
1365 /* re-allocate bigger index */
1366 demux->index = g_renew (GstMatroskaIndex, demux->index,
1367 demux->num_indexes + 32);
1369 demux->index[demux->num_indexes].pos = idx.pos;
1370 demux->index[demux->num_indexes].time = idx.time;
1371 demux->index[demux->num_indexes].track = idx.track;
1372 demux->num_indexes++;
1378 GST_WARNING ("Unknown entry 0x%x in cues header", id);
1381 case GST_EBML_ID_VOID:
1382 if (!gst_ebml_read_skip (ebml))
1387 if (demux->level_up) {
1397 gst_matroska_demux_parse_info (GstMatroskaDemux *demux)
1399 GstEbmlRead *ebml = GST_EBML_READ (demux);
1400 gboolean res = TRUE;
1404 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1407 } else if (demux->level_up) {
1413 /* cluster timecode */
1414 case GST_MATROSKA_ID_TIMECODESCALE: {
1416 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1420 demux->time_scale = num;
1424 case GST_MATROSKA_ID_DURATION: {
1426 if (!gst_ebml_read_float (ebml, &id, &num)) {
1430 demux->duration = num * demux->time_scale;
1434 case GST_MATROSKA_ID_WRITINGAPP: {
1436 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1440 demux->writing_app = text;
1444 case GST_MATROSKA_ID_MUXINGAPP: {
1446 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1450 demux->muxing_app = text;
1454 case GST_MATROSKA_ID_DATEUTC: {
1456 if (!gst_ebml_read_date (ebml, &id, &time)) {
1460 demux->created = time;
1465 GST_WARNING ("Unknown entry 0x%x in info header", id);
1468 case GST_EBML_ID_VOID:
1469 if (!gst_ebml_read_skip (ebml))
1474 if (demux->level_up) {
1484 gst_matroska_demux_parse_metadata (GstMatroskaDemux *demux,
1485 gboolean prevent_eos)
1487 GstEbmlRead *ebml = GST_EBML_READ (demux);
1488 gboolean res = TRUE;
1493 length = gst_bytestream_length (ebml->bs);
1497 /* We're an element that can be seeked to. If we are, then
1498 * we want to prevent EOS, since that'll kill us. So we cache
1499 * file size and seek until there, and don't call EOS upon os. */
1500 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1503 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1506 } else if (demux->level_up) {
1513 GST_WARNING ("metadata unimplemented");
1516 case GST_EBML_ID_VOID:
1517 if (!gst_ebml_read_skip (ebml))
1522 if (demux->level_up) {
1532 * Read signed/unsigned "EBML" numbers.
1533 * Return: number of bytes processed.
1537 gst_matroska_ebmlnum_uint (guint8 *data,
1541 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1549 while (read <= 8 && !(total & len_mask)) {
1556 if ((total &= (len_mask - 1)) == len_mask - 1)
1561 if (data[n] == 0xff)
1563 total = (total << 8) | data[n];
1570 if (read == num_ffs)
1579 gst_matroska_ebmlnum_sint (guint8 *data,
1586 /* read as unsigned number first */
1587 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1591 if (unum == G_MAXUINT64)
1594 *num = unum - ((1 << ((7 * res) - 1)) - 1);
1600 gst_matroska_demux_parse_blockgroup (GstMatroskaDemux *demux,
1601 guint64 cluster_time)
1603 GstEbmlRead *ebml = GST_EBML_READ (demux);
1604 gboolean res = TRUE;
1608 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1611 } else if (demux->level_up) {
1617 /* one block inside the group. Note, block parsing is one
1618 * of the harder things, so this code is a bit complicated.
1619 * See http://www.matroska.org/ for documentation. */
1620 case GST_MATROSKA_ID_BLOCK: {
1624 guint size, *lace_size = NULL;
1625 gint n, stream, flags, laces = 0;
1628 if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
1632 data = GST_BUFFER_DATA (buf);
1633 size = GST_BUFFER_SIZE (buf);
1635 /* first byte(s): blocknum */
1636 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1637 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1638 gst_buffer_unref (buf);
1642 data += n; size -= n;
1644 /* fetch stream from num */
1645 stream = gst_matroska_demux_stream_from_num (demux, num);
1646 if (size <= 3 || stream < 0 || stream >= demux->num_streams) {
1647 gst_buffer_unref (buf);
1648 GST_WARNING ("Invalid stream %d or size %u", stream, size);
1651 if (!GST_PAD_IS_USABLE (demux->src[stream]->pad)) {
1652 gst_buffer_unref (buf);
1656 /* time (relative to cluster time) */
1657 time = (GINT16_FROM_BE (* (gint16 *) data)) * demux->time_scale;
1658 data += 2; size -= 2;
1659 flags = * (guint8 *) data;
1660 data += 1; size -= 1;
1661 switch ((flags & 0x06) >> 1) {
1662 case 0x0: /* no lacing */
1664 lace_size = g_new (gint, 1);
1665 lace_size[0] = size;
1668 case 0x1: /* xiph lacing */
1669 case 0x2: /* fixed-size lacing */
1670 case 0x3: /* EBML lacing */
1675 laces = (* (guint8 *) data) + 1;
1676 data += 1; size -= 1;
1677 lace_size = g_new0 (gint, laces);
1679 switch ((flags & 0x06) >> 1) {
1680 case 0x1: /* xiph lacing */ {
1681 guint temp, total = 0;
1682 for (n = 0; res && n < laces - 1; n++) {
1688 temp = * (guint8 *) data;
1689 lace_size[n] += temp;
1690 data += 1; size -= 1;
1694 total += lace_size[n];
1696 lace_size[n] = size - total;
1700 case 0x2: /* fixed-size lacing */
1701 for (n = 0; n < laces; n++)
1702 lace_size[n] = size / laces;
1705 case 0x3: /* EBML lacing */ {
1707 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1708 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1712 data += n; size -= n;
1713 total = lace_size[0] = num;
1714 for (n = 1; res && n < laces - 1; n++) {
1717 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
1718 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1722 data += r; size -= r;
1723 lace_size[n] = lace_size[n - 1] + snum;
1724 total += lace_size[n];
1726 lace_size[n] = size - total;
1734 for (n = 0; n < laces; n++) {
1735 GstBuffer *sub = gst_buffer_create_sub (buf,
1736 GST_BUFFER_SIZE (buf) - size,
1739 if (cluster_time != GST_CLOCK_TIME_NONE) {
1740 if (time < 0 && (-time) > cluster_time)
1741 GST_BUFFER_TIMESTAMP (sub) = cluster_time;
1743 GST_BUFFER_TIMESTAMP (sub) = cluster_time + time;
1745 /* FIXME: duration */
1747 gst_pad_push (demux->src[stream]->pad, GST_DATA (sub));
1749 size -= lace_size[n];
1754 gst_buffer_unref (buf);
1758 case GST_MATROSKA_ID_BLOCKDURATION: {
1760 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1764 GST_WARNING ("FIXME: implement support for BlockDuration");
1769 GST_WARNING ("Unknown entry 0x%x in blockgroup data", id);
1772 case GST_EBML_ID_VOID:
1773 if (!gst_ebml_read_skip (ebml))
1778 if (demux->level_up) {
1788 gst_matroska_demux_parse_cluster (GstMatroskaDemux *demux)
1790 GstEbmlRead *ebml = GST_EBML_READ (demux);
1791 gboolean res = TRUE;
1793 guint64 cluster_time = GST_CLOCK_TIME_NONE;
1795 /* We seek after index/header parsing before doing a new
1796 * buffer. So here. */
1797 if (demux->seek_pending != GST_CLOCK_TIME_NONE) {
1798 if (!gst_matroska_demux_handle_seek_event (demux))
1800 demux->seek_pending = GST_CLOCK_TIME_NONE;
1804 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1807 } else if (demux->level_up) {
1813 /* cluster timecode */
1814 case GST_MATROSKA_ID_CLUSTERTIMECODE: {
1816 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1820 cluster_time = num * demux->time_scale;
1824 /* a group of blocks inside a cluster */
1825 case GST_MATROSKA_ID_BLOCKGROUP:
1826 if (!gst_ebml_read_master (ebml, &id)) {
1830 res = gst_matroska_demux_parse_blockgroup (demux, cluster_time);
1834 GST_WARNING ("Unknown entry 0x%x in cluster data", id);
1837 case GST_EBML_ID_VOID:
1838 if (!gst_ebml_read_skip (ebml))
1843 if (demux->level_up) {
1853 gst_matroska_demux_parse_contents (GstMatroskaDemux *demux)
1855 GstEbmlRead *ebml = GST_EBML_READ (demux);
1856 gboolean res = TRUE;
1860 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1863 } else if (demux->level_up) {
1869 case GST_MATROSKA_ID_SEEKENTRY: {
1870 guint32 seek_id = 0;
1871 guint64 seek_pos = (guint64) -1, t;
1873 if (!gst_ebml_read_master (ebml, &id)) {
1879 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1882 } else if (demux->level_up) {
1888 case GST_MATROSKA_ID_SEEKID:
1889 if (!gst_ebml_read_uint (ebml, &id, &t))
1894 case GST_MATROSKA_ID_SEEKPOSITION:
1895 if (!gst_ebml_read_uint (ebml, &id, &seek_pos))
1900 GST_WARNING ("Unknown seekhead ID 0x%x", id);
1903 case GST_EBML_ID_VOID:
1904 if (!gst_ebml_read_skip (ebml))
1909 if (demux->level_up) {
1915 if (!seek_id || seek_pos == (guint64) -1) {
1916 GST_WARNING ("Incomplete seekhead entry (0x%x/%"
1917 G_GUINT64_FORMAT ")", seek_id, seek_pos);
1922 case GST_MATROSKA_ID_CUES:
1923 case GST_MATROSKA_ID_TAGS: {
1924 guint level_up = demux->level_up;
1925 guint64 before_pos, length;
1926 GstEbmlLevel *level;
1930 length = gst_bytestream_length (ebml->bs);
1931 before_pos = gst_bytestream_tell (ebml->bs);
1933 /* check for validity */
1934 if (seek_pos + demux->segment_start + 12 >= length) {
1935 g_warning ("Seekhead reference lies outside file!");
1940 if (!(event = gst_ebml_read_seek (ebml,
1941 seek_pos + demux->segment_start)))
1943 gst_event_unref (event);
1945 /* we don't want to lose our seekhead level, so we add
1946 * a dummy. This is a crude hack. */
1947 level = g_new (GstEbmlLevel, 1);
1949 level->length = G_MAXUINT64;
1950 ebml->level = g_list_append (ebml->level, level);
1953 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1957 if (id != seek_id) {
1958 g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%llu)",
1959 seek_id, id, seek_pos + demux->segment_start);
1963 /* read master + parse */
1965 case GST_MATROSKA_ID_CUES:
1966 if (!gst_ebml_read_master (ebml, &id))
1968 else if (!gst_matroska_demux_parse_index (demux, TRUE) &&
1969 gst_bytestream_length (ebml->bs) !=
1970 gst_bytestream_tell (ebml->bs))
1973 demux->index_parsed = TRUE;
1975 case GST_MATROSKA_ID_TAGS:
1976 if (!gst_ebml_read_master (ebml, &id))
1978 else if (!gst_matroska_demux_parse_metadata (demux, TRUE) &&
1979 gst_bytestream_length (ebml->bs) !=
1980 gst_bytestream_tell (ebml->bs))
1983 demux->metadata_parsed = TRUE;
1990 /* remove dummy level */
1991 while (ebml->level) {
1993 level = g_list_last (ebml->level)->data;
1994 ebml->level = g_list_remove (ebml->level, level);
1995 length = level->length;
1997 if (length == G_MAXUINT64)
2002 if (!(event = gst_ebml_read_seek (ebml, before_pos)))
2004 gst_event_unref (event);
2005 demux->level_up = level_up;
2010 GST_INFO ("Ignoring seekhead entry for ID=0x%x", seek_id);
2018 GST_WARNING ("Unknown seekhead ID 0x%x", id);
2021 case GST_EBML_ID_VOID:
2022 if (!gst_ebml_read_skip (ebml))
2027 if (demux->level_up) {
2037 gst_matroska_demux_loop_stream (GstMatroskaDemux *demux)
2039 GstEbmlRead *ebml = GST_EBML_READ (demux);
2040 gboolean res = TRUE;
2043 /* we've found our segment, start reading the different contents in here */
2045 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2048 } else if (demux->level_up) {
2055 case GST_MATROSKA_ID_INFO: {
2056 if (!gst_ebml_read_master (ebml, &id)) {
2060 res = gst_matroska_demux_parse_info (demux);
2064 /* track info headers */
2065 case GST_MATROSKA_ID_TRACKS: {
2066 if (!gst_ebml_read_master (ebml, &id)) {
2070 res = gst_matroska_demux_parse_tracks (demux);
2075 case GST_MATROSKA_ID_CUES: {
2076 if (!demux->index_parsed) {
2077 if (!gst_ebml_read_master (ebml, &id)) {
2081 res = gst_matroska_demux_parse_index (demux, FALSE);
2083 res = gst_ebml_read_skip (ebml);
2088 case GST_MATROSKA_ID_TAGS: {
2089 if (!demux->index_parsed) {
2090 if (!gst_ebml_read_master (ebml, &id)) {
2094 res = gst_matroska_demux_parse_metadata (demux, FALSE);
2096 res = gst_ebml_read_skip (ebml);
2100 /* file index (if seekable, seek to Cues/Tags to parse it) */
2101 case GST_MATROSKA_ID_SEEKHEAD: {
2102 if (!gst_ebml_read_master (ebml, &id)) {
2106 res = gst_matroska_demux_parse_contents (demux);
2110 case GST_MATROSKA_ID_CLUSTER: {
2111 if (!gst_ebml_read_master (ebml, &id)) {
2115 /* The idea is that we parse one cluster per loop and
2116 * then break out of the loop here. In the next call
2117 * of the loopfunc, we will get back here with the
2118 * next cluster. If an error occurs, we didn't
2119 * actually push a buffer, but we still want to break
2120 * out of the loop to handle a possible error. We'll
2121 * get back here if it's recoverable. */
2122 gst_matroska_demux_parse_cluster (demux);
2123 demux->state = GST_MATROSKA_DEMUX_STATE_DATA;
2129 GST_WARNING ("Unknown matroska file header ID 0x%x", id);
2132 case GST_EBML_ID_VOID:
2133 if (!gst_ebml_read_skip (ebml))
2138 if (demux->level_up) {
2148 gst_matroska_demux_loop (GstElement *element)
2150 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2152 /* first, if we're to start, let's actually get starting */
2153 if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
2154 if (!gst_matroska_demux_init_stream (demux)) {
2157 demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
2160 gst_matroska_demux_loop_stream (demux);
2164 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *videocontext,
2165 const gchar *codec_id,
2169 GstMatroskaTrackContext *context =
2170 (GstMatroskaTrackContext *) videocontext;
2171 GstCaps *caps = NULL;
2173 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
2174 gst_riff_strf_vids *vids = NULL;
2177 vids = (gst_riff_strf_vids *) data;
2179 /* assure size is big enough */
2181 GST_WARNING ("Too small BITMAPINFOHEADER (%d bytes)", size);
2184 if (size < sizeof (gst_riff_strf_vids)) {
2185 vids = (gst_riff_strf_vids *) g_realloc (vids, sizeof (gst_riff_strf_vids));
2188 /* little-endian -> byte-order */
2189 vids->size = GUINT32_FROM_LE (vids->size);
2190 vids->width = GUINT32_FROM_LE (vids->width);
2191 vids->height = GUINT32_FROM_LE (vids->height);
2192 vids->planes = GUINT16_FROM_LE (vids->planes);
2193 vids->bit_cnt = GUINT16_FROM_LE (vids->bit_cnt);
2194 vids->compression = GUINT32_FROM_LE (vids->compression);
2195 vids->image_size = GUINT32_FROM_LE (vids->image_size);
2196 vids->xpels_meter = GUINT32_FROM_LE (vids->xpels_meter);
2197 vids->ypels_meter = GUINT32_FROM_LE (vids->ypels_meter);
2198 vids->num_colors = GUINT32_FROM_LE (vids->num_colors);
2199 vids->imp_colors = GUINT32_FROM_LE (vids->imp_colors);
2201 caps = gst_riff_create_video_caps (vids->compression, NULL, vids);
2203 caps = gst_riff_create_video_template_caps ();
2205 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
2206 /* how nice, this is undocumented... */
2207 if (videocontext != NULL) {
2210 switch (videocontext->fourcc) {
2211 case GST_MAKE_FOURCC ('I','4','2','0'):
2212 case GST_MAKE_FOURCC ('Y','U','Y','2'):
2213 fourcc = videocontext->fourcc;
2217 GST_DEBUG ("Unknown fourcc " GST_FOURCC_FORMAT,
2218 GST_FOURCC_ARGS (videocontext->fourcc));
2222 caps = gst_caps_new_simple ("video/x-raw-yuv",
2223 "format", GST_TYPE_FOURCC, fourcc, NULL);
2225 caps = gst_caps_from_string ("video/x-raw-yuv, "
2226 "format = (fourcc) { I420, YUY2, YV12 }");
2228 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) {
2229 caps = gst_caps_new_simple ("video/x-divx",
2230 "divxversion", G_TYPE_INT, 4, NULL);
2231 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) ||
2232 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) {
2233 caps = gst_caps_new_full (
2234 gst_structure_new ("video/x-divx",
2235 "divxversion", G_TYPE_INT, 5, NULL),
2236 gst_structure_new ("video/x-xvid", NULL),
2237 gst_structure_new ("video/mpeg",
2238 "mpegversion", G_TYPE_INT, 4,
2239 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL),
2241 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) {
2242 caps = gst_caps_new_full (
2243 gst_structure_new ("video/x-divx",
2244 "divxversion", G_TYPE_INT, 3, NULL),
2245 gst_structure_new ("video/x-msmpeg",
2246 "msmpegversion", G_TYPE_INT, 43, NULL),
2248 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1) ||
2249 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2)) {
2250 gint mpegversion = -1;
2252 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1))
2254 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2))
2259 caps = gst_caps_new_simple ("video/mpeg",
2260 "systemstream", G_TYPE_BOOLEAN, FALSE,
2261 "mpegversion", G_TYPE_INT, mpegversion, NULL);
2262 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) {
2263 caps = gst_caps_new_simple ("video/x-jpeg", NULL);
2265 GST_WARNING ("Unknown codec '%s', cannot build Caps",
2272 GstStructure *structure;
2274 for (i=0;i<gst_caps_get_size(caps);i++){
2275 structure = gst_caps_get_structure (caps, i);
2276 if (videocontext != NULL) {
2277 if (videocontext->pixel_width > 0 &&
2278 videocontext->pixel_height > 0) {
2279 gint w = videocontext->pixel_width;
2280 gint h = videocontext->pixel_height;
2282 gst_structure_set (structure,
2283 "width", G_TYPE_INT, w,
2284 "height", G_TYPE_INT, h, NULL);
2286 gst_structure_set (structure,
2287 "width", GST_TYPE_INT_RANGE, 16, 4096,
2288 "height", GST_TYPE_INT_RANGE, 16, 4096,
2292 if (videocontext->display_width > 0 &&
2293 videocontext->display_height > 0) {
2294 gint w = 100 * videocontext->display_width / videocontext->pixel_width;
2295 gint h = 100 * videocontext->display_height / videocontext->pixel_height;
2297 gst_structure_set (structure,
2298 "pixel_width", G_TYPE_INT, w,
2299 "pixel_height", G_TYPE_INT, h,
2303 if (context->default_duration > 0) {
2304 gfloat framerate = 1. * GST_SECOND / context->default_duration;
2306 gst_structure_set (structure,
2307 "framerate", G_TYPE_DOUBLE, framerate, NULL);
2309 /* sort of a hack to get most codecs to support,
2310 * even if the default_duration is missing */
2311 gst_structure_set (structure,
2312 "framerate", G_TYPE_DOUBLE, 25.0, NULL);
2315 gst_structure_set (structure,
2316 "width", GST_TYPE_INT_RANGE, 16, 4096,
2317 "height", GST_TYPE_INT_RANGE, 16, 4096,
2318 "pixel_width", GST_TYPE_INT_RANGE, 0, 255,
2319 "pixel_height", GST_TYPE_INT_RANGE, 0, 255,
2320 "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE,
2330 gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *audiocontext,
2331 const gchar *codec_id,
2335 GstMatroskaTrackContext *context =
2336 (GstMatroskaTrackContext *) audiocontext;
2337 GstCaps *caps = NULL;
2339 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
2340 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
2341 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
2344 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1))
2346 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2))
2348 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3))
2353 caps = gst_caps_new_simple ("audio/mpeg",
2354 "mpegversion", G_TYPE_INT, 1,
2355 "layer", G_TYPE_INT, layer, NULL);
2356 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) ||
2357 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) {
2358 gint endianness = -1;
2360 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE))
2361 endianness = G_BIG_ENDIAN;
2362 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE))
2363 endianness = G_LITTLE_ENDIAN;
2367 if (context != NULL) {
2368 caps = gst_caps_new_simple ("audio/x-raw-int",
2369 "width", G_TYPE_INT, audiocontext->bitdepth,
2370 "depth", G_TYPE_INT, audiocontext->bitdepth,
2371 "signed", G_TYPE_BOOLEAN, audiocontext->bitdepth == 8, NULL);
2373 caps = gst_caps_from_string ("audio/x-raw-int, "
2374 "signed = (boolean) { TRUE, FALSE }, "
2375 "depth = (int) { 8, 16 }, "
2376 "width = (int) { 8, 16 }");
2378 gst_caps_set_simple (caps, "endianness", G_TYPE_INT, endianness, NULL);
2379 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
2380 caps = gst_caps_new_simple ("audio/x-raw-float",
2381 "endianness", G_TYPE_INT, G_BYTE_ORDER,
2382 "buffer-frames", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
2383 if (audiocontext != NULL) {
2384 gst_caps_set_simple (caps,
2385 "width", G_TYPE_INT, audiocontext->bitdepth, NULL);
2387 gst_caps_set_simple (caps,
2388 "width", GST_TYPE_INT_RANGE, 32, 64, NULL);
2390 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AC3) ||
2391 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) {
2392 caps = gst_caps_new_simple ("audio/x-ac3", NULL);
2393 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
2394 caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
2395 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
2396 gst_riff_strf_auds *auds = NULL;
2399 auds = (gst_riff_strf_auds *) data;
2401 /* little-endian -> byte-order */
2402 auds->format = GUINT16_FROM_LE (auds->format);
2403 auds->channels = GUINT16_FROM_LE (auds->channels);
2404 auds->rate = GUINT32_FROM_LE (auds->rate);
2405 auds->av_bps = GUINT32_FROM_LE (auds->av_bps);
2406 auds->blockalign = GUINT16_FROM_LE (auds->blockalign);
2407 auds->size = GUINT16_FROM_LE (auds->size);
2409 caps = gst_riff_create_audio_caps (auds->format, NULL, auds);
2411 caps = gst_riff_create_audio_template_caps ();
2413 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2414 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)) ||
2415 !strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2416 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4))) {
2417 gint mpegversion = -1;
2419 if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2420 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)))
2422 else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2423 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4)))
2428 caps = gst_caps_new_simple ("audio/mpeg",
2429 "mpegversion", G_TYPE_INT, mpegversion, NULL);
2431 GST_WARNING ("Unknown codec '%s', cannot build Caps",
2437 GstStructure *structure;
2440 for (i=0; i<gst_caps_get_size(caps); i++){
2441 structure = gst_caps_get_structure (caps, i);
2442 if (audiocontext != NULL) {
2443 if (audiocontext->samplerate > 0 &&
2444 audiocontext->channels > 0) {
2445 gst_structure_set (structure,
2446 "channels", G_TYPE_INT, audiocontext->channels,
2447 "rate", G_TYPE_INT, audiocontext->samplerate,
2451 gst_structure_set (structure,
2452 "channels", GST_TYPE_INT_RANGE, 1, 6,
2453 "rate", GST_TYPE_INT_RANGE, 4000, 96000,
2463 gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext *complexcontext,
2464 const gchar *codec_id,
2468 GstCaps *caps = NULL;
2476 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *subtitlecontext,
2477 const gchar *codec_id,
2481 GstCaps *caps = NULL;
2488 static GstElementStateReturn
2489 gst_matroska_demux_change_state (GstElement *element)
2491 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2493 switch (GST_STATE_TRANSITION (element)) {
2494 case GST_STATE_PAUSED_TO_READY:
2495 gst_matroska_demux_reset (GST_ELEMENT (demux));
2501 if (((GstElementClass *) parent_class)->change_state)
2502 return ((GstElementClass *) parent_class)->change_state (element);
2504 return GST_STATE_SUCCESS;
2508 gst_matroska_demux_get_property (GObject *object,
2513 GstMatroskaDemux *demux;
2515 g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
2516 demux = GST_MATROSKA_DEMUX (object);
2519 case ARG_STREAMINFO:
2520 g_value_set_boxed (value, demux->streaminfo);
2523 g_value_set_boxed (value, demux->metadata);
2526 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2532 gst_matroska_demux_plugin_init (GstPlugin *plugin)
2535 GstCaps *videosrccaps, *audiosrccaps, *subtitlesrccaps, *temp;
2536 const gchar *video_id[] = {
2537 GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC,
2538 GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED,
2539 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP,
2540 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP,
2541 GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3,
2542 GST_MATROSKA_CODEC_ID_VIDEO_MPEG1,
2543 GST_MATROSKA_CODEC_ID_VIDEO_MPEG2,
2544 GST_MATROSKA_CODEC_ID_VIDEO_MJPEG,
2545 /* TODO: Real/Quicktime */
2549 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1,
2550 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2,
2551 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3,
2552 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE,
2553 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE,
2554 GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT,
2555 GST_MATROSKA_CODEC_ID_AUDIO_AC3,
2556 GST_MATROSKA_CODEC_ID_AUDIO_ACM,
2557 GST_MATROSKA_CODEC_ID_AUDIO_VORBIS,
2558 GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2559 GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2560 /* TODO: AC3-9/10, Real, Musepack, Quicktime */
2563 }, *complex_id[] = {
2566 }, *subtitle_id[] = {
2571 /* this filter needs the riff parser */
2572 if (!gst_library_load ("gstbytestream") ||
2573 !gst_library_load ("riff")) /* for fourcc stuff */
2576 /* video src template */
2577 videosrccaps = gst_caps_new_empty ();
2578 for (i = 0; video_id[i] != NULL; i++) {
2579 temp = gst_matroska_demux_video_caps (NULL, video_id[i], NULL, 0);
2580 gst_caps_append (videosrccaps, temp);
2582 for (i = 0; complex_id[i] != NULL; i++) {
2583 temp = gst_matroska_demux_complex_caps (NULL, video_id[i], NULL, 0);
2584 gst_caps_append (videosrccaps, temp);
2586 videosrctempl = gst_pad_template_new ("video_%02d",
2591 audiosrccaps = gst_caps_new_empty ();
2592 /* audio src template */
2593 for (i = 0; audio_id[i] != NULL; i++) {
2594 temp = gst_matroska_demux_audio_caps (NULL, audio_id[i], NULL, 0);
2595 gst_caps_append (audiosrccaps, temp);
2597 audiosrctempl = gst_pad_template_new ("audio_%02d",
2602 subtitlesrccaps = gst_caps_new_empty ();
2603 /* subtitle src template */
2604 for (i = 0; subtitle_id[i] != NULL; i++) {
2605 temp = gst_matroska_demux_subtitle_caps (NULL, subtitle_id[i], NULL, 0);
2606 gst_caps_append (subtitlesrccaps, temp);
2608 subtitlesrctempl = gst_pad_template_new ("subtitle_%02d",
2613 /* create an elementfactory for the matroska_demux element */
2614 if (!gst_element_register (plugin, "matroskademux",
2615 GST_RANK_PRIMARY, GST_TYPE_MATROSKA_DEMUX))