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"
50 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
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 *gst_matroska_demux_get_event_mask (GstPad * pad);
68 static gboolean gst_matroska_demux_handle_src_event (GstPad * pad,
70 static const GstFormat *gst_matroska_demux_get_src_formats (GstPad * pad);
71 static const GstQueryType *gst_matroska_demux_get_src_query_types (GstPad *
73 static gboolean gst_matroska_demux_handle_src_query (GstPad * pad,
74 GstQueryType type, GstFormat * format, gint64 * value);
76 /* gst internal change state handler */
77 static GstElementStateReturn
78 gst_matroska_demux_change_state (GstElement * element);
79 static void gst_matroska_demux_set_clock (GstElement * element,
83 static GstCaps *gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext
85 const gchar * codec_id,
86 gpointer data, guint size, GstMatroskaDemux * demux);
87 static GstCaps *gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext
89 const gchar * codec_id,
90 gpointer data, guint size, GstMatroskaDemux * demux);
91 static GstCaps *gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext
92 * complexcontext, const gchar * codec_id, gpointer data, guint size);
94 * gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
95 subtitlecontext, const gchar * codec_id, gpointer data, guint size);
98 static void gst_matroska_demux_reset (GstElement * element);
100 static GstEbmlReadClass *parent_class = NULL;
101 static GstPadTemplate *videosrctempl, *audiosrctempl, *subtitlesrctempl;
103 /*static guint gst_matroska_demux_signals[LAST_SIGNAL] = { 0 };*/
106 gst_matroska_demux_get_type (void)
108 static GType gst_matroska_demux_type = 0;
110 if (!gst_matroska_demux_type) {
111 static const GTypeInfo gst_matroska_demux_info = {
112 sizeof (GstMatroskaDemuxClass),
113 (GBaseInitFunc) gst_matroska_demux_base_init,
115 (GClassInitFunc) gst_matroska_demux_class_init,
118 sizeof (GstMatroskaDemux),
120 (GInstanceInitFunc) gst_matroska_demux_init,
123 gst_matroska_demux_type =
124 g_type_register_static (GST_TYPE_EBML_READ,
125 "GstMatroskaDemux", &gst_matroska_demux_info, 0);
128 return gst_matroska_demux_type;
132 gst_matroska_demux_base_init (GstMatroskaDemuxClass * klass)
134 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
135 static GstElementDetails gst_matroska_demux_details = {
138 "Demuxes a Matroska Stream into video/audio/subtitles",
139 "Ronald Bultje <rbultje@ronald.bitfreak.net>"
142 gst_element_class_add_pad_template (element_class, videosrctempl);
143 gst_element_class_add_pad_template (element_class, audiosrctempl);
144 gst_element_class_add_pad_template (element_class, subtitlesrctempl);
145 gst_element_class_add_pad_template (element_class,
146 gst_static_pad_template_get (&sink_templ));
147 gst_element_class_set_details (element_class, &gst_matroska_demux_details);
151 gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass)
153 GstElementClass *gstelement_class;
155 gstelement_class = (GstElementClass *) klass;
157 parent_class = g_type_class_ref (GST_TYPE_EBML_READ);
159 gstelement_class->change_state = gst_matroska_demux_change_state;
160 gstelement_class->send_event = gst_matroska_demux_send_event;
161 gstelement_class->set_clock = gst_matroska_demux_set_clock;
165 gst_matroska_demux_init (GstMatroskaDemux * demux)
167 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
170 GST_FLAG_SET (GST_OBJECT (demux), GST_ELEMENT_EVENT_AWARE);
173 gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
175 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
176 GST_EBML_READ (demux)->sinkpad = demux->sinkpad;
178 gst_element_set_loop_function (GST_ELEMENT (demux), gst_matroska_demux_loop);
180 /* initial stream no. */
181 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
182 demux->src[i] = NULL;
184 demux->writing_app = demux->muxing_app = NULL;
188 gst_matroska_demux_reset (GST_ELEMENT (demux));
192 gst_matroska_demux_reset (GstElement * element)
194 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
198 demux->state = GST_MATROSKA_DEMUX_STATE_START;
200 /* clean up existing streams */
201 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
202 if (demux->src[i] != NULL) {
203 if (demux->src[i]->pad != NULL) {
204 gst_element_remove_pad (GST_ELEMENT (demux), demux->src[i]->pad);
206 g_free (demux->src[i]->codec_id);
207 g_free (demux->src[i]->codec_name);
208 g_free (demux->src[i]->name);
209 g_free (demux->src[i]->language);
210 g_free (demux->src[i]->codec_priv);
211 g_free (demux->src[i]);
212 demux->src[i] = NULL;
215 demux->num_streams = 0;
216 demux->num_a_streams = 0;
217 demux->num_t_streams = 0;
218 demux->num_v_streams = 0;
220 /* reset media info */
221 g_free (demux->writing_app);
222 demux->writing_app = NULL;
223 g_free (demux->muxing_app);
224 demux->muxing_app = NULL;
227 demux->num_indexes = 0;
228 g_free (demux->index);
233 demux->time_scale = 1000000;
236 demux->created = G_MININT64;
237 demux->seek_pending = GST_CLOCK_TIME_NONE;
239 demux->metadata_parsed = FALSE;
240 demux->index_parsed = FALSE;
244 gst_matroska_demux_set_clock (GstElement * element, GstClock * clock)
246 GST_MATROSKA_DEMUX (element)->clock = clock;
250 gst_matroska_demux_stream_from_num (GstMatroskaDemux * demux, guint track_num)
254 for (n = 0; n < demux->num_streams; n++) {
255 if (demux->src[n] != NULL && demux->src[n]->num == track_num) {
260 if (n == demux->num_streams) {
261 GST_WARNING ("Failed to find corresponding pad for tracknum %d", track_num);
268 gst_matroska_demux_src_getcaps (GstPad * pad)
270 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
273 for (n = 0; n < demux->num_streams; n++) {
274 if (demux->src[n] != NULL && demux->src[n]->pad == pad) {
279 if (n == demux->num_streams)
280 return gst_caps_new_empty ();
282 return gst_caps_copy (demux->src[n]->caps);
286 gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
288 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
289 GstEbmlRead *ebml = GST_EBML_READ (demux);
290 GstMatroskaTrackContext *context;
291 GstPadTemplate *templ = NULL;
292 GstCaps *caps = NULL;
293 gchar *padname = NULL;
297 if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) {
298 GST_WARNING ("Maximum number of streams (%d) exceeded, skipping",
299 GST_MATROSKA_DEMUX_MAX_STREAMS);
300 return gst_ebml_read_skip (ebml); /* skip-and-continue */
303 /* allocate generic... if we know the type, we'll g_renew()
304 * with the precise type */
305 context = g_new0 (GstMatroskaTrackContext, 1);
306 demux->src[demux->num_streams] = context;
307 context->index = demux->num_streams;
308 context->type = 0; /* no type yet */
309 demux->num_streams++;
311 /* start with the master */
312 if (!gst_ebml_read_master (ebml, &id))
315 /* try reading the trackentry headers */
317 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
320 } else if (demux->level_up > 0) {
326 /* track number (unique stream ID) */
327 case GST_MATROSKA_ID_TRACKNUMBER:{
330 if (!gst_ebml_read_uint (ebml, &id, &num)) {
338 /* track UID (unique identifier) */
339 case GST_MATROSKA_ID_TRACKUID:{
342 if (!gst_ebml_read_uint (ebml, &id, &num)) {
350 /* track type (video, audio, combined, subtitle, etc.) */
351 case GST_MATROSKA_ID_TRACKTYPE:{
354 if (context->type != 0) {
356 ("More than one tracktype defined in a trackentry - skipping");
359 if (!gst_ebml_read_uint (ebml, &id, &num)) {
365 /* ok, so we're actually going to reallocate this thing */
366 switch (context->type) {
367 case GST_MATROSKA_TRACK_TYPE_VIDEO:
368 context = (GstMatroskaTrackContext *)
369 g_renew (GstMatroskaTrackVideoContext, context, 1);
371 case GST_MATROSKA_TRACK_TYPE_AUDIO:
372 context = (GstMatroskaTrackContext *)
373 g_renew (GstMatroskaTrackAudioContext, context, 1);
375 ((GstMatroskaTrackAudioContext *) context)->channels = 1;
376 ((GstMatroskaTrackAudioContext *) context)->samplerate = 8000;
378 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
379 context = (GstMatroskaTrackContext *)
380 g_renew (GstMatroskaTrackComplexContext, context, 1);
382 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
383 context = (GstMatroskaTrackContext *)
384 g_renew (GstMatroskaTrackSubtitleContext, context, 1);
386 case GST_MATROSKA_TRACK_TYPE_LOGO:
387 case GST_MATROSKA_TRACK_TYPE_CONTROL:
389 GST_WARNING ("Unknown or unsupported track type 0x%x",
394 demux->src[demux->num_streams - 1] = context;
398 /* tracktype specific stuff for video */
399 case GST_MATROSKA_ID_TRACKVIDEO:{
400 GstMatroskaTrackVideoContext *videocontext;
402 if (context->type != GST_MATROSKA_TRACK_TYPE_VIDEO) {
404 ("trackvideo EBML entry in non-video track - ignoring track");
407 } else if (!gst_ebml_read_master (ebml, &id)) {
411 videocontext = (GstMatroskaTrackVideoContext *) context;
414 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
417 } else if (demux->level_up > 0) {
423 /* fixme, this should be one-up, but I get it here (?) */
424 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
427 if (!gst_ebml_read_uint (ebml, &id, &num)) {
431 context->default_duration = num;
435 /* video framerate */
436 case GST_MATROSKA_ID_VIDEOFRAMERATE:{
439 if (!gst_ebml_read_float (ebml, &id, &num)) {
443 context->default_duration = GST_SECOND * (1. / num);
447 /* width of the size to display the video at */
448 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
451 if (!gst_ebml_read_uint (ebml, &id, &num)) {
455 videocontext->display_width = num;
459 /* height of the size to display the video at */
460 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
463 if (!gst_ebml_read_uint (ebml, &id, &num)) {
467 videocontext->display_height = num;
471 /* width of the video in the file */
472 case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
475 if (!gst_ebml_read_uint (ebml, &id, &num)) {
479 videocontext->pixel_width = num;
483 /* height of the video in the file */
484 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
487 if (!gst_ebml_read_uint (ebml, &id, &num)) {
491 videocontext->pixel_height = num;
495 /* whether the video is interlaced */
496 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
499 if (!gst_ebml_read_uint (ebml, &id, &num)) {
504 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
506 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
510 /* stereo mode (whether the video has two streams, where
511 * one is for the left eye and the other for the right eye,
512 * which creates a 3D-like effect) */
513 case GST_MATROSKA_ID_VIDEOSTEREOMODE:{
516 if (!gst_ebml_read_uint (ebml, &id, &num)) {
520 if (num != GST_MATROSKA_EYE_MODE_MONO &&
521 num != GST_MATROSKA_EYE_MODE_LEFT &&
522 num != GST_MATROSKA_EYE_MODE_RIGHT &&
523 num != GST_MATROSKA_EYE_MODE_BOTH) {
524 GST_WARNING ("Unknown eye mode 0x%x - ignoring", (guint) num);
527 videocontext->eye_mode = num;
531 /* aspect ratio behaviour */
532 case GST_MATROSKA_ID_VIDEOASPECTRATIO:{
535 if (!gst_ebml_read_uint (ebml, &id, &num)) {
539 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
540 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
541 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
542 GST_WARNING ("Unknown aspect ratio mode 0x%x - ignoring",
546 videocontext->asr_mode = num;
550 /* colourspace (only matters for raw video) fourcc */
551 case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
554 if (!gst_ebml_read_uint (ebml, &id, &num)) {
558 videocontext->fourcc = num;
563 GST_WARNING ("Unknown video track header entry 0x%x - ignoring",
567 case GST_EBML_ID_VOID:
568 if (!gst_ebml_read_skip (ebml))
573 if (demux->level_up) {
581 /* tracktype specific stuff for audio */
582 case GST_MATROSKA_ID_TRACKAUDIO:{
583 GstMatroskaTrackAudioContext *audiocontext;
585 if (context->type != GST_MATROSKA_TRACK_TYPE_AUDIO) {
587 ("trackaudio EBML entry in non-audio track - ignoring track");
590 } else if (!gst_ebml_read_master (ebml, &id)) {
594 audiocontext = (GstMatroskaTrackAudioContext *) context;
597 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
600 } else if (demux->level_up > 0) {
607 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
610 if (!gst_ebml_read_float (ebml, &id, &num)) {
614 audiocontext->samplerate = num;
619 case GST_MATROSKA_ID_AUDIOBITDEPTH:{
622 if (!gst_ebml_read_uint (ebml, &id, &num)) {
626 audiocontext->bitdepth = num;
631 case GST_MATROSKA_ID_AUDIOCHANNELS:{
634 if (!gst_ebml_read_uint (ebml, &id, &num)) {
638 audiocontext->channels = num;
643 GST_WARNING ("Unknown audio track header entry 0x%x - ignoring",
647 case GST_EBML_ID_VOID:
648 if (!gst_ebml_read_skip (ebml))
653 if (demux->level_up) {
661 /* codec identifier */
662 case GST_MATROSKA_ID_CODECID:{
665 if (!gst_ebml_read_ascii (ebml, &id, &text)) {
669 context->codec_id = text;
673 /* codec private data */
674 case GST_MATROSKA_ID_CODECPRIVATE:{
678 if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
682 context->codec_priv = data;
683 context->codec_priv_size = size;
687 /* name of the codec */
688 case GST_MATROSKA_ID_CODECNAME:{
691 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
695 context->codec_name = text;
699 /* name of this track */
700 case GST_MATROSKA_ID_TRACKNAME:{
703 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
707 context->name = text;
711 /* language (matters for audio/subtitles, mostly) */
712 case GST_MATROSKA_ID_TRACKLANGUAGE:{
715 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
719 context->language = text;
723 /* whether this is actually used */
724 case GST_MATROSKA_ID_TRACKFLAGENABLED:{
727 if (!gst_ebml_read_uint (ebml, &id, &num)) {
732 context->flags |= GST_MATROSKA_TRACK_ENABLED;
734 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
738 /* whether it's the default for this track type */
739 case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
742 if (!gst_ebml_read_uint (ebml, &id, &num)) {
747 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
749 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
753 /* lacing (like MPEG, where blocks don't end/start on frame
755 case GST_MATROSKA_ID_TRACKFLAGLACING:{
758 if (!gst_ebml_read_uint (ebml, &id, &num)) {
763 context->flags |= GST_MATROSKA_TRACK_LACING;
765 context->flags &= ~GST_MATROSKA_TRACK_LACING;
769 /* default length (in time) of one data block in this track */
770 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
773 if (!gst_ebml_read_uint (ebml, &id, &num)) {
777 context->default_duration = num;
782 GST_WARNING ("Unknown track header entry 0x%x - ignoring", id);
785 /* we ignore these because they're nothing useful (i.e. crap). */
786 case GST_MATROSKA_ID_CODECINFOURL:
787 case GST_MATROSKA_ID_CODECDOWNLOADURL:
788 case GST_MATROSKA_ID_TRACKMINCACHE:
789 case GST_MATROSKA_ID_TRACKMAXCACHE:
790 case GST_EBML_ID_VOID:
791 if (!gst_ebml_read_skip (ebml))
796 if (demux->level_up) {
802 if (context->type == 0 || context->codec_id == NULL || !res) {
804 GST_WARNING ("Unknown stream/codec in track entry header");
806 demux->num_streams--;
807 demux->src[demux->num_streams] = NULL;
809 g_free (context->codec_id);
810 g_free (context->codec_name);
811 g_free (context->name);
812 g_free (context->language);
813 g_free (context->codec_priv);
820 /* now create the GStreamer connectivity */
821 switch (context->type) {
822 case GST_MATROSKA_TRACK_TYPE_VIDEO:{
823 GstMatroskaTrackVideoContext *videocontext =
824 (GstMatroskaTrackVideoContext *) context;
825 padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
826 templ = gst_element_class_get_pad_template (klass, "video_%02d");
827 caps = gst_matroska_demux_video_caps (videocontext,
829 context->codec_priv, context->codec_priv_size, demux);
833 case GST_MATROSKA_TRACK_TYPE_AUDIO:{
834 GstMatroskaTrackAudioContext *audiocontext =
835 (GstMatroskaTrackAudioContext *) context;
836 padname = g_strdup_printf ("audio_%02d", demux->num_a_streams++);
837 templ = gst_element_class_get_pad_template (klass, "audio_%02d");
838 caps = gst_matroska_demux_audio_caps (audiocontext,
840 context->codec_priv, context->codec_priv_size, demux);
844 case GST_MATROSKA_TRACK_TYPE_COMPLEX:{
845 GstMatroskaTrackComplexContext *complexcontext =
846 (GstMatroskaTrackComplexContext *) context;
847 padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
848 templ = gst_element_class_get_pad_template (klass, "video_%02d");
849 caps = gst_matroska_demux_complex_caps (complexcontext,
850 context->codec_id, context->codec_priv, context->codec_priv_size);
854 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
855 GstMatroskaTrackSubtitleContext *subtitlecontext =
856 (GstMatroskaTrackSubtitleContext *) context;
857 padname = g_strdup_printf ("subtitle_%02d", demux->num_t_streams++);
858 templ = gst_element_class_get_pad_template (klass, "subtitle_%02d");
859 caps = gst_matroska_demux_subtitle_caps (subtitlecontext,
860 context->codec_id, context->codec_priv, context->codec_priv_size);
864 case GST_MATROSKA_TRACK_TYPE_LOGO:
865 case GST_MATROSKA_TRACK_TYPE_CONTROL:
867 /* we should already have quit by now */
871 /* the pad in here */
872 context->pad = gst_pad_new_from_template (templ, padname);
873 context->caps = caps ? caps : gst_caps_new_empty ();
877 /* set some functions */
878 gst_pad_set_formats_function (context->pad,
879 gst_matroska_demux_get_src_formats);
880 gst_pad_set_event_mask_function (context->pad,
881 gst_matroska_demux_get_event_mask);
882 gst_pad_set_event_function (context->pad,
883 gst_matroska_demux_handle_src_event);
884 gst_pad_set_query_type_function (context->pad,
885 gst_matroska_demux_get_src_query_types);
886 gst_pad_set_query_function (context->pad,
887 gst_matroska_demux_handle_src_query);
888 gst_pad_set_getcaps_function (context->pad, gst_matroska_demux_src_getcaps);
890 gst_element_add_pad (GST_ELEMENT (demux), context->pad);
896 static const GstFormat *
897 gst_matroska_demux_get_src_formats (GstPad * pad)
899 /*GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad)); */
901 /* we could try to look for units (i.e. samples) in audio streams
902 * or video streams, but both samplerate and framerate are not
903 * always constant, and since we only have a time indication, we
904 * cannot guarantee anything here based purely on index. So, we
905 * only support time for now. */
906 static const GstFormat src_formats[] = {
914 static const GstQueryType *
915 gst_matroska_demux_get_src_query_types (GstPad * pad)
917 static const GstQueryType src_types[] = {
927 gst_matroska_demux_handle_src_query (GstPad * pad,
928 GstQueryType type, GstFormat * format, gint64 * value)
931 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
934 case GST_QUERY_TOTAL:
936 case GST_FORMAT_DEFAULT:
937 *format = GST_FORMAT_TIME;
939 case GST_FORMAT_TIME:
940 *value = demux->duration;
948 case GST_QUERY_POSITION:
950 case GST_FORMAT_DEFAULT:
951 *format = GST_FORMAT_TIME;
953 case GST_FORMAT_TIME:
970 static GstMatroskaIndex *
971 gst_matroskademux_seek (GstMatroskaDemux * demux)
973 guint entry = (guint) - 1;
974 guint64 offset = demux->seek_pending;
977 /* make sure we don't seek twice */
978 demux->seek_pending = GST_CLOCK_TIME_NONE;
980 for (n = 0; n < demux->num_indexes; n++) {
981 if (entry == (guint) - 1) {
984 gfloat diff_old = fabs (1. * (demux->index[entry].time - offset)),
985 diff_new = fabs (1. * (demux->index[n].time - offset));
987 if (diff_new < diff_old) {
993 if (entry != (guint) - 1) {
994 return &demux->index[entry];
1001 gst_matroska_demux_send_event (GstElement * element, GstEvent * event)
1003 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
1004 gboolean res = TRUE;
1006 switch (GST_EVENT_TYPE (event)) {
1007 case GST_EVENT_SEEK:
1008 switch (GST_EVENT_SEEK_FORMAT (event)) {
1009 case GST_FORMAT_TIME:
1010 demux->seek_pending = GST_EVENT_SEEK_OFFSET (event);
1014 GST_WARNING ("Only time seek is supported");
1021 GST_WARNING ("Unhandled event of type %d", GST_EVENT_TYPE (event));
1026 gst_event_unref (event);
1031 static const GstEventMask *
1032 gst_matroska_demux_get_event_mask (GstPad * pad)
1034 static const GstEventMask masks[] = {
1035 {GST_EVENT_SEEK, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1036 (gint) GST_SEEK_FLAG_KEY_UNIT)},
1037 {GST_EVENT_SEEK_SEGMENT, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1038 (gint) GST_SEEK_FLAG_KEY_UNIT)},
1039 {(GstEventType) 0, (GstEventFlag) 0}
1046 gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event)
1048 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
1049 gboolean res = TRUE;
1051 switch (GST_EVENT_TYPE (event)) {
1052 case GST_EVENT_SEEK_SEGMENT:
1053 case GST_EVENT_SEEK:
1054 return gst_matroska_demux_send_event (GST_ELEMENT (demux), event);
1057 GST_WARNING ("Unhandled event of type %d", GST_EVENT_TYPE (event));
1062 gst_event_unref (event);
1068 gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux)
1070 GstEbmlRead *ebml = GST_EBML_READ (demux);
1071 GstMatroskaIndex *entry = gst_matroskademux_seek (demux);
1078 /* seek (relative to segment) */
1079 if (!(event = gst_ebml_read_seek (ebml, entry->pos + demux->segment_start)))
1081 gst_event_unref (event); /* byte - we want time */
1083 gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, entry->time,
1084 GST_FORMAT_UNDEFINED);
1086 /* forward to all src pads */
1087 for (i = 0; i < demux->num_streams; i++) {
1088 if (GST_PAD_IS_USABLE (demux->src[i]->pad)) {
1089 gst_event_ref (event);
1090 gst_pad_push (demux->src[i]->pad, GST_DATA (event));
1094 gst_event_unref (event);
1100 gst_matroska_demux_init_stream (GstMatroskaDemux * demux)
1102 GstEbmlRead *ebml = GST_EBML_READ (demux);
1107 if (!gst_ebml_read_header (ebml, &doctype, &version))
1110 if (!doctype || strcmp (doctype, "matroska") != 0) {
1111 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1112 ("Input is not a matroska stream (doctype=%s)",
1113 doctype ? doctype : "none"));
1119 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1120 ("Demuxer version (1) is too old to read stream version %d", version));
1124 /* find segment, must be the next element */
1128 if (!(id = gst_ebml_peek_id (ebml, &last_level)))
1131 if (id == GST_MATROSKA_ID_SEGMENT)
1135 GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
1136 GST_MATROSKA_ID_SEGMENT, id);
1137 if (!gst_ebml_read_skip (ebml))
1141 /* we now have a EBML segment */
1142 if (!gst_ebml_read_master (ebml, &id))
1144 /* seeks are from the beginning of the segment,
1145 * after the segment ID/length */
1146 demux->segment_start = gst_bytestream_tell (ebml->bs);
1152 gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
1154 GstEbmlRead *ebml = GST_EBML_READ (demux);
1155 gboolean res = TRUE;
1159 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1162 } else if (demux->level_up) {
1168 /* one track within the "all-tracks" header */
1169 case GST_MATROSKA_ID_TRACKENTRY:
1170 if (!gst_matroska_demux_add_stream (demux))
1175 GST_WARNING ("Unknown entry 0x%x in track header", id);
1178 case GST_EBML_ID_VOID:
1179 if (!gst_ebml_read_skip (ebml))
1184 if (demux->level_up) {
1194 gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
1196 GstEbmlRead *ebml = GST_EBML_READ (demux);
1197 gboolean res = TRUE;
1199 GstMatroskaIndex idx;
1203 length = gst_bytestream_length (ebml->bs);
1207 /* We're an element that can be seeked to. If we are, then
1208 * we want to prevent EOS, since that'll kill us. So we cache
1209 * file size and seek until there, and don't call EOS upon os. */
1210 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1213 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1216 } else if (demux->level_up) {
1222 /* one single index entry ('point') */
1223 case GST_MATROSKA_ID_POINTENTRY:
1224 if (!gst_ebml_read_master (ebml, &id)) {
1229 /* in the end, we hope to fill one entry with a
1230 * timestamp, a file position and a tracknum */
1231 idx.pos = (guint64) - 1;
1232 idx.time = (guint64) - 1;
1233 idx.track = (guint16) - 1;
1236 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1239 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1242 } else if (demux->level_up) {
1248 /* one single index entry ('point') */
1249 case GST_MATROSKA_ID_CUETIME:{
1252 if (!gst_ebml_read_uint (ebml, &id, &time)) {
1256 idx.time = time * demux->time_scale;
1260 /* position in the file + track to which it belongs */
1261 case GST_MATROSKA_ID_CUETRACKPOSITION:
1262 if (!gst_ebml_read_master (ebml, &id)) {
1268 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1271 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1274 } else if (demux->level_up) {
1281 case GST_MATROSKA_ID_CUETRACK:{
1284 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1292 /* position in file */
1293 case GST_MATROSKA_ID_CUECLUSTERPOSITION:{
1296 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1305 GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions",
1309 case GST_EBML_ID_VOID:
1310 if (!gst_ebml_read_skip (ebml))
1315 if (demux->level_up) {
1324 GST_WARNING ("Unknown entry 0x%x in cuespoint index", id);
1327 case GST_EBML_ID_VOID:
1328 if (!gst_ebml_read_skip (ebml))
1333 if (demux->level_up) {
1339 /* so let's see if we got what we wanted */
1340 if (idx.pos != (guint64) - 1 &&
1341 idx.time != (guint64) - 1 && idx.track != (guint16) - 1) {
1342 if (demux->num_indexes % 32 == 0) {
1343 /* re-allocate bigger index */
1344 demux->index = g_renew (GstMatroskaIndex, demux->index,
1345 demux->num_indexes + 32);
1347 demux->index[demux->num_indexes].pos = idx.pos;
1348 demux->index[demux->num_indexes].time = idx.time;
1349 demux->index[demux->num_indexes].track = idx.track;
1350 demux->num_indexes++;
1356 GST_WARNING ("Unknown entry 0x%x in cues header", id);
1359 case GST_EBML_ID_VOID:
1360 if (!gst_ebml_read_skip (ebml))
1365 if (demux->level_up) {
1375 gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
1377 GstEbmlRead *ebml = GST_EBML_READ (demux);
1378 gboolean res = TRUE;
1382 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1385 } else if (demux->level_up) {
1391 /* cluster timecode */
1392 case GST_MATROSKA_ID_TIMECODESCALE:{
1395 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1399 demux->time_scale = num;
1403 case GST_MATROSKA_ID_DURATION:{
1406 if (!gst_ebml_read_float (ebml, &id, &num)) {
1410 demux->duration = num * demux->time_scale;
1414 case GST_MATROSKA_ID_WRITINGAPP:{
1417 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1421 demux->writing_app = text;
1425 case GST_MATROSKA_ID_MUXINGAPP:{
1428 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1432 demux->muxing_app = text;
1436 case GST_MATROSKA_ID_DATEUTC:{
1439 if (!gst_ebml_read_date (ebml, &id, &time)) {
1443 demux->created = time;
1448 GST_WARNING ("Unknown entry 0x%x in info header", id);
1451 case GST_EBML_ID_VOID:
1452 if (!gst_ebml_read_skip (ebml))
1457 if (demux->level_up) {
1467 gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
1468 gboolean prevent_eos)
1470 GstEbmlRead *ebml = GST_EBML_READ (demux);
1471 gboolean res = TRUE;
1476 gchar *matroska_tagname;
1477 gchar *gstreamer_tagname;
1482 GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}
1484 GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}
1486 GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}
1488 GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}
1490 GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}
1492 GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}
1494 GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}
1496 GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}
1498 GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}
1503 gboolean have_tags = FALSE;
1504 GstTagList *taglist = gst_tag_list_new ();
1507 length = gst_bytestream_length (ebml->bs);
1511 /* We're an element that can be seeked to. If we are, then
1512 * we want to prevent EOS, since that'll kill us. So we cache
1513 * file size and seek until there, and don't call EOS upon os. */
1514 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1517 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1520 } else if (demux->level_up) {
1526 case GST_MATROSKA_ID_TAG:
1527 if (!gst_ebml_read_master (ebml, &id)) {
1533 /* read all sub-entries */
1534 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1537 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1540 } else if (demux->level_up) {
1546 case GST_MATROSKA_ID_SIMPLETAG:{
1547 gchar *tag = NULL, *value = NULL;
1549 if (!gst_ebml_read_master (ebml, &id)) {
1555 /* read all sub-entries */
1556 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1559 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1562 } else if (demux->level_up) {
1568 case GST_MATROSKA_ID_TAGNAME:
1570 res = gst_ebml_read_ascii (ebml, &id, &tag);
1573 case GST_MATROSKA_ID_TAGSTRING:
1575 res = gst_ebml_read_utf8 (ebml, &id, &value);
1579 GST_WARNING ("Unknown entry 0x%x in metadata collection",
1583 case GST_EBML_ID_VOID:
1584 if (!gst_ebml_read_skip (ebml))
1589 if (demux->level_up) {
1596 for (i = 0; tag_conv[i].matroska_tagname != NULL; i++) {
1597 if (!strcmp (tag_conv[i].matroska_tagname, tag)) {
1602 const gchar *type = tag_conv[i].gstreamer_tagname;
1603 GType dest_type = gst_tag_get_type (type);
1605 g_value_init (&src, G_TYPE_STRING);
1606 g_value_set_string (&src, value);
1607 g_value_init (&dest, dest_type);
1608 g_value_transform (&src, &dest);
1609 g_value_unset (&src);
1610 gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
1612 g_value_unset (&dest);
1624 GST_WARNING ("Unknown entry 0x%x in metadata collection", id);
1627 case GST_EBML_ID_VOID:
1628 if (!gst_ebml_read_skip (ebml))
1633 if (demux->level_up) {
1641 GST_WARNING ("Unknown entry 0x%x in metadata header", id);
1644 case GST_EBML_ID_VOID:
1645 if (!gst_ebml_read_skip (ebml))
1650 if (demux->level_up) {
1657 const GList *padlist;
1659 /* let the world know about this wonderful thing */
1660 for (padlist = gst_element_get_pad_list (GST_ELEMENT (ebml));
1661 padlist != NULL; padlist = padlist->next) {
1662 if (GST_PAD_IS_SRC (padlist->data) && GST_PAD_IS_USABLE (padlist->data)) {
1663 gst_pad_push (GST_PAD (padlist->data),
1664 GST_DATA (gst_event_new_tag (taglist)));
1667 gst_element_found_tags (GST_ELEMENT (ebml), taglist);
1669 gst_tag_list_free (taglist);
1676 * Read signed/unsigned "EBML" numbers.
1677 * Return: number of bytes processed.
1681 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
1683 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1691 while (read <= 8 && !(total & len_mask)) {
1698 if ((total &= (len_mask - 1)) == len_mask - 1)
1703 if (data[n] == 0xff)
1705 total = (total << 8) | data[n];
1712 if (read == num_ffs)
1721 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
1726 /* read as unsigned number first */
1727 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1731 if (unum == G_MAXUINT64)
1734 *num = unum - ((1 << ((7 * res) - 1)) - 1);
1740 gst_matroska_demux_parse_blockgroup (GstMatroskaDemux * demux,
1741 guint64 cluster_time)
1743 GstEbmlRead *ebml = GST_EBML_READ (demux);
1744 gboolean res = TRUE;
1748 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1751 } else if (demux->level_up) {
1757 /* one block inside the group. Note, block parsing is one
1758 * of the harder things, so this code is a bit complicated.
1759 * See http://www.matroska.org/ for documentation. */
1760 case GST_MATROSKA_ID_BLOCK:{
1764 guint size, *lace_size = NULL;
1765 gint n, stream, flags, laces = 0;
1768 if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
1772 data = GST_BUFFER_DATA (buf);
1773 size = GST_BUFFER_SIZE (buf);
1775 /* first byte(s): blocknum */
1776 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1777 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
1778 gst_buffer_unref (buf);
1785 /* fetch stream from num */
1786 stream = gst_matroska_demux_stream_from_num (demux, num);
1787 if (size <= 3 || stream < 0 || stream >= demux->num_streams) {
1788 gst_buffer_unref (buf);
1789 GST_WARNING ("Invalid stream %d or size %u", stream, size);
1792 if (!GST_PAD_IS_USABLE (demux->src[stream]->pad)) {
1793 gst_buffer_unref (buf);
1797 /* time (relative to cluster time) */
1798 time = (GINT16_FROM_BE (*(gint16 *) data)) * demux->time_scale;
1801 flags = *(guint8 *) data;
1804 switch ((flags & 0x06) >> 1) {
1805 case 0x0: /* no lacing */
1807 lace_size = g_new (gint, 1);
1808 lace_size[0] = size;
1811 case 0x1: /* xiph lacing */
1812 case 0x2: /* fixed-size lacing */
1813 case 0x3: /* EBML lacing */
1818 laces = (*(guint8 *) data) + 1;
1821 lace_size = g_new0 (gint, laces);
1823 switch ((flags & 0x06) >> 1) {
1824 case 0x1: /* xiph lacing */ {
1825 guint temp, total = 0;
1827 for (n = 0; res && n < laces - 1; n++) {
1833 temp = *(guint8 *) data;
1834 lace_size[n] += temp;
1840 total += lace_size[n];
1842 lace_size[n] = size - total;
1846 case 0x2: /* fixed-size lacing */
1847 for (n = 0; n < laces; n++)
1848 lace_size[n] = size / laces;
1851 case 0x3: /* EBML lacing */ {
1854 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1855 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1862 total = lace_size[0] = num;
1863 for (n = 1; res && n < laces - 1; n++) {
1867 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
1868 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1875 lace_size[n] = lace_size[n - 1] + snum;
1876 total += lace_size[n];
1878 lace_size[n] = size - total;
1886 for (n = 0; n < laces; n++) {
1887 GstBuffer *sub = gst_buffer_create_sub (buf,
1888 GST_BUFFER_SIZE (buf) - size,
1891 if (cluster_time != GST_CLOCK_TIME_NONE) {
1892 if (time < 0 && (-time) > cluster_time)
1893 GST_BUFFER_TIMESTAMP (sub) = cluster_time;
1895 GST_BUFFER_TIMESTAMP (sub) = cluster_time + time;
1897 /* FIXME: duration */
1899 gst_pad_push (demux->src[stream]->pad, GST_DATA (sub));
1901 size -= lace_size[n];
1906 gst_buffer_unref (buf);
1910 case GST_MATROSKA_ID_BLOCKDURATION:{
1913 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1917 GST_WARNING ("FIXME: implement support for BlockDuration");
1922 GST_WARNING ("Unknown entry 0x%x in blockgroup data", id);
1925 case GST_EBML_ID_VOID:
1926 if (!gst_ebml_read_skip (ebml))
1931 if (demux->level_up) {
1941 gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
1943 GstEbmlRead *ebml = GST_EBML_READ (demux);
1944 gboolean res = TRUE;
1946 guint64 cluster_time = GST_CLOCK_TIME_NONE;
1948 /* We seek after index/header parsing before doing a new
1949 * buffer. So here. */
1950 if (demux->seek_pending != GST_CLOCK_TIME_NONE) {
1951 if (!gst_matroska_demux_handle_seek_event (demux))
1953 demux->seek_pending = GST_CLOCK_TIME_NONE;
1957 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1960 } else if (demux->level_up) {
1966 /* cluster timecode */
1967 case GST_MATROSKA_ID_CLUSTERTIMECODE:{
1970 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1974 cluster_time = num * demux->time_scale;
1978 /* a group of blocks inside a cluster */
1979 case GST_MATROSKA_ID_BLOCKGROUP:
1980 if (!gst_ebml_read_master (ebml, &id)) {
1984 res = gst_matroska_demux_parse_blockgroup (demux, cluster_time);
1988 GST_WARNING ("Unknown entry 0x%x in cluster data", id);
1991 case GST_EBML_ID_VOID:
1992 if (!gst_ebml_read_skip (ebml))
1997 if (demux->level_up) {
2007 gst_matroska_demux_parse_contents (GstMatroskaDemux * demux)
2009 GstEbmlRead *ebml = GST_EBML_READ (demux);
2010 gboolean res = TRUE;
2014 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2017 } else if (demux->level_up) {
2023 case GST_MATROSKA_ID_SEEKENTRY:{
2024 guint32 seek_id = 0;
2025 guint64 seek_pos = (guint64) - 1, t;
2027 if (!gst_ebml_read_master (ebml, &id)) {
2033 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2036 } else if (demux->level_up) {
2042 case GST_MATROSKA_ID_SEEKID:
2043 if (!gst_ebml_read_uint (ebml, &id, &t))
2048 case GST_MATROSKA_ID_SEEKPOSITION:
2049 if (!gst_ebml_read_uint (ebml, &id, &seek_pos))
2054 GST_WARNING ("Unknown seekhead ID 0x%x", id);
2057 case GST_EBML_ID_VOID:
2058 if (!gst_ebml_read_skip (ebml))
2063 if (demux->level_up) {
2069 if (!seek_id || seek_pos == (guint64) - 1) {
2070 GST_WARNING ("Incomplete seekhead entry (0x%x/%"
2071 G_GUINT64_FORMAT ")", seek_id, seek_pos);
2076 case GST_MATROSKA_ID_CUES:
2077 case GST_MATROSKA_ID_TAGS:{
2078 guint level_up = demux->level_up;
2079 guint64 before_pos, length;
2080 GstEbmlLevel *level;
2084 length = gst_bytestream_length (ebml->bs);
2085 before_pos = gst_bytestream_tell (ebml->bs);
2087 /* check for validity */
2088 if (seek_pos + demux->segment_start + 12 >= length) {
2089 g_warning ("Seekhead reference lies outside file!");
2094 if (!(event = gst_ebml_read_seek (ebml,
2095 seek_pos + demux->segment_start)))
2097 gst_event_unref (event);
2099 /* we don't want to lose our seekhead level, so we add
2100 * a dummy. This is a crude hack. */
2101 level = g_new (GstEbmlLevel, 1);
2103 level->length = G_MAXUINT64;
2104 ebml->level = g_list_append (ebml->level, level);
2107 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2111 if (id != seek_id) {
2112 g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%llu)",
2113 seek_id, id, seek_pos + demux->segment_start);
2117 /* read master + parse */
2119 case GST_MATROSKA_ID_CUES:
2120 if (!gst_ebml_read_master (ebml, &id))
2122 else if (!gst_matroska_demux_parse_index (demux, TRUE) &&
2123 gst_bytestream_length (ebml->bs) !=
2124 gst_bytestream_tell (ebml->bs))
2127 demux->index_parsed = TRUE;
2129 case GST_MATROSKA_ID_TAGS:
2130 if (!gst_ebml_read_master (ebml, &id))
2132 else if (!gst_matroska_demux_parse_metadata (demux, TRUE) &&
2133 gst_bytestream_length (ebml->bs) !=
2134 gst_bytestream_tell (ebml->bs))
2137 demux->metadata_parsed = TRUE;
2144 /* remove dummy level */
2145 while (ebml->level) {
2148 level = g_list_last (ebml->level)->data;
2149 ebml->level = g_list_remove (ebml->level, level);
2150 length = level->length;
2152 if (length == G_MAXUINT64)
2157 if (!(event = gst_ebml_read_seek (ebml, before_pos)))
2159 gst_event_unref (event);
2160 demux->level_up = level_up;
2165 GST_INFO ("Ignoring seekhead entry for ID=0x%x", seek_id);
2173 GST_WARNING ("Unknown seekhead ID 0x%x", id);
2176 case GST_EBML_ID_VOID:
2177 if (!gst_ebml_read_skip (ebml))
2182 if (demux->level_up) {
2192 gst_matroska_demux_loop_stream (GstMatroskaDemux * demux)
2194 GstEbmlRead *ebml = GST_EBML_READ (demux);
2195 gboolean res = TRUE;
2198 /* we've found our segment, start reading the different contents in here */
2200 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2203 } else if (demux->level_up) {
2210 case GST_MATROSKA_ID_INFO:{
2211 if (!gst_ebml_read_master (ebml, &id)) {
2215 res = gst_matroska_demux_parse_info (demux);
2219 /* track info headers */
2220 case GST_MATROSKA_ID_TRACKS:{
2221 if (!gst_ebml_read_master (ebml, &id)) {
2225 res = gst_matroska_demux_parse_tracks (demux);
2230 case GST_MATROSKA_ID_CUES:{
2231 if (!demux->index_parsed) {
2232 if (!gst_ebml_read_master (ebml, &id)) {
2236 res = gst_matroska_demux_parse_index (demux, FALSE);
2238 res = gst_ebml_read_skip (ebml);
2243 case GST_MATROSKA_ID_TAGS:{
2244 if (!demux->index_parsed) {
2245 if (!gst_ebml_read_master (ebml, &id)) {
2249 res = gst_matroska_demux_parse_metadata (demux, FALSE);
2251 res = gst_ebml_read_skip (ebml);
2255 /* file index (if seekable, seek to Cues/Tags to parse it) */
2256 case GST_MATROSKA_ID_SEEKHEAD:{
2257 if (!gst_ebml_read_master (ebml, &id)) {
2261 res = gst_matroska_demux_parse_contents (demux);
2265 case GST_MATROSKA_ID_CLUSTER:{
2266 if (!gst_ebml_read_master (ebml, &id)) {
2270 /* The idea is that we parse one cluster per loop and
2271 * then break out of the loop here. In the next call
2272 * of the loopfunc, we will get back here with the
2273 * next cluster. If an error occurs, we didn't
2274 * actually push a buffer, but we still want to break
2275 * out of the loop to handle a possible error. We'll
2276 * get back here if it's recoverable. */
2277 gst_matroska_demux_parse_cluster (demux);
2278 demux->state = GST_MATROSKA_DEMUX_STATE_DATA;
2284 GST_WARNING ("Unknown matroska file header ID 0x%x", id);
2287 case GST_EBML_ID_VOID:
2288 if (!gst_ebml_read_skip (ebml))
2293 if (demux->level_up) {
2303 gst_matroska_demux_loop (GstElement * element)
2305 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2307 /* first, if we're to start, let's actually get starting */
2308 if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
2309 if (!gst_matroska_demux_init_stream (demux)) {
2312 demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
2315 gst_matroska_demux_loop_stream (demux);
2319 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * videocontext,
2320 const gchar * codec_id, gpointer data, guint size, GstMatroskaDemux * demux)
2322 GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) videocontext;
2323 GstCaps *caps = NULL;
2325 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
2326 gst_riff_strf_vids *vids = NULL;
2329 char *codec_name = NULL;
2330 GstTagList *list = gst_tag_list_new ();
2332 vids = (gst_riff_strf_vids *) data;
2334 /* assure size is big enough */
2336 GST_WARNING ("Too small BITMAPINFOHEADER (%d bytes)", size);
2339 if (size < sizeof (gst_riff_strf_vids)) {
2341 (gst_riff_strf_vids *) g_realloc (vids,
2342 sizeof (gst_riff_strf_vids));
2345 /* little-endian -> byte-order */
2346 vids->size = GUINT32_FROM_LE (vids->size);
2347 vids->width = GUINT32_FROM_LE (vids->width);
2348 vids->height = GUINT32_FROM_LE (vids->height);
2349 vids->planes = GUINT16_FROM_LE (vids->planes);
2350 vids->bit_cnt = GUINT16_FROM_LE (vids->bit_cnt);
2351 vids->compression = GUINT32_FROM_LE (vids->compression);
2352 vids->image_size = GUINT32_FROM_LE (vids->image_size);
2353 vids->xpels_meter = GUINT32_FROM_LE (vids->xpels_meter);
2354 vids->ypels_meter = GUINT32_FROM_LE (vids->ypels_meter);
2355 vids->num_colors = GUINT32_FROM_LE (vids->num_colors);
2356 vids->imp_colors = GUINT32_FROM_LE (vids->imp_colors);
2358 caps = gst_riff_create_video_caps (vids->compression, NULL, vids,
2360 gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
2362 if (GST_IS_ELEMENT (demux))
2363 gst_element_found_tags (GST_ELEMENT (demux), list);
2364 gst_tag_list_free (list);
2366 g_free (codec_name);
2368 caps = gst_riff_create_video_template_caps ();
2370 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
2371 /* how nice, this is undocumented... */
2372 if (videocontext != NULL) {
2375 switch (videocontext->fourcc) {
2376 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
2377 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
2378 fourcc = videocontext->fourcc;
2382 GST_DEBUG ("Unknown fourcc " GST_FOURCC_FORMAT,
2383 GST_FOURCC_ARGS (videocontext->fourcc));
2387 caps = gst_caps_new_simple ("video/x-raw-yuv",
2388 "format", GST_TYPE_FOURCC, fourcc, NULL);
2390 caps = gst_caps_from_string ("video/x-raw-yuv, "
2391 "format = (fourcc) { I420, YUY2, YV12 }");
2393 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) {
2394 caps = gst_caps_new_simple ("video/x-divx",
2395 "divxversion", G_TYPE_INT, 4, NULL);
2396 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) ||
2397 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) {
2398 caps = gst_caps_new_full (gst_structure_new ("video/x-divx",
2399 "divxversion", G_TYPE_INT, 5, NULL),
2400 gst_structure_new ("video/x-xvid", NULL),
2401 gst_structure_new ("video/mpeg",
2402 "mpegversion", G_TYPE_INT, 4,
2403 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL), NULL);
2404 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) {
2405 caps = gst_caps_new_full (gst_structure_new ("video/x-divx",
2406 "divxversion", G_TYPE_INT, 3, NULL),
2407 gst_structure_new ("video/x-msmpeg",
2408 "msmpegversion", G_TYPE_INT, 43, NULL), NULL);
2409 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1) ||
2410 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2)) {
2411 gint mpegversion = -1;
2413 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1))
2415 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2))
2420 caps = gst_caps_new_simple ("video/mpeg",
2421 "systemstream", G_TYPE_BOOLEAN, FALSE,
2422 "mpegversion", G_TYPE_INT, mpegversion, NULL);
2423 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) {
2424 caps = gst_caps_new_simple ("video/x-jpeg", NULL);
2426 GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id);
2432 GstStructure *structure;
2434 for (i = 0; i < gst_caps_get_size (caps); i++) {
2435 structure = gst_caps_get_structure (caps, i);
2436 if (videocontext != NULL) {
2437 if (videocontext->pixel_width > 0 && videocontext->pixel_height > 0) {
2438 gint w = videocontext->pixel_width;
2439 gint h = videocontext->pixel_height;
2441 gst_structure_set (structure,
2442 "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, NULL);
2444 gst_structure_set (structure,
2445 "width", GST_TYPE_INT_RANGE, 16, 4096,
2446 "height", GST_TYPE_INT_RANGE, 16, 4096, NULL);
2449 if (videocontext->display_width > 0 && videocontext->display_height > 0) {
2451 100 * videocontext->display_width / videocontext->pixel_width;
2453 100 * videocontext->display_height / videocontext->pixel_height;
2455 gst_structure_set (structure,
2456 "pixel_width", G_TYPE_INT, w,
2457 "pixel_height", G_TYPE_INT, h, NULL);
2460 if (context->default_duration > 0) {
2461 gfloat framerate = 1. * GST_SECOND / context->default_duration;
2463 gst_structure_set (structure,
2464 "framerate", G_TYPE_DOUBLE, framerate, NULL);
2466 /* sort of a hack to get most codecs to support,
2467 * even if the default_duration is missing */
2468 gst_structure_set (structure, "framerate", G_TYPE_DOUBLE, 25.0, NULL);
2471 gst_structure_set (structure,
2472 "width", GST_TYPE_INT_RANGE, 16, 4096,
2473 "height", GST_TYPE_INT_RANGE, 16, 4096,
2474 "pixel_width", GST_TYPE_INT_RANGE, 0, 255,
2475 "pixel_height", GST_TYPE_INT_RANGE, 0, 255,
2476 "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
2485 gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * audiocontext,
2486 const gchar * codec_id, gpointer data, guint size, GstMatroskaDemux * demux)
2488 GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) audiocontext;
2489 GstCaps *caps = NULL;
2491 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
2492 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
2493 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
2496 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1))
2498 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2))
2500 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3))
2505 caps = gst_caps_new_simple ("audio/mpeg",
2506 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL);
2507 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) ||
2508 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) {
2509 gint endianness = -1;
2511 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE))
2512 endianness = G_BIG_ENDIAN;
2513 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE))
2514 endianness = G_LITTLE_ENDIAN;
2518 if (context != NULL) {
2519 caps = gst_caps_new_simple ("audio/x-raw-int",
2520 "width", G_TYPE_INT, audiocontext->bitdepth,
2521 "depth", G_TYPE_INT, audiocontext->bitdepth,
2522 "signed", G_TYPE_BOOLEAN, audiocontext->bitdepth == 8, NULL);
2524 caps = gst_caps_from_string ("audio/x-raw-int, "
2525 "signed = (boolean) { TRUE, FALSE }, "
2526 "depth = (int) { 8, 16 }, " "width = (int) { 8, 16 }");
2528 gst_caps_set_simple (caps, "endianness", G_TYPE_INT, endianness, NULL);
2529 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
2530 caps = gst_caps_new_simple ("audio/x-raw-float",
2531 "endianness", G_TYPE_INT, G_BYTE_ORDER,
2532 "buffer-frames", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
2533 if (audiocontext != NULL) {
2534 gst_caps_set_simple (caps,
2535 "width", G_TYPE_INT, audiocontext->bitdepth, NULL);
2537 gst_caps_set_simple (caps, "width", GST_TYPE_INT_RANGE, 32, 64, NULL);
2539 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AC3,
2540 strlen (GST_MATROSKA_CODEC_ID_AUDIO_AC3)) ||
2541 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) {
2542 caps = gst_caps_new_simple ("audio/x-ac3", NULL);
2543 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
2544 caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
2545 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
2546 gst_riff_strf_auds *auds = NULL;
2549 char *codec_name = NULL;
2550 GstTagList *list = gst_tag_list_new ();
2552 auds = (gst_riff_strf_auds *) data;
2554 /* little-endian -> byte-order */
2555 auds->format = GUINT16_FROM_LE (auds->format);
2556 auds->channels = GUINT16_FROM_LE (auds->channels);
2557 auds->rate = GUINT32_FROM_LE (auds->rate);
2558 auds->av_bps = GUINT32_FROM_LE (auds->av_bps);
2559 auds->blockalign = GUINT16_FROM_LE (auds->blockalign);
2560 auds->size = GUINT16_FROM_LE (auds->size);
2562 caps = gst_riff_create_audio_caps (auds->format, NULL, auds, &codec_name);
2563 gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_AUDIO_CODEC,
2565 if (GST_IS_ELEMENT (demux))
2566 gst_element_found_tags (GST_ELEMENT (demux), list);
2567 gst_tag_list_free (list);
2569 g_free (codec_name);
2571 caps = gst_riff_create_audio_template_caps ();
2573 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2574 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)) ||
2575 !strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2576 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4))) {
2577 gint mpegversion = -1;
2579 if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2580 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)))
2582 else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2583 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4)))
2588 caps = gst_caps_new_simple ("audio/mpeg",
2589 "mpegversion", G_TYPE_INT, mpegversion, NULL);
2591 GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id);
2592 g_print ("Codec=%s\n", codec_id);
2597 GstStructure *structure;
2600 for (i = 0; i < gst_caps_get_size (caps); i++) {
2601 structure = gst_caps_get_structure (caps, i);
2602 if (audiocontext != NULL) {
2603 if (audiocontext->samplerate > 0 && audiocontext->channels > 0) {
2604 gst_structure_set (structure,
2605 "channels", G_TYPE_INT, audiocontext->channels,
2606 "rate", G_TYPE_INT, audiocontext->samplerate, NULL);
2609 gst_structure_set (structure,
2610 "channels", GST_TYPE_INT_RANGE, 1, 6,
2611 "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
2620 gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext *
2621 complexcontext, const gchar * codec_id, gpointer data, guint size)
2623 GstCaps *caps = NULL;
2631 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
2632 subtitlecontext, const gchar * codec_id, gpointer data, guint size)
2634 GstCaps *caps = NULL;
2641 static GstElementStateReturn
2642 gst_matroska_demux_change_state (GstElement * element)
2644 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2646 switch (GST_STATE_TRANSITION (element)) {
2647 case GST_STATE_PAUSED_TO_READY:
2648 gst_matroska_demux_reset (GST_ELEMENT (demux));
2654 if (((GstElementClass *) parent_class)->change_state)
2655 return ((GstElementClass *) parent_class)->change_state (element);
2657 return GST_STATE_SUCCESS;
2661 gst_matroska_demux_plugin_init (GstPlugin * plugin)
2664 GstCaps *videosrccaps, *audiosrccaps, *subtitlesrccaps, *temp;
2665 const gchar *video_id[] = {
2666 GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC,
2667 GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED,
2668 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP,
2669 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP,
2670 GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3,
2671 GST_MATROSKA_CODEC_ID_VIDEO_MPEG1,
2672 GST_MATROSKA_CODEC_ID_VIDEO_MPEG2,
2673 GST_MATROSKA_CODEC_ID_VIDEO_MJPEG,
2674 /* TODO: Real/Quicktime */
2679 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1,
2680 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2,
2681 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3,
2682 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE,
2683 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE,
2684 GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT,
2685 GST_MATROSKA_CODEC_ID_AUDIO_AC3,
2686 GST_MATROSKA_CODEC_ID_AUDIO_ACM,
2687 GST_MATROSKA_CODEC_ID_AUDIO_VORBIS,
2688 GST_MATROSKA_CODEC_ID_AUDIO_MPEG2, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2689 /* TODO: AC3-9/10, Real, Musepack, Quicktime */
2695 , *subtitle_id[] = {
2699 /* this filter needs the riff parser */
2700 if (!gst_library_load ("gstbytestream") || !gst_library_load ("riff")) /* for fourcc stuff */
2703 /* video src template */
2704 videosrccaps = gst_caps_new_empty ();
2705 for (i = 0; video_id[i] != NULL; i++) {
2706 temp = gst_matroska_demux_video_caps (NULL, video_id[i], NULL, 0, NULL);
2707 gst_caps_append (videosrccaps, temp);
2709 for (i = 0; complex_id[i] != NULL; i++) {
2710 temp = gst_matroska_demux_complex_caps (NULL, video_id[i], NULL, 0);
2711 gst_caps_append (videosrccaps, temp);
2713 videosrctempl = gst_pad_template_new ("video_%02d",
2714 GST_PAD_SRC, GST_PAD_SOMETIMES, videosrccaps);
2716 audiosrccaps = gst_caps_new_empty ();
2717 /* audio src template */
2718 for (i = 0; audio_id[i] != NULL; i++) {
2719 temp = gst_matroska_demux_audio_caps (NULL, audio_id[i], NULL, 0, NULL);
2720 gst_caps_append (audiosrccaps, temp);
2722 audiosrctempl = gst_pad_template_new ("audio_%02d",
2723 GST_PAD_SRC, GST_PAD_SOMETIMES, audiosrccaps);
2725 subtitlesrccaps = gst_caps_new_empty ();
2726 /* subtitle src template */
2727 for (i = 0; subtitle_id[i] != NULL; i++) {
2728 temp = gst_matroska_demux_subtitle_caps (NULL, subtitle_id[i], NULL, 0);
2729 gst_caps_append (subtitlesrccaps, temp);
2731 subtitlesrctempl = gst_pad_template_new ("subtitle_%02d",
2732 GST_PAD_SRC, GST_PAD_SOMETIMES, subtitlesrccaps);
2734 /* create an elementfactory for the matroska_demux element */
2735 if (!gst_element_register (plugin, "matroskademux",
2736 GST_RANK_PRIMARY, GST_TYPE_MATROSKA_DEMUX))