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 GST_PAD_TEMPLATE_FACTORY (sink_templ,
59 /* gobject magic foo */
60 static void gst_matroska_demux_base_init (GstMatroskaDemuxClass *klass);
61 static void gst_matroska_demux_class_init (GstMatroskaDemuxClass *klass);
62 static void gst_matroska_demux_init (GstMatroskaDemux *demux);
64 /* element functions */
65 static void gst_matroska_demux_loop (GstElement *element);
66 static gboolean gst_matroska_demux_send_event (GstElement *element,
70 static const GstEventMask *
71 gst_matroska_demux_get_event_mask (GstPad *pad);
72 static gboolean gst_matroska_demux_handle_src_event (GstPad *pad,
74 static const GstFormat *
75 gst_matroska_demux_get_src_formats (GstPad *pad);
76 static const GstQueryType*
77 gst_matroska_demux_get_src_query_types(GstPad *pad);
78 static gboolean gst_matroska_demux_handle_src_query (GstPad *pad,
83 /* gst internal change state handler */
84 static GstElementStateReturn
85 gst_matroska_demux_change_state (GstElement *element);
86 static void gst_matroska_demux_set_clock (GstElement *element,
90 static void gst_matroska_demux_get_property (GObject *object,
96 static GstCaps *gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext
98 const gchar *codec_id,
101 static GstCaps *gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext
103 const gchar *codec_id,
106 static GstCaps *gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext
108 const gchar *codec_id,
111 static GstCaps *gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext
113 const gchar *codec_id,
118 static void gst_matroska_demux_reset (GstElement *element);
120 static GstEbmlReadClass *parent_class = NULL;
121 static GstPadTemplate *videosrctempl, *audiosrctempl, *subtitlesrctempl;
122 /*static guint gst_matroska_demux_signals[LAST_SIGNAL] = { 0 };*/
125 gst_matroska_demux_get_type (void)
127 static GType gst_matroska_demux_type = 0;
129 if (!gst_matroska_demux_type) {
130 static const GTypeInfo gst_matroska_demux_info = {
131 sizeof (GstMatroskaDemuxClass),
132 (GBaseInitFunc) gst_matroska_demux_base_init,
134 (GClassInitFunc) gst_matroska_demux_class_init,
137 sizeof (GstMatroskaDemux),
139 (GInstanceInitFunc) gst_matroska_demux_init,
142 gst_matroska_demux_type =
143 g_type_register_static (GST_TYPE_EBML_READ,
145 &gst_matroska_demux_info, 0);
148 return gst_matroska_demux_type;
152 gst_matroska_demux_base_init (GstMatroskaDemuxClass *klass)
154 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
155 static GstElementDetails gst_matroska_demux_details = {
158 "Demuxes a Matroska Stream into video/audio/subtitles",
159 "Ronald Bultje <rbultje@ronald.bitfreak.net>"
162 gst_element_class_add_pad_template (element_class, videosrctempl);
163 gst_element_class_add_pad_template (element_class, audiosrctempl);
164 gst_element_class_add_pad_template (element_class, subtitlesrctempl);
165 gst_element_class_add_pad_template (element_class,
166 GST_PAD_TEMPLATE_GET (sink_templ));
167 gst_element_class_set_details (element_class,
168 &gst_matroska_demux_details);
172 gst_matroska_demux_class_init (GstMatroskaDemuxClass *klass)
174 GObjectClass *gobject_class;
175 GstElementClass *gstelement_class;
177 gobject_class = (GObjectClass *) klass;
178 gstelement_class = (GstElementClass *) klass;
180 g_object_class_install_property (gobject_class, ARG_METADATA,
181 g_param_spec_boxed ("metadata", "Metadata", "Metadata",
182 GST_TYPE_CAPS, G_PARAM_READABLE));
183 g_object_class_install_property (gobject_class, ARG_STREAMINFO,
184 g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
185 GST_TYPE_CAPS, G_PARAM_READABLE));
187 parent_class = g_type_class_ref (GST_TYPE_EBML_READ);
189 gobject_class->get_property = gst_matroska_demux_get_property;
191 gstelement_class->change_state = gst_matroska_demux_change_state;
192 gstelement_class->send_event = gst_matroska_demux_send_event;
193 gstelement_class->set_clock = gst_matroska_demux_set_clock;
197 gst_matroska_demux_init (GstMatroskaDemux *demux)
199 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
202 GST_FLAG_SET (GST_OBJECT (demux), GST_ELEMENT_EVENT_AWARE);
204 demux->sinkpad = gst_pad_new_from_template (
205 gst_element_class_get_pad_template (klass, "sink"), "sink");
206 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
207 GST_EBML_READ (demux)->sinkpad = demux->sinkpad;
209 gst_element_set_loop_function (GST_ELEMENT (demux),
210 gst_matroska_demux_loop);
212 /* initial stream no. */
213 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
214 demux->src[i] = NULL;
216 demux->streaminfo = demux->metadata = NULL;
217 demux->writing_app = demux->muxing_app = NULL;
221 gst_matroska_demux_reset (GST_ELEMENT (demux));
225 gst_matroska_demux_reset (GstElement *element)
227 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
231 demux->state = GST_MATROSKA_DEMUX_STATE_START;
233 /* clean up existing streams */
234 for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
235 if (demux->src[i] != NULL) {
236 if (demux->src[i]->pad != NULL) {
237 gst_element_remove_pad (GST_ELEMENT (demux), demux->src[i]->pad);
239 g_free (demux->src[i]->codec_id);
240 g_free (demux->src[i]->codec_name);
241 g_free (demux->src[i]->name);
242 g_free (demux->src[i]->language);
243 g_free (demux->src[i]->codec_priv);
244 g_free (demux->src[i]);
245 demux->src[i] = NULL;
248 demux->num_streams = 0;
249 demux->num_a_streams = 0;
250 demux->num_t_streams = 0;
251 demux->num_v_streams = 0;
253 /* reset media info */
254 gst_caps_replace (&demux->metadata, NULL);
255 gst_caps_replace (&demux->streaminfo, NULL);
257 g_free (demux->writing_app);
258 demux->writing_app = NULL;
259 g_free (demux->muxing_app);
260 demux->muxing_app = NULL;
263 demux->num_indexes = 0;
264 g_free (demux->index);
269 demux->time_scale = 1000000;
272 demux->created = G_MININT64;
273 demux->seek_pending = GST_CLOCK_TIME_NONE;
275 demux->metadata_parsed = FALSE;
276 demux->index_parsed = FALSE;
280 gst_matroska_demux_set_clock (GstElement *element,
283 GST_MATROSKA_DEMUX (element)->clock = clock;
287 gst_matroska_demux_stream_from_num (GstMatroskaDemux *demux,
292 for (n = 0; n < demux->num_streams; n++) {
293 if (demux->src[n] != NULL &&
294 demux->src[n]->num == track_num) {
299 if (n == demux->num_streams) {
300 GST_WARNING ("Failed to find corresponding pad for tracknum %d",
308 gst_matroska_demux_add_stream (GstMatroskaDemux *demux)
310 GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
311 GstEbmlRead *ebml = GST_EBML_READ (demux);
312 GstMatroskaTrackContext *context;
313 GstPadTemplate *templ = NULL;
314 GstCaps *caps = NULL;
315 gchar *padname = NULL;
319 if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) {
320 GST_WARNING ("Maximum number of streams (%d) exceeded, skipping",
321 GST_MATROSKA_DEMUX_MAX_STREAMS);
322 return gst_ebml_read_skip (ebml); /* skip-and-continue */
325 /* allocate generic... if we know the type, we'll g_renew()
326 * with the precise type */
327 context = g_new0 (GstMatroskaTrackContext, 1);
328 demux->src[demux->num_streams] = context;
329 context->index = demux->num_streams;
330 context->type = 0; /* no type yet */
331 demux->num_streams++;
333 /* start with the master */
334 if (!gst_ebml_read_master (ebml, &id))
337 /* try reading the trackentry headers */
339 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
342 } else if (demux->level_up > 0) {
348 /* track number (unique stream ID) */
349 case GST_MATROSKA_ID_TRACKNUMBER: {
351 if (!gst_ebml_read_uint (ebml, &id, &num)) {
359 /* track UID (unique identifier) */
360 case GST_MATROSKA_ID_TRACKUID: {
362 if (!gst_ebml_read_uint (ebml, &id, &num)) {
370 /* track type (video, audio, combined, subtitle, etc.) */
371 case GST_MATROSKA_ID_TRACKTYPE: {
373 if (context->type != 0) {
374 GST_WARNING ("More than one tracktype defined in a trackentry - skipping");
377 if (!gst_ebml_read_uint (ebml, &id, &num)) {
383 /* ok, so we're actually going to reallocate this thing */
384 switch (context->type) {
385 case GST_MATROSKA_TRACK_TYPE_VIDEO:
386 context = (GstMatroskaTrackContext *)
387 g_renew (GstMatroskaTrackVideoContext, context, 1);
389 case GST_MATROSKA_TRACK_TYPE_AUDIO:
390 context = (GstMatroskaTrackContext *)
391 g_renew (GstMatroskaTrackAudioContext, context, 1);
393 ((GstMatroskaTrackAudioContext *) context)->channels = 1;
394 ((GstMatroskaTrackAudioContext *) context)->samplerate = 8000;
396 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
397 context = (GstMatroskaTrackContext *)
398 g_renew (GstMatroskaTrackComplexContext, context, 1);
400 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
401 context = (GstMatroskaTrackContext *)
402 g_renew (GstMatroskaTrackSubtitleContext, context, 1);
404 case GST_MATROSKA_TRACK_TYPE_LOGO:
405 case GST_MATROSKA_TRACK_TYPE_CONTROL:
407 GST_WARNING ("Unknown or unsupported track type 0x%x",
412 demux->src[demux->num_streams-1] = context;
416 /* tracktype specific stuff for video */
417 case GST_MATROSKA_ID_TRACKVIDEO: {
418 GstMatroskaTrackVideoContext *videocontext;
419 if (context->type != GST_MATROSKA_TRACK_TYPE_VIDEO) {
420 GST_WARNING ("trackvideo EBML entry in non-video track - ignoring track");
423 } else if (!gst_ebml_read_master (ebml, &id)) {
427 videocontext = (GstMatroskaTrackVideoContext *) context;
430 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
433 } else if (demux->level_up > 0) {
439 /* fixme, this should be one-up, but I get it here (?) */
440 case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
442 if (!gst_ebml_read_uint (ebml, &id, &num)) {
446 context->default_duration = num;
450 /* video framerate */
451 case GST_MATROSKA_ID_VIDEOFRAMERATE: {
453 if (!gst_ebml_read_float (ebml, &id, &num)) {
457 context->default_duration = GST_SECOND * (1. / num);
461 /* width of the size to display the video at */
462 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH: {
464 if (!gst_ebml_read_uint (ebml, &id, &num)) {
468 videocontext->display_width = num;
472 /* height of the size to display the video at */
473 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT: {
475 if (!gst_ebml_read_uint (ebml, &id, &num)) {
479 videocontext->display_height = num;
483 /* width of the video in the file */
484 case GST_MATROSKA_ID_VIDEOPIXELWIDTH: {
486 if (!gst_ebml_read_uint (ebml, &id, &num)) {
490 videocontext->pixel_width = num;
494 /* height of the video in the file */
495 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT: {
497 if (!gst_ebml_read_uint (ebml, &id, &num)) {
501 videocontext->pixel_height = num;
505 /* whether the video is interlaced */
506 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED: {
508 if (!gst_ebml_read_uint (ebml, &id, &num)) {
513 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
515 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
519 /* stereo mode (whether the video has two streams, where
520 * one is for the left eye and the other for the right eye,
521 * which creates a 3D-like effect) */
522 case GST_MATROSKA_ID_VIDEOSTEREOMODE: {
524 if (!gst_ebml_read_uint (ebml, &id, &num)) {
528 if (num != GST_MATROSKA_EYE_MODE_MONO &&
529 num != GST_MATROSKA_EYE_MODE_LEFT &&
530 num != GST_MATROSKA_EYE_MODE_RIGHT &&
531 num != GST_MATROSKA_EYE_MODE_BOTH) {
532 GST_WARNING ("Unknown eye mode 0x%x - ignoring",
536 videocontext->eye_mode = num;
540 /* aspect ratio behaviour */
541 case GST_MATROSKA_ID_VIDEOASPECTRATIO: {
543 if (!gst_ebml_read_uint (ebml, &id, &num)) {
547 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
548 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
549 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
550 GST_WARNING ("Unknown aspect ratio mode 0x%x - ignoring",
554 videocontext->asr_mode = num;
558 /* colourspace (only matters for raw video) fourcc */
559 case GST_MATROSKA_ID_VIDEOCOLOURSPACE: {
561 if (!gst_ebml_read_uint (ebml, &id, &num)) {
565 videocontext->fourcc = num;
570 GST_WARNING ("Unknown video track header entry 0x%x - ignoring",
574 case GST_EBML_ID_VOID:
575 if (!gst_ebml_read_skip (ebml))
580 if (demux->level_up) {
588 /* tracktype specific stuff for audio */
589 case GST_MATROSKA_ID_TRACKAUDIO: {
590 GstMatroskaTrackAudioContext *audiocontext;
591 if (context->type != GST_MATROSKA_TRACK_TYPE_AUDIO) {
592 GST_WARNING ("trackaudio EBML entry in non-audio track - ignoring track");
595 } else if (!gst_ebml_read_master (ebml, &id)) {
599 audiocontext = (GstMatroskaTrackAudioContext *) context;
602 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
605 } else if (demux->level_up > 0) {
612 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ: {
614 if (!gst_ebml_read_float (ebml, &id, &num)) {
618 audiocontext->samplerate = num;
623 case GST_MATROSKA_ID_AUDIOBITDEPTH: {
625 if (!gst_ebml_read_uint (ebml, &id, &num)) {
629 audiocontext->bitdepth = num;
634 case GST_MATROSKA_ID_AUDIOCHANNELS: {
636 if (!gst_ebml_read_uint (ebml, &id, &num)) {
640 audiocontext->channels = num;
645 GST_WARNING ("Unknown audio track header entry 0x%x - ignoring",
649 case GST_EBML_ID_VOID:
650 if (!gst_ebml_read_skip (ebml))
655 if (demux->level_up) {
663 /* codec identifier */
664 case GST_MATROSKA_ID_CODECID: {
666 if (!gst_ebml_read_ascii (ebml, &id, &text)) {
670 context->codec_id = text;
674 /* codec private data */
675 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: {
690 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
694 context->codec_name = text;
698 /* name of this track */
699 case GST_MATROSKA_ID_TRACKNAME: {
701 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
705 context->name = text;
709 /* language (matters for audio/subtitles, mostly) */
710 case GST_MATROSKA_ID_TRACKLANGUAGE: {
712 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
716 context->language = text;
720 /* whether this is actually used */
721 case GST_MATROSKA_ID_TRACKFLAGENABLED: {
723 if (!gst_ebml_read_uint (ebml, &id, &num)) {
728 context->flags |= GST_MATROSKA_TRACK_ENABLED;
730 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
734 /* whether it's the default for this track type */
735 case GST_MATROSKA_ID_TRACKFLAGDEFAULT: {
737 if (!gst_ebml_read_uint (ebml, &id, &num)) {
742 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
744 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
748 /* lacing (like MPEG, where blocks don't end/start on frame
750 case GST_MATROSKA_ID_TRACKFLAGLACING: {
752 if (!gst_ebml_read_uint (ebml, &id, &num)) {
757 context->flags |= GST_MATROSKA_TRACK_LACING;
759 context->flags &= ~GST_MATROSKA_TRACK_LACING;
763 /* default length (in time) of one data block in this track */
764 case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
766 if (!gst_ebml_read_uint (ebml, &id, &num)) {
770 context->default_duration = num;
775 GST_WARNING ("Unknown track header entry 0x%x - ignoring", id);
778 /* we ignore these because they're nothing useful (i.e. crap). */
779 case GST_MATROSKA_ID_CODECINFOURL:
780 case GST_MATROSKA_ID_CODECDOWNLOADURL:
781 case GST_MATROSKA_ID_TRACKMINCACHE:
782 case GST_MATROSKA_ID_TRACKMAXCACHE:
783 case GST_EBML_ID_VOID:
784 if (!gst_ebml_read_skip (ebml))
789 if (demux->level_up) {
795 if (context->type == 0 || context->codec_id == NULL || !res) {
797 GST_WARNING ("Unknown stream/codec in track entry header");
799 demux->num_streams--;
800 demux->src[demux->num_streams] = NULL;
802 g_free (context->codec_id);
803 g_free (context->codec_name);
804 g_free (context->name);
805 g_free (context->language);
806 g_free (context->codec_priv);
813 /* now create the GStreamer connectivity */
814 switch (context->type) {
815 case GST_MATROSKA_TRACK_TYPE_VIDEO: {
816 GstMatroskaTrackVideoContext *videocontext =
817 (GstMatroskaTrackVideoContext *) context;
818 padname = g_strdup_printf ("video_%02d", demux->num_v_streams);
819 templ = gst_element_class_get_pad_template (klass, "video_%02d");
820 caps = gst_matroska_demux_video_caps (videocontext,
823 context->codec_priv_size);
827 case GST_MATROSKA_TRACK_TYPE_AUDIO: {
828 GstMatroskaTrackAudioContext *audiocontext =
829 (GstMatroskaTrackAudioContext *) context;
830 padname = g_strdup_printf ("audio_%02d", demux->num_a_streams);
831 templ = gst_element_class_get_pad_template (klass, "audio_%02d");
832 caps = gst_matroska_demux_audio_caps (audiocontext,
835 context->codec_priv_size);
839 case GST_MATROSKA_TRACK_TYPE_COMPLEX: {
840 GstMatroskaTrackComplexContext *complexcontext =
841 (GstMatroskaTrackComplexContext *) context;
842 padname = g_strdup_printf ("video_%02d", demux->num_v_streams);
843 templ = gst_element_class_get_pad_template (klass, "video_%02d");
844 caps = gst_matroska_demux_complex_caps (complexcontext,
847 context->codec_priv_size);
851 case GST_MATROSKA_TRACK_TYPE_SUBTITLE: {
852 GstMatroskaTrackSubtitleContext *subtitlecontext =
853 (GstMatroskaTrackSubtitleContext *) context;
854 padname = g_strdup_printf ("subtitle_%02d", demux->num_t_streams);
855 templ = gst_element_class_get_pad_template (klass, "subtitle_%02d");
856 caps = gst_matroska_demux_subtitle_caps (subtitlecontext,
859 context->codec_priv_size);
863 case GST_MATROSKA_TRACK_TYPE_LOGO:
864 case GST_MATROSKA_TRACK_TYPE_CONTROL:
866 /* we should already have quit by now */
870 /* the pad in here */
871 context->pad = gst_pad_new_from_template (templ, padname);
874 if (gst_pad_try_set_caps (context->pad, caps) <= 0) {
875 GST_WARNING ("Failed to set caps on next element for %s",
881 /* set some functions */
882 gst_pad_set_formats_function (context->pad,
883 gst_matroska_demux_get_src_formats);
884 gst_pad_set_event_mask_function (context->pad,
885 gst_matroska_demux_get_event_mask);
886 gst_pad_set_event_function (context->pad,
887 gst_matroska_demux_handle_src_event);
888 gst_pad_set_query_type_function (context->pad,
889 gst_matroska_demux_get_src_query_types);
890 gst_pad_set_query_function (context->pad,
891 gst_matroska_demux_handle_src_query);
893 gst_element_add_pad (GST_ELEMENT (demux), context->pad);
899 static const GstFormat *
900 gst_matroska_demux_get_src_formats (GstPad *pad)
902 /*GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));*/
904 /* we could try to look for units (i.e. samples) in audio streams
905 * or video streams, but both samplerate and framerate are not
906 * always constant, and since we only have a time indication, we
907 * cannot guarantee anything here based purely on index. So, we
908 * only support time for now. */
909 static const GstFormat src_formats[] = {
917 static const GstQueryType *
918 gst_matroska_demux_get_src_query_types (GstPad *pad)
920 static const GstQueryType src_types[] = {
930 gst_matroska_demux_handle_src_query (GstPad *pad,
936 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
939 case GST_QUERY_TOTAL:
941 case GST_FORMAT_DEFAULT:
942 *format = GST_FORMAT_TIME;
944 case GST_FORMAT_TIME:
945 *value = demux->duration;
953 case GST_QUERY_POSITION:
955 case GST_FORMAT_DEFAULT:
956 *format = GST_FORMAT_TIME;
958 case GST_FORMAT_TIME:
975 static GstMatroskaIndex *
976 gst_matroskademux_seek (GstMatroskaDemux *demux)
978 guint entry = (guint) -1;
979 guint64 offset = demux->seek_pending;
982 /* make sure we don't seek twice */
983 demux->seek_pending = GST_CLOCK_TIME_NONE;
985 for (n = 0; n < demux->num_indexes; n++) {
986 if (entry == (guint) -1) {
989 gfloat diff_old = fabs (1. * (demux->index[entry].time - offset)),
990 diff_new = fabs (1. * (demux->index[n].time - offset));
992 if (diff_new < diff_old) {
998 if (entry != (guint) -1) {
999 return &demux->index[entry];
1006 gst_matroska_demux_send_event (GstElement *element,
1009 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
1010 gboolean res = TRUE;
1012 switch (GST_EVENT_TYPE (event)) {
1013 case GST_EVENT_SEEK:
1014 switch (GST_EVENT_SEEK_FORMAT (event)) {
1015 case GST_FORMAT_TIME:
1016 demux->seek_pending = GST_EVENT_SEEK_OFFSET (event);
1020 GST_WARNING ("Only time seek is supported");
1027 GST_WARNING ("Unhandled event of type %d",
1028 GST_EVENT_TYPE (event));
1033 gst_event_unref (event);
1038 static const GstEventMask *
1039 gst_matroska_demux_get_event_mask (GstPad *pad)
1041 static const GstEventMask masks[] = {
1042 { GST_EVENT_SEEK, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1043 (gint) GST_SEEK_FLAG_KEY_UNIT) },
1044 { GST_EVENT_SEEK_SEGMENT, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1045 (gint) GST_SEEK_FLAG_KEY_UNIT) },
1046 { (GstEventType) 0, (GstEventFlag) 0 }
1053 gst_matroska_demux_handle_src_event (GstPad *pad,
1056 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
1057 gboolean res = TRUE;
1059 switch (GST_EVENT_TYPE (event)) {
1060 case GST_EVENT_SEEK_SEGMENT:
1061 case GST_EVENT_SEEK:
1062 return gst_matroska_demux_send_event (GST_ELEMENT (demux), event);
1065 GST_WARNING ("Unhandled event of type %d",
1066 GST_EVENT_TYPE (event));
1071 gst_event_unref (event);
1077 gst_matroska_demux_handle_seek_event (GstMatroskaDemux *demux)
1079 GstEbmlRead *ebml = GST_EBML_READ (demux);
1080 GstMatroskaIndex *entry = gst_matroskademux_seek (demux);
1087 /* seek (relative to segment) */
1088 if (!(event = gst_ebml_read_seek (ebml,
1089 entry->pos + demux->segment_start)))
1091 gst_event_unref (event); /* byte - we want time */
1092 event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
1095 /* forward to all src pads */
1096 for (i = 0; i < demux->num_streams; i++) {
1097 if (GST_PAD_IS_USABLE (demux->src[i]->pad)) {
1098 gst_event_ref (event);
1099 gst_pad_push (demux->src[i]->pad, GST_DATA (event));
1103 gst_event_unref (event);
1109 gst_matroska_demux_init_stream (GstMatroskaDemux *demux)
1111 GstEbmlRead *ebml = GST_EBML_READ (demux);
1116 if (!gst_ebml_read_header (ebml, &doctype, &version))
1119 if (!doctype || strcmp (doctype, "matroska") != 0) {
1120 gst_element_error (GST_ELEMENT (demux),
1121 "Input is not a matroska stream (doctype=%s)",
1122 doctype ? doctype : "none");
1128 gst_element_error (GST_ELEMENT (demux),
1129 "Demuxer version (1) is too old to read stream version %d",
1134 /* find segment, must be the next element */
1138 if (!(id = gst_ebml_peek_id (ebml, &last_level)))
1141 if (id == GST_MATROSKA_ID_SEGMENT)
1145 GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
1146 GST_MATROSKA_ID_SEGMENT, id);
1147 if (!gst_ebml_read_skip (ebml))
1151 /* we now have a EBML segment */
1152 if (!gst_ebml_read_master (ebml, &id))
1154 /* seeks are from the beginning of the segment,
1155 * after the segment ID/length */
1156 demux->segment_start = gst_bytestream_tell (ebml->bs);
1162 gst_matroska_demux_parse_tracks (GstMatroskaDemux *demux)
1164 GstEbmlRead *ebml = GST_EBML_READ (demux);
1165 gboolean res = TRUE;
1169 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1172 } else if (demux->level_up) {
1178 /* one track within the "all-tracks" header */
1179 case GST_MATROSKA_ID_TRACKENTRY:
1180 if (!gst_matroska_demux_add_stream (demux))
1185 GST_WARNING ("Unknown entry 0x%x in track header", id);
1188 case GST_EBML_ID_VOID:
1189 if (!gst_ebml_read_skip (ebml))
1194 if (demux->level_up) {
1204 gst_matroska_demux_parse_index (GstMatroskaDemux *demux,
1205 gboolean prevent_eos)
1207 GstEbmlRead *ebml = GST_EBML_READ (demux);
1208 gboolean res = TRUE;
1210 GstMatroskaIndex idx;
1214 length = gst_bytestream_length (ebml->bs);
1215 gst_clock_set_active (demux->clock, FALSE);
1219 /* We're an element that can be seeked to. If we are, then
1220 * we want to prevent EOS, since that'll kill us. So we cache
1221 * file size and seek until there, and don't call EOS upon os. */
1222 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1225 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1228 } else if (demux->level_up) {
1234 /* one single index entry ('point') */
1235 case GST_MATROSKA_ID_POINTENTRY:
1236 if (!gst_ebml_read_master (ebml, &id)) {
1241 /* in the end, we hope to fill one entry with a
1242 * timestamp, a file position and a tracknum */
1243 idx.pos = (guint64) -1;
1244 idx.time = (guint64) -1;
1245 idx.track = (guint16) -1;
1248 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1251 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1254 } else if (demux->level_up) {
1260 /* one single index entry ('point') */
1261 case GST_MATROSKA_ID_CUETIME: {
1263 if (!gst_ebml_read_uint (ebml, &id, &time)) {
1267 idx.time = time * demux->time_scale;
1271 /* position in the file + track to which it belongs */
1272 case GST_MATROSKA_ID_CUETRACKPOSITION:
1273 if (!gst_ebml_read_master (ebml, &id)) {
1279 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1282 } else if (!(id = gst_ebml_peek_id (ebml,
1283 &demux->level_up))) {
1286 } else if (demux->level_up) {
1293 case GST_MATROSKA_ID_CUETRACK: {
1295 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1303 /* position in file */
1304 case GST_MATROSKA_ID_CUECLUSTERPOSITION: {
1306 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1315 GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions", id);
1318 case GST_EBML_ID_VOID:
1319 if (!gst_ebml_read_skip (ebml))
1324 if (demux->level_up) {
1333 GST_WARNING ("Unknown entry 0x%x in cuespoint index", id);
1336 case GST_EBML_ID_VOID:
1337 if (!gst_ebml_read_skip (ebml))
1342 if (demux->level_up) {
1348 /* so let's see if we got what we wanted */
1349 if (idx.pos != (guint64) -1 &&
1350 idx.time != (guint64) -1 &&
1351 idx.track != (guint16) -1) {
1352 if (demux->num_indexes % 32 == 0) {
1353 /* re-allocate bigger index */
1354 demux->index = g_renew (GstMatroskaIndex, demux->index,
1355 demux->num_indexes + 32);
1357 demux->index[demux->num_indexes].pos = idx.pos;
1358 demux->index[demux->num_indexes].time = idx.time;
1359 demux->index[demux->num_indexes].track = idx.track;
1360 demux->num_indexes++;
1366 GST_WARNING ("Unknown entry 0x%x in cues header", id);
1369 case GST_EBML_ID_VOID:
1370 if (!gst_ebml_read_skip (ebml))
1375 if (demux->level_up) {
1382 gst_clock_set_active (demux->clock, TRUE);
1389 gst_matroska_demux_parse_info (GstMatroskaDemux *demux)
1391 GstEbmlRead *ebml = GST_EBML_READ (demux);
1392 gboolean res = TRUE;
1396 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1399 } else if (demux->level_up) {
1405 /* cluster timecode */
1406 case GST_MATROSKA_ID_TIMECODESCALE: {
1408 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1412 demux->time_scale = num;
1416 case GST_MATROSKA_ID_DURATION: {
1418 if (!gst_ebml_read_float (ebml, &id, &num)) {
1422 demux->duration = num * demux->time_scale;
1426 case GST_MATROSKA_ID_WRITINGAPP: {
1428 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1432 demux->writing_app = text;
1436 case GST_MATROSKA_ID_MUXINGAPP: {
1438 if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1442 demux->muxing_app = text;
1446 case GST_MATROSKA_ID_DATEUTC: {
1448 if (!gst_ebml_read_date (ebml, &id, &time)) {
1452 demux->created = time;
1457 GST_WARNING ("Unknown entry 0x%x in info header", id);
1460 case GST_EBML_ID_VOID:
1461 if (!gst_ebml_read_skip (ebml))
1466 if (demux->level_up) {
1476 gst_matroska_demux_parse_metadata (GstMatroskaDemux *demux,
1477 gboolean prevent_eos)
1479 GstEbmlRead *ebml = GST_EBML_READ (demux);
1480 gboolean res = TRUE;
1485 length = gst_bytestream_length (ebml->bs);
1486 gst_clock_set_active (demux->clock, FALSE);
1490 /* We're an element that can be seeked to. If we are, then
1491 * we want to prevent EOS, since that'll kill us. So we cache
1492 * file size and seek until there, and don't call EOS upon os. */
1493 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1496 } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1499 } else if (demux->level_up) {
1506 GST_WARNING ("metadata unimplemented");
1509 case GST_EBML_ID_VOID:
1510 if (!gst_ebml_read_skip (ebml))
1515 if (demux->level_up) {
1522 gst_clock_set_active (demux->clock, TRUE);
1529 * Read signed/unsigned "EBML" numbers.
1530 * Return: number of bytes processed.
1534 gst_matroska_ebmlnum_uint (guint8 *data,
1538 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1546 while (read <= 8 && !(total & len_mask)) {
1553 if ((total &= (len_mask - 1)) == len_mask - 1)
1558 if (data[n] == 0xff)
1560 total = (total << 8) | data[n];
1567 if (read == num_ffs)
1576 gst_matroska_ebmlnum_sint (guint8 *data,
1583 /* read as unsigned number first */
1584 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1588 if (unum == G_MAXUINT64)
1591 *num = unum - ((1 << ((7 * res) - 1)) - 1);
1597 gst_matroska_demux_parse_blockgroup (GstMatroskaDemux *demux,
1598 guint64 cluster_time)
1600 GstEbmlRead *ebml = GST_EBML_READ (demux);
1601 gboolean res = TRUE;
1605 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1608 } else if (demux->level_up) {
1614 /* one block inside the group. Note, block parsing is one
1615 * of the harder things, so this code is a bit complicated.
1616 * See http://www.matroska.org/ for documentation. */
1617 case GST_MATROSKA_ID_BLOCK: {
1621 guint size, *lace_size = NULL;
1622 gint n, stream, flags, laces = 0;
1625 if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
1629 data = GST_BUFFER_DATA (buf);
1630 size = GST_BUFFER_SIZE (buf);
1632 /* first byte(s): blocknum */
1633 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1634 gst_element_error (GST_ELEMENT (demux), "Data error");
1635 gst_buffer_unref (buf);
1639 data += n; size -= n;
1641 /* fetch stream from num */
1642 stream = gst_matroska_demux_stream_from_num (demux, num);
1643 if (size <= 3 || stream < 0 || stream >= demux->num_streams) {
1644 gst_buffer_unref (buf);
1645 GST_WARNING ("Invalid stream %d or size %u", stream, size);
1648 if (!GST_PAD_IS_USABLE (demux->src[stream]->pad)) {
1649 gst_buffer_unref (buf);
1653 /* time (relative to cluster time) */
1654 time = (* (gint16 *) data) * demux->time_scale;
1655 time = GINT16_FROM_BE (time);
1656 data += 2; size -= 2;
1657 flags = * (guint8 *) data;
1658 data += 1; size -= 1;
1659 switch ((flags & 0x06) >> 1) {
1660 case 0x0: /* no lacing */
1662 lace_size = g_new (gint, 1);
1663 lace_size[0] = size;
1666 case 0x1: /* xiph lacing */
1667 case 0x2: /* fixed-size lacing */
1668 case 0x3: /* EBML lacing */
1673 laces = (* (guint8 *) data) + 1;
1674 data += 1; size -= 1;
1675 lace_size = g_new0 (gint, laces);
1677 switch ((flags & 0x06) >> 1) {
1678 case 0x1: /* xiph lacing */ {
1679 guint temp, total = 0;
1680 for (n = 0; res && n < laces - 1; n++) {
1686 temp = * (guint8 *) data;
1687 lace_size[n] += temp;
1688 data += 1; size -= 1;
1692 total += lace_size[n];
1694 lace_size[n] = size - total;
1698 case 0x2: /* fixed-size lacing */
1699 for (n = 0; n < laces; n++)
1700 lace_size[n] = size / laces;
1703 case 0x3: /* EBML lacing */ {
1705 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1706 gst_element_error (GST_ELEMENT (demux), "Data error");
1710 data += n; size -= n;
1711 total = lace_size[0] = num;
1712 for (n = 1; res && n < laces - 1; n++) {
1715 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
1716 gst_element_error (GST_ELEMENT (demux), "Data error");
1720 data += r; size -= r;
1721 lace_size[n] = lace_size[0] + snum;
1722 total += lace_size[n];
1724 lace_size[n] = size - total;
1732 for (n = 0; n < laces; n++) {
1733 GstBuffer *sub = gst_buffer_create_sub (buf,
1734 GST_BUFFER_SIZE (buf) - size,
1737 if (cluster_time != GST_CLOCK_TIME_NONE)
1738 GST_BUFFER_TIMESTAMP (sub) = cluster_time + time;
1740 /* FIXME: duration */
1742 gst_pad_push (demux->src[stream]->pad, GST_DATA (sub));
1744 size -= lace_size[n];
1749 gst_buffer_unref (buf);
1753 case GST_MATROSKA_ID_BLOCKDURATION: {
1755 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1759 GST_WARNING ("FIXME: implement support for BlockDuration");
1764 GST_WARNING ("Unknown entry 0x%x in blockgroup data", id);
1767 case GST_EBML_ID_VOID:
1768 if (!gst_ebml_read_skip (ebml))
1773 if (demux->level_up) {
1783 gst_matroska_demux_parse_cluster (GstMatroskaDemux *demux)
1785 GstEbmlRead *ebml = GST_EBML_READ (demux);
1786 gboolean res = TRUE;
1788 guint64 cluster_time = GST_CLOCK_TIME_NONE;
1790 /* We seek after index/header parsing before doing a new
1791 * buffer. So here. */
1792 if (demux->seek_pending != GST_CLOCK_TIME_NONE) {
1793 if (!gst_matroska_demux_handle_seek_event (demux))
1795 demux->seek_pending = GST_CLOCK_TIME_NONE;
1799 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1802 } else if (demux->level_up) {
1808 /* cluster timecode */
1809 case GST_MATROSKA_ID_CLUSTERTIMECODE: {
1811 if (!gst_ebml_read_uint (ebml, &id, &num)) {
1815 cluster_time = num * demux->time_scale;
1819 /* a group of blocks inside a cluster */
1820 case GST_MATROSKA_ID_BLOCKGROUP:
1821 if (!gst_ebml_read_master (ebml, &id)) {
1825 res = gst_matroska_demux_parse_blockgroup (demux, cluster_time);
1829 GST_WARNING ("Unknown entry 0x%x in cluster data", id);
1832 case GST_EBML_ID_VOID:
1833 if (!gst_ebml_read_skip (ebml))
1838 if (demux->level_up) {
1848 gst_matroska_demux_parse_contents (GstMatroskaDemux *demux)
1850 GstEbmlRead *ebml = GST_EBML_READ (demux);
1851 gboolean res = TRUE;
1855 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1858 } else if (demux->level_up) {
1864 case GST_MATROSKA_ID_SEEKENTRY: {
1865 guint32 seek_id = 0;
1866 guint64 seek_pos = (guint64) -1, t;
1868 if (!gst_ebml_read_master (ebml, &id)) {
1874 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1877 } else if (demux->level_up) {
1883 case GST_MATROSKA_ID_SEEKID:
1884 if (!gst_ebml_read_uint (ebml, &id, &t))
1889 case GST_MATROSKA_ID_SEEKPOSITION:
1890 if (!gst_ebml_read_uint (ebml, &id, &seek_pos))
1895 GST_WARNING ("Unknown seekhead ID 0x%x", id);
1898 case GST_EBML_ID_VOID:
1899 if (!gst_ebml_read_skip (ebml))
1904 if (demux->level_up) {
1910 if (!seek_id || seek_pos == (guint64) -1) {
1911 GST_WARNING ("Incomplete seekhead entry (0x%x/%"
1912 G_GUINT64_FORMAT ")", seek_id, seek_pos);
1917 case GST_MATROSKA_ID_CUES:
1918 case GST_MATROSKA_ID_TAGS: {
1919 guint level_up = demux->level_up;
1920 guint64 before_pos, length;
1921 GstEbmlLevel *level;
1925 length = gst_bytestream_length (ebml->bs);
1926 before_pos = gst_bytestream_tell (ebml->bs);
1928 /* check for validity */
1929 if (seek_pos + demux->segment_start + 12 >= length) {
1930 g_warning ("Seekhead reference lies outside file!");
1935 if (!(event = gst_ebml_read_seek (ebml,
1936 seek_pos + demux->segment_start)))
1938 gst_event_unref (event);
1940 /* we don't want to lose our seekhead level, so we add
1941 * a dummy. This is a crude hack. */
1942 level = g_new (GstEbmlLevel, 1);
1944 level->length = G_MAXUINT64;
1945 ebml->level = g_list_append (ebml->level, level);
1948 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1952 if (id != seek_id) {
1953 g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%llu)",
1954 seek_id, id, seek_pos + demux->segment_start);
1958 /* read master + parse */
1960 case GST_MATROSKA_ID_CUES:
1961 if (!gst_ebml_read_master (ebml, &id))
1963 else if (!gst_matroska_demux_parse_index (demux, TRUE) &&
1964 gst_bytestream_length (ebml->bs) !=
1965 gst_bytestream_tell (ebml->bs))
1968 demux->index_parsed = TRUE;
1970 case GST_MATROSKA_ID_TAGS:
1971 if (!gst_ebml_read_master (ebml, &id))
1973 else if (!gst_matroska_demux_parse_metadata (demux, TRUE) &&
1974 gst_bytestream_length (ebml->bs) !=
1975 gst_bytestream_tell (ebml->bs))
1978 demux->metadata_parsed = TRUE;
1985 /* remove dummy level */
1986 while (ebml->level) {
1988 level = g_list_last (ebml->level)->data;
1989 ebml->level = g_list_remove (ebml->level, level);
1990 length = level->length;
1992 if (length == G_MAXUINT64)
1997 if (!(event = gst_ebml_read_seek (ebml, before_pos)))
1999 gst_event_unref (event);
2000 demux->level_up = level_up;
2005 GST_INFO ("Ignoring seekhead entry for ID=0x%x", seek_id);
2013 GST_WARNING ("Unknown seekhead ID 0x%x", id);
2016 case GST_EBML_ID_VOID:
2017 if (!gst_ebml_read_skip (ebml))
2022 if (demux->level_up) {
2032 gst_matroska_demux_loop_stream (GstMatroskaDemux *demux)
2034 GstEbmlRead *ebml = GST_EBML_READ (demux);
2035 gboolean res = TRUE;
2038 /* we've found our segment, start reading the different contents in here */
2040 if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2043 } else if (demux->level_up) {
2050 case GST_MATROSKA_ID_INFO: {
2051 if (!gst_ebml_read_master (ebml, &id)) {
2055 res = gst_matroska_demux_parse_info (demux);
2059 /* track info headers */
2060 case GST_MATROSKA_ID_TRACKS: {
2061 if (!gst_ebml_read_master (ebml, &id)) {
2065 res = gst_matroska_demux_parse_tracks (demux);
2070 case GST_MATROSKA_ID_CUES: {
2071 if (!demux->index_parsed) {
2072 if (!gst_ebml_read_master (ebml, &id)) {
2076 res = gst_matroska_demux_parse_index (demux, FALSE);
2078 res = gst_ebml_read_skip (ebml);
2083 case GST_MATROSKA_ID_TAGS: {
2084 if (!demux->index_parsed) {
2085 if (!gst_ebml_read_master (ebml, &id)) {
2089 res = gst_matroska_demux_parse_metadata (demux, FALSE);
2091 res = gst_ebml_read_skip (ebml);
2095 /* file index (if seekable, seek to Cues/Tags to parse it) */
2096 case GST_MATROSKA_ID_SEEKHEAD: {
2097 if (!gst_ebml_read_master (ebml, &id)) {
2101 res = gst_matroska_demux_parse_contents (demux);
2105 case GST_MATROSKA_ID_CLUSTER: {
2106 if (!gst_ebml_read_master (ebml, &id)) {
2110 /* The idea is that we parse one cluster per loop and
2111 * then break out of the loop here. In the next call
2112 * of the loopfunc, we will get back here with the
2113 * next cluster. If an error occurs, we didn't
2114 * actually push a buffer, but we still want to break
2115 * out of the loop to handle a possible error. We'll
2116 * get back here if it's recoverable. */
2117 gst_matroska_demux_parse_cluster (demux);
2118 demux->state = GST_MATROSKA_DEMUX_STATE_DATA;
2124 GST_WARNING ("Unknown matroska file header ID 0x%x", id);
2127 case GST_EBML_ID_VOID:
2128 if (!gst_ebml_read_skip (ebml))
2133 if (demux->level_up) {
2143 gst_matroska_demux_loop (GstElement *element)
2145 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2147 /* first, if we're to start, let's actually get starting */
2148 if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
2149 if (!gst_matroska_demux_init_stream (demux)) {
2152 demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
2155 gst_matroska_demux_loop_stream (demux);
2159 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *videocontext,
2160 const gchar *codec_id,
2164 GstMatroskaTrackContext *context =
2165 (GstMatroskaTrackContext *) videocontext;
2166 GstCaps *caps = NULL;
2168 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
2169 gst_riff_strf_vids *vids = NULL;
2173 vids = (gst_riff_strf_vids *) data;
2175 /* assure size is big enough */
2177 GST_WARNING ("Too small BITMAPINFOHEADER (%d bytes)", size);
2180 if (size < sizeof (gst_riff_strf_vids)) {
2181 vids = (gst_riff_strf_vids *) g_realloc (vids, sizeof (gst_riff_strf_vids));
2184 /* little-endian -> byte-order */
2185 vids->size = GUINT32_FROM_LE (vids->size);
2186 vids->width = GUINT32_FROM_LE (vids->width);
2187 vids->height = GUINT32_FROM_LE (vids->height);
2188 vids->planes = GUINT16_FROM_LE (vids->planes);
2189 vids->bit_cnt = GUINT16_FROM_LE (vids->bit_cnt);
2190 vids->compression = GUINT32_FROM_LE (vids->compression);
2191 vids->image_size = GUINT32_FROM_LE (vids->image_size);
2192 vids->xpels_meter = GUINT32_FROM_LE (vids->xpels_meter);
2193 vids->ypels_meter = GUINT32_FROM_LE (vids->ypels_meter);
2194 vids->num_colors = GUINT32_FROM_LE (vids->num_colors);
2195 vids->imp_colors = GUINT32_FROM_LE (vids->imp_colors);
2197 caps = gst_riff_create_video_caps (vids->compression, NULL, vids);
2199 caps = gst_riff_create_video_template_caps ();
2202 for (t = caps; t != NULL; t = t->next) {
2203 gst_props_remove_entry_by_name (t->properties, "width");
2204 gst_props_remove_entry_by_name (t->properties, "height");
2205 gst_props_remove_entry_by_name (t->properties, "framerate");
2207 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
2208 /* how nice, this is undocumented... */
2209 if (videocontext != NULL) {
2212 switch (videocontext->fourcc) {
2213 case GST_MAKE_FOURCC ('I','4','2','0'):
2214 case GST_MAKE_FOURCC ('Y','U','Y','2'):
2215 fourcc = videocontext->fourcc;
2219 GST_DEBUG ("Unknown fourcc " GST_FOURCC_FORMAT,
2220 GST_FOURCC_ARGS (videocontext->fourcc));
2224 caps = GST_CAPS_NEW ("matroskademux_src_uncompressed",
2226 "format", GST_PROPS_FOURCC (fourcc));
2228 caps = GST_CAPS_NEW ("matroskademux_src_uncompressed",
2230 "format", GST_PROPS_LIST (
2231 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
2232 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')),
2233 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','V','1','2'))
2237 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) {
2238 caps = GST_CAPS_NEW ("matroskademux_src_divx4",
2240 "divxversion", GST_PROPS_INT (4));
2241 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) ||
2242 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) {
2243 caps = GST_CAPS_NEW ("matroskademux_src_divx5",
2245 "divxversion", GST_PROPS_INT (5));
2246 caps = gst_caps_append (caps,
2247 GST_CAPS_NEW ("matroskademux_src_xvid",
2250 caps = gst_caps_append (caps,
2251 GST_CAPS_NEW ("matroskademux_src_mpeg4asp/ap",
2253 "mpegversion", GST_PROPS_INT (4),
2254 "systemstream", GST_PROPS_BOOLEAN (FALSE)));
2255 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) {
2256 caps = GST_CAPS_NEW ("matroskademux_src_msmpeg4v3",
2258 "divxversion", GST_PROPS_INT (3));
2259 caps = gst_caps_append (caps,
2260 GST_CAPS_NEW ("matroskademux_src_divx3",
2262 "msmpegversion", GST_PROPS_INT (43)));
2263 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1) ||
2264 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2)) {
2265 gint mpegversion = -1;
2267 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1))
2269 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2))
2274 caps = GST_CAPS_NEW ("matroska_demux_mpeg1",
2276 "systemstream", GST_PROPS_BOOLEAN (FALSE),
2277 "mpegversion", GST_PROPS_INT (mpegversion));
2278 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) {
2279 caps = GST_CAPS_NEW ("matroska_demux_mjpeg",
2283 GST_WARNING ("Unknown codec '%s', cannot build Caps",
2289 GstPropsEntry *fps = NULL;
2290 GstPropsEntry *width = NULL, *height = NULL;
2291 GstPropsEntry *pixel_width = NULL, *pixel_height = NULL;
2293 for (one = caps; one != NULL; one = one->next) {
2294 if (videocontext != NULL) {
2295 if (videocontext->pixel_width > 0 &&
2296 videocontext->pixel_height > 0) {
2297 gint w = videocontext->pixel_width;
2298 gint h = videocontext->pixel_height;
2300 width = gst_props_entry_new ("width",
2302 height = gst_props_entry_new ("height",
2306 if (videocontext->display_width > 0 &&
2307 videocontext->display_height > 0) {
2308 gint w = 100 * videocontext->display_width / videocontext->pixel_width;
2309 gint h = 100 * videocontext->display_height / videocontext->pixel_height;
2311 pixel_width = gst_props_entry_new ("pixel_width",
2313 pixel_height = gst_props_entry_new ("pixel_height",
2317 if (context->default_duration > 0) {
2318 gfloat framerate = 1. * GST_SECOND / context->default_duration;
2320 fps = gst_props_entry_new ("framerate",
2321 GST_PROPS_FLOAT (framerate));
2323 /* sort of a hack to get most codecs to support,
2324 * even if the default_duration is missing */
2325 fps = gst_props_entry_new ("framerate", GST_PROPS_FLOAT (25.));
2328 width = gst_props_entry_new ("width",
2329 GST_PROPS_INT_RANGE (16, 4096));
2330 height = gst_props_entry_new ("height",
2331 GST_PROPS_INT_RANGE (16, 4096));
2333 pixel_width = gst_props_entry_new ("pixel_width",
2334 GST_PROPS_INT_RANGE (0, 255));
2335 pixel_height = gst_props_entry_new ("pixel_height",
2336 GST_PROPS_INT_RANGE (0, 255));
2338 fps = gst_props_entry_new ("framerate",
2339 GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT));
2342 if (one->properties == NULL) {
2343 one->properties = gst_props_empty_new ();
2346 if (width != NULL && height != NULL) {
2347 gst_props_add_entry (one->properties, width);
2348 gst_props_add_entry (one->properties, height);
2351 if (pixel_width != NULL && pixel_height != NULL) {
2352 gst_props_add_entry (one->properties, pixel_width);
2353 gst_props_add_entry (one->properties, pixel_height);
2357 gst_props_add_entry (one->properties, fps);
2366 gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *audiocontext,
2367 const gchar *codec_id,
2371 GstMatroskaTrackContext *context =
2372 (GstMatroskaTrackContext *) audiocontext;
2373 GstCaps *caps = NULL;
2375 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
2376 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
2377 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
2380 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1))
2382 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2))
2384 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3))
2389 caps = GST_CAPS_NEW ("matroskademux_mpeg1-l1",
2391 "mpegversion", GST_PROPS_INT (1),
2392 "layer", GST_PROPS_INT (layer));
2393 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) ||
2394 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) {
2395 gint endianness = -1;
2396 GstPropsEntry *depth, *width, *sign;
2398 if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE))
2399 endianness = G_BIG_ENDIAN;
2400 else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE))
2401 endianness = G_LITTLE_ENDIAN;
2405 if (context != NULL) {
2406 width = gst_props_entry_new ("width",
2407 GST_PROPS_INT (audiocontext->bitdepth));
2408 depth = gst_props_entry_new ("depth",
2409 GST_PROPS_INT (audiocontext->bitdepth));
2410 sign = gst_props_entry_new ("signed",
2411 GST_PROPS_BOOLEAN (audiocontext->bitdepth == 8));
2413 width = gst_props_entry_new ("width", GST_PROPS_LIST (
2415 GST_PROPS_INT (16)));
2416 depth = gst_props_entry_new ("depth", GST_PROPS_LIST (
2418 GST_PROPS_INT (16)));
2419 sign = gst_props_entry_new ("signed", GST_PROPS_LIST (
2420 GST_PROPS_BOOLEAN (TRUE),
2421 GST_PROPS_BOOLEAN (FALSE)));
2424 caps = GST_CAPS_NEW ("matroskademux_audio_raw",
2426 "endianness", GST_PROPS_INT (endianness));
2427 gst_props_add_entry (caps->properties, width);
2428 gst_props_add_entry (caps->properties, depth);
2429 gst_props_add_entry (caps->properties, sign);
2430 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
2431 GstPropsEntry *width;
2433 if (audiocontext != NULL) {
2434 width = gst_props_entry_new ("width",
2435 GST_PROPS_INT (audiocontext->bitdepth));
2437 width = gst_props_entry_new ("width", GST_PROPS_LIST (
2439 GST_PROPS_INT (64)));
2442 caps = GST_CAPS_NEW ("matroskademux_audio_float",
2443 "audio/x-raw-float",
2444 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
2445 "buffer-frames", GST_PROPS_INT_RANGE (1, G_MAXINT));
2447 gst_props_add_entry (caps->properties, width);
2448 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AC3) ||
2449 !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) {
2450 caps = GST_CAPS_NEW ("matroskademux_audio_ac3/dts",
2453 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
2454 caps = GST_CAPS_NEW ("matroskademux_audio_vorbis",
2457 } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
2458 gst_riff_strf_auds *auds = NULL;
2462 auds = (gst_riff_strf_auds *) data;
2464 /* little-endian -> byte-order */
2465 auds->format = GUINT16_FROM_LE (auds->format);
2466 auds->channels = GUINT16_FROM_LE (auds->channels);
2467 auds->rate = GUINT32_FROM_LE (auds->rate);
2468 auds->av_bps = GUINT32_FROM_LE (auds->av_bps);
2469 auds->blockalign = GUINT16_FROM_LE (auds->blockalign);
2470 auds->size = GUINT16_FROM_LE (auds->size);
2472 caps = gst_riff_create_audio_caps (auds->format, NULL, auds);
2474 caps = gst_riff_create_audio_template_caps ();
2477 for (t = caps; t != NULL; t = t->next) {
2478 gst_props_remove_entry_by_name (t->properties, "rate");
2479 gst_props_remove_entry_by_name (t->properties, "channels");
2481 } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2482 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)) ||
2483 !strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2484 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4))) {
2485 gint mpegversion = -1;
2487 if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2488 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)))
2490 else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2491 strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4)))
2496 caps = GST_CAPS_NEW ("matroska_demux_aac_mpeg2",
2498 "mpegversion", GST_PROPS_INT (mpegversion));
2500 GST_WARNING ("Unknown codec '%s', cannot build Caps",
2506 GstPropsEntry *chans = NULL, *rate = NULL;
2508 for (one = caps; one != NULL; one = one->next) {
2509 if (audiocontext != NULL) {
2510 if (audiocontext->samplerate > 0 &&
2511 audiocontext->channels > 0) {
2512 chans = gst_props_entry_new ("channels",
2513 GST_PROPS_INT (audiocontext->channels));
2514 rate = gst_props_entry_new ("rate",
2515 GST_PROPS_INT (audiocontext->samplerate));
2518 chans = gst_props_entry_new ("channels",
2519 GST_PROPS_INT_RANGE (1, 6));
2520 rate = gst_props_entry_new ("rate",
2521 GST_PROPS_INT_RANGE (4000, 96000));
2524 if (caps->properties == NULL) {
2525 caps->properties = gst_props_empty_new ();
2528 if (chans != NULL && rate != NULL) {
2529 gst_props_add_entry (caps->properties, chans);
2530 gst_props_add_entry (caps->properties, rate);
2539 gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext *complexcontext,
2540 const gchar *codec_id,
2544 GstCaps *caps = NULL;
2552 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *subtitlecontext,
2553 const gchar *codec_id,
2557 GstCaps *caps = NULL;
2564 static GstElementStateReturn
2565 gst_matroska_demux_change_state (GstElement *element)
2567 GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2569 switch (GST_STATE_TRANSITION (element)) {
2570 case GST_STATE_PAUSED_TO_READY:
2571 gst_matroska_demux_reset (GST_ELEMENT (demux));
2577 if (((GstElementClass *) parent_class)->change_state)
2578 return ((GstElementClass *) parent_class)->change_state (element);
2580 return GST_STATE_SUCCESS;
2584 gst_matroska_demux_get_property (GObject *object,
2589 GstMatroskaDemux *demux;
2591 g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
2592 demux = GST_MATROSKA_DEMUX (object);
2595 case ARG_STREAMINFO:
2596 g_value_set_boxed (value, demux->streaminfo);
2599 g_value_set_boxed (value, demux->metadata);
2602 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2608 gst_matroska_demux_plugin_init (GstPlugin *plugin)
2611 GstCaps *videosrccaps = NULL, *audiosrccaps = NULL,
2612 *subtitlesrccaps = NULL, *temp;
2613 const gchar *video_id[] = {
2614 GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC,
2615 GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED,
2616 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP,
2617 GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP,
2618 GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3,
2619 GST_MATROSKA_CODEC_ID_VIDEO_MPEG1,
2620 GST_MATROSKA_CODEC_ID_VIDEO_MPEG2,
2621 GST_MATROSKA_CODEC_ID_VIDEO_MJPEG,
2622 /* TODO: Real/Quicktime */
2626 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1,
2627 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2,
2628 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3,
2629 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE,
2630 GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE,
2631 GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT,
2632 GST_MATROSKA_CODEC_ID_AUDIO_AC3,
2633 GST_MATROSKA_CODEC_ID_AUDIO_ACM,
2634 GST_MATROSKA_CODEC_ID_AUDIO_VORBIS,
2635 GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2636 GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2637 /* TODO: AC3-9/10, Real, Musepack, Quicktime */
2640 }, *complex_id[] = {
2643 }, *subtitle_id[] = {
2648 /* this filter needs the riff parser */
2649 if (!gst_library_load ("gstbytestream") ||
2650 !gst_library_load ("riff")) /* for fourcc stuff */
2653 /* video src template */
2654 for (i = 0; video_id[i] != NULL; i++) {
2655 temp = gst_matroska_demux_video_caps (NULL, video_id[i], NULL, 0);
2656 videosrccaps = gst_caps_append (videosrccaps, temp);
2658 for (i = 0; complex_id[i] != NULL; i++) {
2659 temp = gst_matroska_demux_complex_caps (NULL, video_id[i], NULL, 0);
2660 videosrccaps = gst_caps_append (videosrccaps, temp);
2662 videosrctempl = gst_pad_template_new ("video_%02d",
2665 videosrccaps, NULL);
2667 /* audio src template */
2668 for (i = 0; audio_id[i] != NULL; i++) {
2669 temp = gst_matroska_demux_audio_caps (NULL, audio_id[i], NULL, 0);
2670 audiosrccaps = gst_caps_append (audiosrccaps, temp);
2672 audiosrctempl = gst_pad_template_new ("audio_%02d",
2675 audiosrccaps, NULL);
2677 /* subtitle src template */
2678 for (i = 0; subtitle_id[i] != NULL; i++) {
2679 temp = gst_matroska_demux_subtitle_caps (NULL, subtitle_id[i], NULL, 0);
2680 subtitlesrccaps = gst_caps_append (subtitlesrccaps, temp);
2682 subtitlesrctempl = gst_pad_template_new ("subtitle_%02d",
2685 subtitlesrccaps, NULL);
2687 /* create an elementfactory for the matroska_demux element */
2688 if (!gst_element_register (plugin, "matroskademux",
2689 GST_RANK_PRIMARY, GST_TYPE_MATROSKA_DEMUX))