1 /* GStreamer Matroska muxer/demuxer
2 * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 * (c) 2006 Tim-Philipp Müller <tim centricular net>
4 * (c) 2008 Sebastian Dröge <slomo@circular-chaos.org>
5 * (c) 2011 Debarshi Ray <rishi@gnu.org>
6 *
7 * matroska-parse.c: matroska file/stream parser
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25 /* TODO: check CRC32 if present
26 * TODO: there can be a segment after the first segment. Handle like
27 * chained oggs. Fixes #334082
28 * TODO: Test samples: http://www.matroska.org/samples/matrix/index.html
29 * http://samples.mplayerhq.hu/Matroska/
30 * TODO: check if parseing is done correct for all codecs according to spec
31 * TODO: seeking with incomplete or without CUE
32 */
33
34 /**
35 * SECTION:element-matroskaparse
36 *
37 * matroskaparse parsees a Matroska file into the different contained streams.
38 *
39 * <refsect2>
40 * <title>Example launch line</title>
41 * |[
42 * gst-launch-1.0 -v filesrc location=/path/to/mkv ! matroskaparse ! vorbisdec ! audioconvert ! audioresample ! autoaudiosink
43 * ]| This pipeline parsees a Matroska file and outputs the contained Vorbis audio.
44 * </refsect2>
45 */
46
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include <math.h>
53 #include <string.h>
54 #include <glib/gprintf.h>
55
56 /* For AVI compatibility mode
57 and for fourcc stuff */
58 #include <gst/riff/riff-read.h>
59 #include <gst/riff/riff-ids.h>
60 #include <gst/riff/riff-media.h>
61
62 #include <gst/tag/tag.h>
63
64 #include <gst/pbutils/pbutils.h>
65
66 #include "matroska-parse.h"
67 #include "matroska-ids.h"
68
69 GST_DEBUG_CATEGORY_STATIC (matroskaparse_debug);
70 #define GST_CAT_DEFAULT matroskaparse_debug
71
72 #define DEBUG_ELEMENT_START(parse, ebml, element) \
73 GST_DEBUG_OBJECT (parse, "Parsing " element " element at offset %" \
74 G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
75
76 #define DEBUG_ELEMENT_STOP(parse, ebml, element, ret) \
77 GST_DEBUG_OBJECT (parse, "Parsing " element " element " \
78 " finished with '%s'", gst_flow_get_name (ret))
79
80 #define INVALID_DATA_THRESHOLD (2 * 1024 * 1024)
81
82 enum
83 {
84 PROP_0
85 };
86
87 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
88 GST_PAD_SINK,
89 GST_PAD_ALWAYS,
90 GST_STATIC_CAPS ("audio/x-matroska; video/x-matroska; "
91 "video/x-matroska-3d; audio/webm; video/webm")
92 );
93
94 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
95 GST_PAD_SRC,
96 GST_PAD_ALWAYS,
97 GST_STATIC_CAPS ("audio/x-matroska; video/x-matroska; "
98 "video/x-matroska-3d; audio/webm; video/webm")
99 );
100
101 static GstFlowReturn gst_matroska_parse_parse_id (GstMatroskaParse * parse,
102 guint32 id, guint64 length, guint needed);
103
104 /* element functions */
105 //static void gst_matroska_parse_loop (GstPad * pad);
106
107 static gboolean gst_matroska_parse_element_send_event (GstElement * element,
108 GstEvent * event);
109 static gboolean gst_matroska_parse_element_query (GstElement * element,
110 GstQuery * query);
111
112 /* pad functions */
113 static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
114 GstPad * pad, GstEvent * event);
115 static gboolean gst_matroska_parse_handle_src_event (GstPad * pad,
116 GstObject * parent, GstEvent * event);
117 static gboolean gst_matroska_parse_handle_src_query (GstPad * pad,
118 GstObject * parent, GstQuery * query);
119
120 static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad,
121 GstObject * parent, GstEvent * event);
122 static GstFlowReturn gst_matroska_parse_chain (GstPad * pad,
123 GstObject * parent, GstBuffer * buffer);
124
125 static GstStateChangeReturn
126 gst_matroska_parse_change_state (GstElement * element,
127 GstStateChange transition);
128 #if 0
129 static void
130 gst_matroska_parse_set_index (GstElement * element, GstIndex * index);
131 static GstIndex *gst_matroska_parse_get_index (GstElement * element);
132 #endif
133
134 /* stream methods */
135 static void gst_matroska_parse_reset (GstElement * element);
136 static gboolean perform_seek_to_offset (GstMatroskaParse * parse,
137 guint64 offset);
138 static GstCaps *gst_matroska_parse_forge_caps (gboolean is_webm,
139 gboolean has_video);
140
141 GType gst_matroska_parse_get_type (void);
142 #define parent_class gst_matroska_parse_parent_class
143 G_DEFINE_TYPE (GstMatroskaParse, gst_matroska_parse, GST_TYPE_ELEMENT);
144
145 static void
gst_matroska_parse_finalize(GObject * object)146 gst_matroska_parse_finalize (GObject * object)
147 {
148 GstMatroskaParse *parse = GST_MATROSKA_PARSE (object);
149
150 gst_matroska_read_common_finalize (&parse->common);
151 G_OBJECT_CLASS (parent_class)->finalize (object);
152 }
153
154 static void
gst_matroska_parse_class_init(GstMatroskaParseClass * klass)155 gst_matroska_parse_class_init (GstMatroskaParseClass * klass)
156 {
157 GObjectClass *gobject_class = (GObjectClass *) klass;
158 GstElementClass *gstelement_class = (GstElementClass *) klass;
159
160 GST_DEBUG_CATEGORY_INIT (matroskaparse_debug, "matroskaparse", 0,
161 "Matroska parser");
162
163 gobject_class->finalize = gst_matroska_parse_finalize;
164
165 gstelement_class->change_state =
166 GST_DEBUG_FUNCPTR (gst_matroska_parse_change_state);
167 gstelement_class->send_event =
168 GST_DEBUG_FUNCPTR (gst_matroska_parse_element_send_event);
169 gstelement_class->query =
170 GST_DEBUG_FUNCPTR (gst_matroska_parse_element_query);
171
172 #if 0
173 gstelement_class->set_index =
174 GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index);
175 gstelement_class->get_index =
176 GST_DEBUG_FUNCPTR (gst_matroska_parse_get_index);
177 #endif
178
179 gst_element_class_add_static_pad_template (gstelement_class, &src_templ);
180 gst_element_class_add_static_pad_template (gstelement_class, &sink_templ);
181
182 gst_element_class_set_static_metadata (gstelement_class,
183 "Matroska parser", "Codec/Parser",
184 "Parses Matroska/WebM streams into video/audio/subtitles",
185 "GStreamer maintainers <gstreamer-devel@lists.freedesktop.org>");
186 }
187
188 static void
gst_matroska_parse_init(GstMatroskaParse * parse)189 gst_matroska_parse_init (GstMatroskaParse * parse)
190 {
191 parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
192 "sink");
193 gst_pad_set_chain_function (parse->common.sinkpad,
194 GST_DEBUG_FUNCPTR (gst_matroska_parse_chain));
195 gst_pad_set_event_function (parse->common.sinkpad,
196 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_sink_event));
197 gst_element_add_pad (GST_ELEMENT (parse), parse->common.sinkpad);
198
199 parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
200 gst_pad_set_event_function (parse->srcpad,
201 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event));
202 gst_pad_set_query_function (parse->srcpad,
203 GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
204 gst_pad_use_fixed_caps (parse->srcpad);
205
206 gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
207
208 /* init defaults for common read context */
209 gst_matroska_read_common_init (&parse->common);
210
211 GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
212
213 /* finish off */
214 gst_matroska_parse_reset (GST_ELEMENT (parse));
215 }
216
217 static void
gst_matroska_parse_reset(GstElement * element)218 gst_matroska_parse_reset (GstElement * element)
219 {
220 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
221
222 GST_DEBUG_OBJECT (parse, "Resetting state");
223
224 gst_matroska_read_common_reset (GST_ELEMENT (parse), &parse->common);
225
226 parse->num_a_streams = 0;
227 parse->num_t_streams = 0;
228 parse->num_v_streams = 0;
229
230 parse->clock = NULL;
231 parse->tracks_parsed = FALSE;
232
233 g_list_foreach (parse->seek_parsed,
234 (GFunc) gst_matroska_read_common_free_parsed_el, NULL);
235 g_list_free (parse->seek_parsed);
236 parse->seek_parsed = NULL;
237
238 parse->last_stop_end = GST_CLOCK_TIME_NONE;
239 parse->seek_block = 0;
240 parse->cluster_time = GST_CLOCK_TIME_NONE;
241 parse->cluster_offset = 0;
242 parse->next_cluster_offset = 0;
243 parse->index_offset = 0;
244 parse->seekable = FALSE;
245 parse->need_newsegment = TRUE;
246 parse->building_index = FALSE;
247 if (parse->seek_event) {
248 gst_event_unref (parse->seek_event);
249 parse->seek_event = NULL;
250 }
251
252 parse->seek_index = NULL;
253 parse->seek_entry = 0;
254
255 if (parse->close_segment) {
256 gst_event_unref (parse->close_segment);
257 parse->close_segment = NULL;
258 }
259
260 if (parse->new_segment) {
261 gst_event_unref (parse->new_segment);
262 parse->new_segment = NULL;
263 }
264
265 if (parse->streamheader != NULL) {
266 gst_buffer_unref (parse->streamheader);
267 parse->streamheader = NULL;
268 }
269 }
270
271 static GstFlowReturn
gst_matroska_parse_add_stream(GstMatroskaParse * parse,GstEbmlRead * ebml)272 gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml)
273 {
274 GstMatroskaTrackContext *context;
275 GstFlowReturn ret;
276 guint32 id;
277
278 DEBUG_ELEMENT_START (parse, ebml, "TrackEntry");
279
280 /* start with the master */
281 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
282 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
283 return ret;
284 }
285
286 /* allocate generic... if we know the type, we'll g_renew()
287 * with the precise type */
288 context = g_new0 (GstMatroskaTrackContext, 1);
289 g_ptr_array_add (parse->common.src, context);
290 context->index = parse->common.num_streams;
291 context->index_writer_id = -1;
292 context->type = 0; /* no type yet */
293 context->default_duration = 0;
294 context->pos = 0;
295 context->set_discont = TRUE;
296 context->timecodescale = 1.0;
297 context->flags =
298 GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
299 GST_MATROSKA_TRACK_LACING;
300 context->to_offset = G_MAXINT64;
301 context->alignment = 1;
302 parse->common.num_streams++;
303 g_assert (parse->common.src->len == parse->common.num_streams);
304
305 GST_DEBUG_OBJECT (parse, "Stream number %d", context->index);
306
307 /* try reading the trackentry headers */
308 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
309 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
310 break;
311
312 switch (id) {
313 /* track number (unique stream ID) */
314 case GST_MATROSKA_ID_TRACKNUMBER:{
315 guint64 num;
316
317 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
318 break;
319
320 if (num == 0) {
321 GST_ERROR_OBJECT (parse, "Invalid TrackNumber 0");
322 ret = GST_FLOW_ERROR;
323 break;
324 } else if (!gst_matroska_read_common_tracknumber_unique (&parse->common,
325 num)) {
326 GST_ERROR_OBJECT (parse, "TrackNumber %" G_GUINT64_FORMAT
327 " is not unique", num);
328 ret = GST_FLOW_ERROR;
329 break;
330 }
331
332 GST_DEBUG_OBJECT (parse, "TrackNumber: %" G_GUINT64_FORMAT, num);
333 context->num = num;
334 break;
335 }
336 /* track UID (unique identifier) */
337 case GST_MATROSKA_ID_TRACKUID:{
338 guint64 num;
339
340 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
341 break;
342
343 if (num == 0) {
344 GST_ERROR_OBJECT (parse, "Invalid TrackUID 0");
345 ret = GST_FLOW_ERROR;
346 break;
347 }
348
349 GST_DEBUG_OBJECT (parse, "TrackUID: %" G_GUINT64_FORMAT, num);
350 context->uid = num;
351 break;
352 }
353
354 /* track type (video, audio, combined, subtitle, etc.) */
355 case GST_MATROSKA_ID_TRACKTYPE:{
356 guint64 track_type;
357
358 if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
359 break;
360 }
361
362 if (context->type != 0 && context->type != track_type) {
363 GST_WARNING_OBJECT (parse,
364 "More than one tracktype defined in a TrackEntry - skipping");
365 break;
366 } else if (track_type < 1 || track_type > 254) {
367 GST_WARNING_OBJECT (parse, "Invalid TrackType %" G_GUINT64_FORMAT,
368 track_type);
369 break;
370 }
371
372 GST_DEBUG_OBJECT (parse, "TrackType: %" G_GUINT64_FORMAT, track_type);
373
374 /* ok, so we're actually going to reallocate this thing */
375 switch (track_type) {
376 case GST_MATROSKA_TRACK_TYPE_VIDEO:
377 gst_matroska_track_init_video_context (&context);
378 parse->common.has_video = TRUE;
379 break;
380 case GST_MATROSKA_TRACK_TYPE_AUDIO:
381 gst_matroska_track_init_audio_context (&context);
382 break;
383 case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
384 gst_matroska_track_init_subtitle_context (&context);
385 break;
386 case GST_MATROSKA_TRACK_TYPE_COMPLEX:
387 case GST_MATROSKA_TRACK_TYPE_LOGO:
388 case GST_MATROSKA_TRACK_TYPE_BUTTONS:
389 case GST_MATROSKA_TRACK_TYPE_CONTROL:
390 default:
391 GST_WARNING_OBJECT (parse,
392 "Unknown or unsupported TrackType %" G_GUINT64_FORMAT,
393 track_type);
394 context->type = 0;
395 break;
396 }
397 g_ptr_array_index (parse->common.src, parse->common.num_streams - 1)
398 = context;
399 break;
400 }
401
402 /* tracktype specific stuff for video */
403 case GST_MATROSKA_ID_TRACKVIDEO:{
404 GstMatroskaTrackVideoContext *videocontext;
405
406 DEBUG_ELEMENT_START (parse, ebml, "TrackVideo");
407
408 if (!gst_matroska_track_init_video_context (&context)) {
409 GST_WARNING_OBJECT (parse,
410 "TrackVideo element in non-video track - ignoring track");
411 ret = GST_FLOW_ERROR;
412 break;
413 } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
414 break;
415 }
416 videocontext = (GstMatroskaTrackVideoContext *) context;
417 g_ptr_array_index (parse->common.src, parse->common.num_streams - 1)
418 = context;
419
420 while (ret == GST_FLOW_OK &&
421 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
422 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
423 break;
424
425 switch (id) {
426 /* Should be one level up but some broken muxers write it here. */
427 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
428 guint64 num;
429
430 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
431 break;
432
433 if (num == 0) {
434 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
435 break;
436 }
437
438 GST_DEBUG_OBJECT (parse,
439 "TrackDefaultDuration: %" G_GUINT64_FORMAT, num);
440 context->default_duration = num;
441 break;
442 }
443
444 /* video framerate */
445 /* NOTE: This one is here only for backward compatibility.
446 * Use _TRACKDEFAULDURATION one level up. */
447 case GST_MATROSKA_ID_VIDEOFRAMERATE:{
448 gdouble num;
449
450 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
451 break;
452
453 if (num <= 0.0) {
454 GST_WARNING_OBJECT (parse, "Invalid TrackVideoFPS %lf", num);
455 break;
456 }
457
458 GST_DEBUG_OBJECT (parse, "TrackVideoFrameRate: %lf", num);
459 if (context->default_duration == 0)
460 context->default_duration =
461 gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
462 videocontext->default_fps = num;
463 break;
464 }
465
466 /* width of the size to display the video at */
467 case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
468 guint64 num;
469
470 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
471 break;
472
473 if (num == 0) {
474 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayWidth 0");
475 break;
476 }
477
478 GST_DEBUG_OBJECT (parse,
479 "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num);
480 videocontext->display_width = num;
481 break;
482 }
483
484 /* height of the size to display the video at */
485 case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
486 guint64 num;
487
488 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
489 break;
490
491 if (num == 0) {
492 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayHeight 0");
493 break;
494 }
495
496 GST_DEBUG_OBJECT (parse,
497 "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num);
498 videocontext->display_height = num;
499 break;
500 }
501
502 /* width of the video in the file */
503 case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
504 guint64 num;
505
506 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
507 break;
508
509 if (num == 0) {
510 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelWidth 0");
511 break;
512 }
513
514 GST_DEBUG_OBJECT (parse,
515 "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num);
516 videocontext->pixel_width = num;
517 break;
518 }
519
520 /* height of the video in the file */
521 case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
522 guint64 num;
523
524 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
525 break;
526
527 if (num == 0) {
528 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelHeight 0");
529 break;
530 }
531
532 GST_DEBUG_OBJECT (parse,
533 "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num);
534 videocontext->pixel_height = num;
535 break;
536 }
537
538 /* whether the video is interlaced */
539 case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
540 guint64 num;
541
542 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
543 break;
544
545 if (num == 1)
546 videocontext->interlace_mode =
547 GST_MATROSKA_INTERLACE_MODE_INTERLACED;
548 else if (num == 2)
549 videocontext->interlace_mode =
550 GST_MATROSKA_INTERLACE_MODE_PROGRESSIVE;
551 else
552 videocontext->interlace_mode =
553 GST_MATROSKA_INTERLACE_MODE_UNKNOWN;
554
555 GST_DEBUG_OBJECT (parse, "video track interlacing mode: %d",
556 videocontext->interlace_mode);
557 break;
558 }
559
560 /* aspect ratio behaviour */
561 case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
562 guint64 num;
563
564 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
565 break;
566
567 if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
568 num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
569 num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
570 GST_WARNING_OBJECT (parse,
571 "Unknown TrackVideoAspectRatioType 0x%x", (guint) num);
572 break;
573 }
574 GST_DEBUG_OBJECT (parse,
575 "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num);
576 videocontext->asr_mode = num;
577 break;
578 }
579
580 /* colourspace (only matters for raw video) fourcc */
581 case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
582 guint8 *data;
583 guint64 datalen;
584
585 if ((ret =
586 gst_ebml_read_binary (ebml, &id, &data,
587 &datalen)) != GST_FLOW_OK)
588 break;
589
590 if (datalen != 4) {
591 g_free (data);
592 GST_WARNING_OBJECT (parse,
593 "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT,
594 datalen);
595 break;
596 }
597
598 memcpy (&videocontext->fourcc, data, 4);
599 GST_DEBUG_OBJECT (parse,
600 "TrackVideoColourSpace: %" GST_FOURCC_FORMAT,
601 GST_FOURCC_ARGS (videocontext->fourcc));
602 g_free (data);
603 break;
604 }
605
606 default:
607 GST_WARNING_OBJECT (parse,
608 "Unknown TrackVideo subelement 0x%x - ignoring", id);
609 /* fall through */
610 case GST_MATROSKA_ID_VIDEOSTEREOMODE:
611 case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
612 case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
613 case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
614 case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
615 case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
616 case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
617 ret = gst_ebml_read_skip (ebml);
618 break;
619 }
620 }
621
622 DEBUG_ELEMENT_STOP (parse, ebml, "TrackVideo", ret);
623 break;
624 }
625
626 /* tracktype specific stuff for audio */
627 case GST_MATROSKA_ID_TRACKAUDIO:{
628 GstMatroskaTrackAudioContext *audiocontext;
629
630 DEBUG_ELEMENT_START (parse, ebml, "TrackAudio");
631
632 if (!gst_matroska_track_init_audio_context (&context)) {
633 GST_WARNING_OBJECT (parse,
634 "TrackAudio element in non-audio track - ignoring track");
635 ret = GST_FLOW_ERROR;
636 break;
637 }
638
639 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
640 break;
641
642 audiocontext = (GstMatroskaTrackAudioContext *) context;
643 g_ptr_array_index (parse->common.src, parse->common.num_streams - 1)
644 = context;
645
646 while (ret == GST_FLOW_OK &&
647 gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
648 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
649 break;
650
651 switch (id) {
652 /* samplerate */
653 case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
654 gdouble num;
655
656 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
657 break;
658
659
660 if (num <= 0.0) {
661 GST_WARNING_OBJECT (parse,
662 "Invalid TrackAudioSamplingFrequency %lf", num);
663 break;
664 }
665
666 GST_DEBUG_OBJECT (parse, "TrackAudioSamplingFrequency: %lf", num);
667 audiocontext->samplerate = num;
668 break;
669 }
670
671 /* bitdepth */
672 case GST_MATROSKA_ID_AUDIOBITDEPTH:{
673 guint64 num;
674
675 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
676 break;
677
678 if (num == 0) {
679 GST_WARNING_OBJECT (parse, "Invalid TrackAudioBitDepth 0");
680 break;
681 }
682
683 GST_DEBUG_OBJECT (parse, "TrackAudioBitDepth: %" G_GUINT64_FORMAT,
684 num);
685 audiocontext->bitdepth = num;
686 break;
687 }
688
689 /* channels */
690 case GST_MATROSKA_ID_AUDIOCHANNELS:{
691 guint64 num;
692
693 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
694 break;
695
696 if (num == 0) {
697 GST_WARNING_OBJECT (parse, "Invalid TrackAudioChannels 0");
698 break;
699 }
700
701 GST_DEBUG_OBJECT (parse, "TrackAudioChannels: %" G_GUINT64_FORMAT,
702 num);
703 audiocontext->channels = num;
704 break;
705 }
706
707 default:
708 GST_WARNING_OBJECT (parse,
709 "Unknown TrackAudio subelement 0x%x - ignoring", id);
710 /* fall through */
711 case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
712 case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
713 ret = gst_ebml_read_skip (ebml);
714 break;
715 }
716 }
717
718 DEBUG_ELEMENT_STOP (parse, ebml, "TrackAudio", ret);
719
720 break;
721 }
722
723 /* codec identifier */
724 case GST_MATROSKA_ID_CODECID:{
725 gchar *text;
726
727 if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK)
728 break;
729
730 GST_DEBUG_OBJECT (parse, "CodecID: %s", GST_STR_NULL (text));
731 context->codec_id = text;
732 break;
733 }
734
735 /* codec private data */
736 case GST_MATROSKA_ID_CODECPRIVATE:{
737 guint8 *data;
738 guint64 size;
739
740 if ((ret =
741 gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK)
742 break;
743
744 context->codec_priv = data;
745 context->codec_priv_size = size;
746
747 GST_DEBUG_OBJECT (parse, "CodecPrivate of size %" G_GUINT64_FORMAT,
748 size);
749 break;
750 }
751
752 /* name of the codec */
753 case GST_MATROSKA_ID_CODECNAME:{
754 gchar *text;
755
756 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
757 break;
758
759 GST_DEBUG_OBJECT (parse, "CodecName: %s", GST_STR_NULL (text));
760 context->codec_name = text;
761 break;
762 }
763
764 /* name of this track */
765 case GST_MATROSKA_ID_TRACKNAME:{
766 gchar *text;
767
768 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
769 break;
770
771 context->name = text;
772 GST_DEBUG_OBJECT (parse, "TrackName: %s", GST_STR_NULL (text));
773 break;
774 }
775
776 /* language (matters for audio/subtitles, mostly) */
777 case GST_MATROSKA_ID_TRACKLANGUAGE:{
778 gchar *text;
779
780 if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
781 break;
782
783
784 context->language = text;
785
786 /* fre-ca => fre */
787 if (strlen (context->language) >= 4 && context->language[3] == '-')
788 context->language[3] = '\0';
789
790 GST_DEBUG_OBJECT (parse, "TrackLanguage: %s",
791 GST_STR_NULL (context->language));
792 break;
793 }
794
795 /* whether this is actually used */
796 case GST_MATROSKA_ID_TRACKFLAGENABLED:{
797 guint64 num;
798
799 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
800 break;
801
802 if (num)
803 context->flags |= GST_MATROSKA_TRACK_ENABLED;
804 else
805 context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
806
807 GST_DEBUG_OBJECT (parse, "TrackEnabled: %d",
808 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
809 break;
810 }
811
812 /* whether it's the default for this track type */
813 case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
814 guint64 num;
815
816 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
817 break;
818
819 if (num)
820 context->flags |= GST_MATROSKA_TRACK_DEFAULT;
821 else
822 context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
823
824 GST_DEBUG_OBJECT (parse, "TrackDefault: %d",
825 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
826 break;
827 }
828
829 /* whether the track must be used during playback */
830 case GST_MATROSKA_ID_TRACKFLAGFORCED:{
831 guint64 num;
832
833 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
834 break;
835
836 if (num)
837 context->flags |= GST_MATROSKA_TRACK_FORCED;
838 else
839 context->flags &= ~GST_MATROSKA_TRACK_FORCED;
840
841 GST_DEBUG_OBJECT (parse, "TrackForced: %d",
842 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
843 break;
844 }
845
846 /* lacing (like MPEG, where blocks don't end/start on frame
847 * boundaries) */
848 case GST_MATROSKA_ID_TRACKFLAGLACING:{
849 guint64 num;
850
851 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
852 break;
853
854 if (num)
855 context->flags |= GST_MATROSKA_TRACK_LACING;
856 else
857 context->flags &= ~GST_MATROSKA_TRACK_LACING;
858
859 GST_DEBUG_OBJECT (parse, "TrackLacing: %d",
860 (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
861 break;
862 }
863
864 /* default length (in time) of one data block in this track */
865 case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
866 guint64 num;
867
868 if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
869 break;
870
871
872 if (num == 0) {
873 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
874 break;
875 }
876
877 GST_DEBUG_OBJECT (parse, "TrackDefaultDuration: %" G_GUINT64_FORMAT,
878 num);
879 context->default_duration = num;
880 break;
881 }
882
883 case GST_MATROSKA_ID_CONTENTENCODINGS:{
884 ret = gst_matroska_read_common_read_track_encodings (&parse->common,
885 ebml, context);
886 break;
887 }
888
889 case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
890 gdouble num;
891
892 if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
893 break;
894
895 if (num <= 0.0) {
896 GST_WARNING_OBJECT (parse, "Invalid TrackTimeCodeScale %lf", num);
897 break;
898 }
899
900 GST_DEBUG_OBJECT (parse, "TrackTimeCodeScale: %lf", num);
901 context->timecodescale = num;
902 break;
903 }
904
905 default:
906 GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id);
907 /* pass-through */
908
909 /* we ignore these because they're nothing useful (i.e. crap)
910 * or simply not implemented yet. */
911 case GST_MATROSKA_ID_TRACKMINCACHE:
912 case GST_MATROSKA_ID_TRACKMAXCACHE:
913 case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
914 case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
915 case GST_MATROSKA_ID_TRACKOVERLAY:
916 case GST_MATROSKA_ID_TRACKTRANSLATE:
917 case GST_MATROSKA_ID_TRACKOFFSET:
918 case GST_MATROSKA_ID_CODECSETTINGS:
919 case GST_MATROSKA_ID_CODECINFOURL:
920 case GST_MATROSKA_ID_CODECDOWNLOADURL:
921 case GST_MATROSKA_ID_CODECDECODEALL:
922 ret = gst_ebml_read_skip (ebml);
923 break;
924 }
925 }
926
927 DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
928
929 /* Decode codec private data if necessary */
930 if (context->encodings && context->encodings->len > 0 && context->codec_priv
931 && context->codec_priv_size > 0) {
932 if (!gst_matroska_decode_data (context->encodings,
933 &context->codec_priv, &context->codec_priv_size,
934 GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
935 GST_WARNING_OBJECT (parse, "Decoding codec private data failed");
936 ret = GST_FLOW_ERROR;
937 }
938 }
939
940 if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK
941 && ret != GST_FLOW_EOS)) {
942 if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
943 GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header");
944
945 parse->common.num_streams--;
946 g_ptr_array_remove_index (parse->common.src, parse->common.num_streams);
947 g_assert (parse->common.src->len == parse->common.num_streams);
948 gst_matroska_track_free (context);
949
950 return ret;
951 }
952
953 if ((context->language == NULL || *context->language == '\0') &&
954 (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO ||
955 context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
956 GST_LOG ("stream %d: language=eng (assuming default)", context->index);
957 context->language = g_strdup ("eng");
958 }
959
960
961 /* tadaah! */
962 return ret;
963 }
964
965 static gboolean
gst_matroska_parse_query(GstMatroskaParse * parse,GstPad * pad,GstQuery * query)966 gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
967 GstQuery * query)
968 {
969 gboolean res = FALSE;
970 GstMatroskaTrackContext *context = NULL;
971
972 if (pad) {
973 context = gst_pad_get_element_private (pad);
974 }
975
976 switch (GST_QUERY_TYPE (query)) {
977 case GST_QUERY_POSITION:
978 {
979 GstFormat format;
980
981 gst_query_parse_position (query, &format, NULL);
982
983 if (format == GST_FORMAT_TIME) {
984 GST_OBJECT_LOCK (parse);
985 if (context)
986 gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
987 else
988 gst_query_set_position (query, GST_FORMAT_TIME,
989 parse->common.segment.position);
990 GST_OBJECT_UNLOCK (parse);
991 } else if (format == GST_FORMAT_DEFAULT && context
992 && context->default_duration) {
993 GST_OBJECT_LOCK (parse);
994 gst_query_set_position (query, GST_FORMAT_DEFAULT,
995 context->pos / context->default_duration);
996 GST_OBJECT_UNLOCK (parse);
997 } else {
998 GST_DEBUG_OBJECT (parse,
999 "only position query in TIME and DEFAULT format is supported");
1000 }
1001
1002 res = TRUE;
1003 break;
1004 }
1005 case GST_QUERY_DURATION:
1006 {
1007 GstFormat format;
1008
1009 gst_query_parse_duration (query, &format, NULL);
1010
1011 if (format == GST_FORMAT_TIME) {
1012 GST_OBJECT_LOCK (parse);
1013 gst_query_set_duration (query, GST_FORMAT_TIME,
1014 parse->common.segment.duration);
1015 GST_OBJECT_UNLOCK (parse);
1016 } else if (format == GST_FORMAT_DEFAULT && context
1017 && context->default_duration) {
1018 GST_OBJECT_LOCK (parse);
1019 gst_query_set_duration (query, GST_FORMAT_DEFAULT,
1020 parse->common.segment.duration / context->default_duration);
1021 GST_OBJECT_UNLOCK (parse);
1022 } else {
1023 GST_DEBUG_OBJECT (parse,
1024 "only duration query in TIME and DEFAULT format is supported");
1025 }
1026
1027 res = TRUE;
1028 break;
1029 }
1030
1031 case GST_QUERY_SEEKING:
1032 {
1033 GstFormat fmt;
1034
1035 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1036 if (fmt == GST_FORMAT_TIME) {
1037 gboolean seekable;
1038
1039 /* assuming we'll be able to get an index ... */
1040 seekable = parse->seekable;
1041
1042 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1043 0, parse->common.segment.duration);
1044 res = TRUE;
1045 }
1046 break;
1047 }
1048 default:
1049 if (pad)
1050 res = gst_pad_query_default (pad, (GstObject *) parse, query);
1051 break;
1052 }
1053
1054 return res;
1055 }
1056
1057 static gboolean
gst_matroska_parse_element_query(GstElement * element,GstQuery * query)1058 gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
1059 {
1060 return gst_matroska_parse_query (GST_MATROSKA_PARSE (element), NULL, query);
1061 }
1062
1063 static gboolean
gst_matroska_parse_handle_src_query(GstPad * pad,GstObject * parent,GstQuery * query)1064 gst_matroska_parse_handle_src_query (GstPad * pad, GstObject * parent,
1065 GstQuery * query)
1066 {
1067 gboolean ret;
1068 GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
1069
1070 ret = gst_matroska_parse_query (parse, pad, query);
1071
1072 return ret;
1073 }
1074
1075 static void
gst_matroska_parse_send_tags(GstMatroskaParse * parse)1076 gst_matroska_parse_send_tags (GstMatroskaParse * parse)
1077 {
1078 if (G_UNLIKELY (parse->common.global_tags_changed)) {
1079 GstEvent *tag_event;
1080 gst_tag_list_add (parse->common.global_tags, GST_TAG_MERGE_REPLACE,
1081 GST_TAG_CONTAINER_FORMAT, "Matroska", NULL);
1082 GST_DEBUG_OBJECT (parse, "Sending global_tags %p : %" GST_PTR_FORMAT,
1083 parse->common.global_tags, parse->common.global_tags);
1084
1085 /* Send a copy as we want to keep our local ref writable to add more tags
1086 * if any are found */
1087 tag_event =
1088 gst_event_new_tag (gst_tag_list_copy (parse->common.global_tags));
1089
1090 gst_pad_push_event (parse->srcpad, tag_event);
1091
1092 parse->common.global_tags_changed = FALSE;
1093 }
1094 }
1095
1096 /* returns FALSE if there are no pads to deliver event to,
1097 * otherwise TRUE (whatever the outcome of event sending),
1098 * takes ownership of the passed event! */
1099 static gboolean
gst_matroska_parse_send_event(GstMatroskaParse * parse,GstEvent * event)1100 gst_matroska_parse_send_event (GstMatroskaParse * parse, GstEvent * event)
1101 {
1102 gboolean ret = FALSE;
1103
1104 g_return_val_if_fail (event != NULL, FALSE);
1105
1106 GST_DEBUG_OBJECT (parse, "Sending event of type %s to all source pads",
1107 GST_EVENT_TYPE_NAME (event));
1108
1109 gst_pad_push_event (parse->srcpad, event);
1110
1111 return ret;
1112 }
1113
1114 static gboolean
gst_matroska_parse_element_send_event(GstElement * element,GstEvent * event)1115 gst_matroska_parse_element_send_event (GstElement * element, GstEvent * event)
1116 {
1117 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
1118 gboolean res;
1119
1120 g_return_val_if_fail (event != NULL, FALSE);
1121
1122 if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
1123 res = gst_matroska_parse_handle_seek_event (parse, NULL, event);
1124 } else {
1125 GST_WARNING_OBJECT (parse, "Unhandled event of type %s",
1126 GST_EVENT_TYPE_NAME (event));
1127 res = FALSE;
1128 }
1129 gst_event_unref (event);
1130 return res;
1131 }
1132
1133 #if 0
1134 /* searches for a cluster start from @pos,
1135 * return GST_FLOW_OK and cluster position in @pos if found */
1136 static GstFlowReturn
1137 gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
1138 {
1139 gint64 newpos = *pos;
1140 gint64 orig_offset;
1141 GstFlowReturn ret = GST_FLOW_OK;
1142 const guint chunk = 64 * 1024;
1143 GstBuffer *buf;
1144 GstMapInfo map;
1145 gpointer data;
1146 gsize size;
1147 guint64 length;
1148 guint32 id;
1149 guint needed;
1150
1151 orig_offset = parse->common.offset;
1152
1153 /* read in at newpos and scan for ebml cluster id */
1154 while (1) {
1155 GstByteReader reader;
1156 gint cluster_pos;
1157
1158 buf = NULL;
1159 ret = gst_pad_pull_range (parse->common.sinkpad, newpos, chunk, &buf);
1160 if (ret != GST_FLOW_OK)
1161 break;
1162 GST_DEBUG_OBJECT (parse,
1163 "read buffer size %" G_GSIZE_FORMAT " at offset %" G_GINT64_FORMAT,
1164 gst_buffer_get_size (buf), newpos);
1165 gst_buffer_map (buf, &map, GST_MAP_READ);
1166 data = map.data;
1167 size = map.size;
1168 gst_byte_reader_init (&reader, data, size);
1169 cluster_pos = 0;
1170 resume:
1171 cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
1172 GST_MATROSKA_ID_CLUSTER, cluster_pos, size - cluster_pos);
1173 if (cluster_pos >= 0) {
1174 newpos += cluster_pos;
1175 GST_DEBUG_OBJECT (parse,
1176 "found cluster ebml id at offset %" G_GINT64_FORMAT, newpos);
1177 /* extra checks whether we really sync'ed to a cluster:
1178 * - either it is the first and only cluster
1179 * - either there is a cluster after this one
1180 * - either cluster length is undefined
1181 */
1182 /* ok if first cluster (there may not a subsequent one) */
1183 if (newpos == parse->first_cluster_offset) {
1184 GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
1185 break;
1186 }
1187 parse->common.offset = newpos;
1188 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
1189 GST_ELEMENT_CAST (parse), &id, &length, &needed);
1190 if (ret != GST_FLOW_OK)
1191 goto resume;
1192 g_assert (id == GST_MATROSKA_ID_CLUSTER);
1193 GST_DEBUG_OBJECT (parse, "cluster size %" G_GUINT64_FORMAT ", prefix %d",
1194 length, needed);
1195 /* ok if undefined length or first cluster */
1196 if (length == G_MAXUINT64) {
1197 GST_DEBUG_OBJECT (parse, "cluster has undefined length -> OK");
1198 break;
1199 }
1200 /* skip cluster */
1201 parse->common.offset += length + needed;
1202 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
1203 GST_ELEMENT_CAST (parse), &id, &length, &needed);
1204 if (ret != GST_FLOW_OK)
1205 goto resume;
1206 GST_DEBUG_OBJECT (parse, "next element is %scluster",
1207 id == GST_MATROSKA_ID_CLUSTER ? "" : "not ");
1208 if (id == GST_MATROSKA_ID_CLUSTER)
1209 break;
1210 /* not ok, resume */
1211 goto resume;
1212 } else {
1213 /* partial cluster id may have been in tail of buffer */
1214 newpos += MAX (size, 4) - 3;
1215 gst_buffer_unmap (buf, &map);
1216 gst_buffer_unref (buf);
1217 buf = NULL;
1218 }
1219 }
1220
1221 if (buf) {
1222 gst_buffer_unmap (buf, &map);
1223 gst_buffer_unref (buf);
1224 buf = NULL;
1225 }
1226
1227 parse->common.offset = orig_offset;
1228 *pos = newpos;
1229 return ret;
1230 }
1231 #endif
1232
1233 static gboolean
gst_matroska_parse_handle_seek_event(GstMatroskaParse * parse,GstPad * pad,GstEvent * event)1234 gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
1235 GstPad * pad, GstEvent * event)
1236 {
1237 GstMatroskaIndex *entry = NULL;
1238 GstSeekFlags flags;
1239 GstSeekType cur_type, stop_type;
1240 GstFormat format;
1241 gdouble rate;
1242 gint64 cur, stop;
1243 GstMatroskaTrackContext *track = NULL;
1244 GstSegment seeksegment = { 0, };
1245 gboolean update;
1246 GstSearchMode snap_dir;
1247
1248 if (pad)
1249 track = gst_pad_get_element_private (pad);
1250
1251 track = gst_matroska_read_common_get_seek_track (&parse->common, track);
1252
1253 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1254 &stop_type, &stop);
1255
1256 /* we can only seek on time */
1257 if (format != GST_FORMAT_TIME) {
1258 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
1259 return FALSE;
1260 }
1261
1262 /* copy segment, we need this because we still need the old
1263 * segment when we close the current segment. */
1264 memcpy (&seeksegment, &parse->common.segment, sizeof (GstSegment));
1265
1266 if (event) {
1267 GST_DEBUG_OBJECT (parse, "configuring seek");
1268 gst_segment_do_seek (&seeksegment, rate, format, flags,
1269 cur_type, cur, stop_type, stop, &update);
1270 }
1271
1272 GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
1273
1274 if (seeksegment.rate < 0)
1275 snap_dir = GST_SEARCH_MODE_AFTER;
1276 else
1277 snap_dir = GST_SEARCH_MODE_BEFORE;
1278
1279 /* check sanity before we start flushing and all that */
1280 GST_OBJECT_LOCK (parse);
1281 if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track,
1282 seeksegment.position, &parse->seek_index, &parse->seek_entry,
1283 snap_dir)) == NULL) {
1284 /* pull mode without index can scan later on */
1285 GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
1286 GST_OBJECT_UNLOCK (parse);
1287 return FALSE;
1288 }
1289 GST_DEBUG_OBJECT (parse, "Seek position looks sane");
1290 GST_OBJECT_UNLOCK (parse);
1291
1292 /* need to seek to cluster start to pick up cluster time */
1293 /* upstream takes care of flushing and all that
1294 * ... and newsegment event handling takes care of the rest */
1295 return perform_seek_to_offset (parse, entry->pos
1296 + parse->common.ebml_segment_start);
1297 }
1298
1299 /*
1300 * Handle whether we can perform the seek event or if we have to let the chain
1301 * function handle seeks to build the seek indexes first.
1302 */
1303 static gboolean
gst_matroska_parse_handle_seek_push(GstMatroskaParse * parse,GstPad * pad,GstEvent * event)1304 gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad,
1305 GstEvent * event)
1306 {
1307 GstSeekFlags flags;
1308 GstSeekType cur_type, stop_type;
1309 GstFormat format;
1310 gdouble rate;
1311 gint64 cur, stop;
1312
1313 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1314 &stop_type, &stop);
1315
1316 /* sanity checks */
1317
1318 /* we can only seek on time */
1319 if (format != GST_FORMAT_TIME) {
1320 GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
1321 return FALSE;
1322 }
1323
1324 if (stop_type != GST_SEEK_TYPE_NONE && stop != GST_CLOCK_TIME_NONE) {
1325 GST_DEBUG_OBJECT (parse, "Seek end-time not supported in streaming mode");
1326 return FALSE;
1327 }
1328
1329 if (!(flags & GST_SEEK_FLAG_FLUSH)) {
1330 GST_DEBUG_OBJECT (parse,
1331 "Non-flushing seek not supported in streaming mode");
1332 return FALSE;
1333 }
1334
1335 if (flags & GST_SEEK_FLAG_SEGMENT) {
1336 GST_DEBUG_OBJECT (parse, "Segment seek not supported in streaming mode");
1337 return FALSE;
1338 }
1339
1340 /* check for having parsed index already */
1341 if (!parse->common.index_parsed) {
1342 gboolean building_index;
1343 guint64 offset = 0;
1344
1345 if (!parse->index_offset) {
1346 GST_DEBUG_OBJECT (parse, "no index (location); no seek in push mode");
1347 return FALSE;
1348 }
1349
1350 GST_OBJECT_LOCK (parse);
1351 /* handle the seek event in the chain function */
1352 parse->common.state = GST_MATROSKA_READ_STATE_SEEK;
1353 /* no more seek can be issued until state reset to _DATA */
1354
1355 /* copy the event */
1356 if (parse->seek_event)
1357 gst_event_unref (parse->seek_event);
1358 parse->seek_event = gst_event_ref (event);
1359
1360 /* set the building_index flag so that only one thread can setup the
1361 * structures for index seeking. */
1362 building_index = parse->building_index;
1363 if (!building_index) {
1364 parse->building_index = TRUE;
1365 offset = parse->index_offset;
1366 }
1367 GST_OBJECT_UNLOCK (parse);
1368
1369 if (!building_index) {
1370 /* seek to the first subindex or legacy index */
1371 GST_INFO_OBJECT (parse, "Seeking to Cues at %" G_GUINT64_FORMAT, offset);
1372 return perform_seek_to_offset (parse, offset);
1373 }
1374
1375 /* well, we are handling it already */
1376 return TRUE;
1377 }
1378
1379 /* delegate to tweaked regular seek */
1380 return gst_matroska_parse_handle_seek_event (parse, pad, event);
1381 }
1382
1383 static gboolean
gst_matroska_parse_handle_src_event(GstPad * pad,GstObject * parent,GstEvent * event)1384 gst_matroska_parse_handle_src_event (GstPad * pad, GstObject * parent,
1385 GstEvent * event)
1386 {
1387 GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
1388 gboolean res = TRUE;
1389
1390 switch (GST_EVENT_TYPE (event)) {
1391 case GST_EVENT_SEEK:
1392 /* no seeking until we are (safely) ready */
1393 if (parse->common.state != GST_MATROSKA_READ_STATE_DATA) {
1394 GST_DEBUG_OBJECT (parse, "not ready for seeking yet");
1395 return FALSE;
1396 }
1397 res = gst_matroska_parse_handle_seek_push (parse, pad, event);
1398 gst_event_unref (event);
1399 break;
1400
1401 case GST_EVENT_QOS:
1402 {
1403 GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
1404 if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
1405 GstMatroskaTrackVideoContext *videocontext =
1406 (GstMatroskaTrackVideoContext *) context;
1407 gdouble proportion;
1408 GstClockTimeDiff diff;
1409 GstClockTime timestamp;
1410
1411 gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
1412
1413 GST_OBJECT_LOCK (parse);
1414 videocontext->earliest_time = timestamp + diff;
1415 GST_OBJECT_UNLOCK (parse);
1416 }
1417 res = TRUE;
1418 gst_event_unref (event);
1419 break;
1420 }
1421
1422 /* events we don't need to handle */
1423 case GST_EVENT_NAVIGATION:
1424 gst_event_unref (event);
1425 res = FALSE;
1426 break;
1427
1428 case GST_EVENT_LATENCY:
1429 default:
1430 res = gst_pad_push_event (parse->common.sinkpad, event);
1431 break;
1432 }
1433
1434 return res;
1435 }
1436
1437 static GstFlowReturn
gst_matroska_parse_parse_tracks(GstMatroskaParse * parse,GstEbmlRead * ebml)1438 gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml)
1439 {
1440 GstFlowReturn ret = GST_FLOW_OK;
1441 guint32 id;
1442
1443 DEBUG_ELEMENT_START (parse, ebml, "Tracks");
1444
1445 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1446 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
1447 return ret;
1448 }
1449
1450 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1451 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1452 break;
1453
1454 switch (id) {
1455 /* one track within the "all-tracks" header */
1456 case GST_MATROSKA_ID_TRACKENTRY:
1457 ret = gst_matroska_parse_add_stream (parse, ebml);
1458 break;
1459
1460 default:
1461 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
1462 "Track", id);
1463 break;
1464 }
1465 }
1466 DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
1467
1468 parse->tracks_parsed = TRUE;
1469
1470 return ret;
1471 }
1472
1473 /*
1474 * Read signed/unsigned "EBML" numbers.
1475 * Return: number of bytes processed.
1476 */
1477
1478 static gint
gst_matroska_ebmlnum_uint(guint8 * data,guint size,guint64 * num)1479 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
1480 {
1481 gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1482 guint64 total;
1483
1484 if (size <= 0) {
1485 return -1;
1486 }
1487
1488 total = data[0];
1489 while (read <= 8 && !(total & len_mask)) {
1490 read++;
1491 len_mask >>= 1;
1492 }
1493 if (read > 8)
1494 return -1;
1495
1496 if ((total &= (len_mask - 1)) == len_mask - 1)
1497 num_ffs++;
1498 if (size < read)
1499 return -1;
1500 while (n < read) {
1501 if (data[n] == 0xff)
1502 num_ffs++;
1503 total = (total << 8) | data[n];
1504 n++;
1505 }
1506
1507 if (read == num_ffs && total != 0)
1508 *num = G_MAXUINT64;
1509 else
1510 *num = total;
1511
1512 return read;
1513 }
1514
1515 static gint
gst_matroska_ebmlnum_sint(guint8 * data,guint size,gint64 * num)1516 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
1517 {
1518 guint64 unum;
1519 gint res;
1520
1521 /* read as unsigned number first */
1522 if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1523 return -1;
1524
1525 /* make signed */
1526 if (unum == G_MAXUINT64)
1527 *num = G_MAXINT64;
1528 else
1529 *num = unum - ((1 << ((7 * res) - 1)) - 1);
1530
1531 return res;
1532 }
1533
1534 static GstFlowReturn
gst_matroska_parse_parse_blockgroup_or_simpleblock(GstMatroskaParse * parse,GstEbmlRead * ebml,guint64 cluster_time,guint64 cluster_offset,gboolean is_simpleblock)1535 gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
1536 GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset,
1537 gboolean is_simpleblock)
1538 {
1539 GstMatroskaTrackContext *stream = NULL;
1540 GstFlowReturn ret = GST_FLOW_OK;
1541 gboolean readblock = FALSE;
1542 guint32 id;
1543 guint64 block_duration = 0;
1544 GstBuffer *buf = NULL;
1545 GstMapInfo map;
1546 gint stream_num = -1, n, laces = 0;
1547 guint size = 0;
1548 gint *lace_size = NULL;
1549 gint64 time = 0;
1550 gint flags = 0;
1551 gint64 referenceblock = 0;
1552
1553 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1554 if (!is_simpleblock) {
1555 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) {
1556 goto data_error;
1557 }
1558 } else {
1559 id = GST_MATROSKA_ID_SIMPLEBLOCK;
1560 }
1561
1562 switch (id) {
1563 /* one block inside the group. Note, block parsing is one
1564 * of the harder things, so this code is a bit complicated.
1565 * See http://www.matroska.org/ for documentation. */
1566 case GST_MATROSKA_ID_SIMPLEBLOCK:
1567 case GST_MATROSKA_ID_BLOCK:
1568 {
1569 guint64 num;
1570 guint8 *data;
1571
1572 if (buf) {
1573 gst_buffer_unref (buf);
1574 buf = NULL;
1575 }
1576 if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
1577 break;
1578
1579 gst_buffer_map (buf, &map, GST_MAP_READ);
1580 data = map.data;
1581 size = map.size;
1582
1583 /* first byte(s): blocknum */
1584 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
1585 goto data_error;
1586 data += n;
1587 size -= n;
1588
1589 /* fetch stream from num */
1590 stream_num = gst_matroska_read_common_stream_from_num (&parse->common,
1591 num);
1592 if (G_UNLIKELY (size < 3)) {
1593 GST_WARNING_OBJECT (parse, "Invalid size %u", size);
1594 /* non-fatal, try next block(group) */
1595 ret = GST_FLOW_OK;
1596 goto done;
1597 } else if (G_UNLIKELY (stream_num < 0 ||
1598 stream_num >= parse->common.num_streams)) {
1599 /* let's not give up on a stray invalid track number */
1600 GST_WARNING_OBJECT (parse,
1601 "Invalid stream %d for track number %" G_GUINT64_FORMAT
1602 "; ignoring block", stream_num, num);
1603 goto done;
1604 }
1605
1606 stream = g_ptr_array_index (parse->common.src, stream_num);
1607
1608 /* time (relative to cluster time) */
1609 time = ((gint16) GST_READ_UINT16_BE (data));
1610 data += 2;
1611 size -= 2;
1612 flags = GST_READ_UINT8 (data);
1613 data += 1;
1614 size -= 1;
1615
1616 GST_LOG_OBJECT (parse, "time %" G_GUINT64_FORMAT ", flags %d", time,
1617 flags);
1618
1619 switch ((flags & 0x06) >> 1) {
1620 case 0x0: /* no lacing */
1621 laces = 1;
1622 lace_size = g_new (gint, 1);
1623 lace_size[0] = size;
1624 break;
1625
1626 case 0x1: /* xiph lacing */
1627 case 0x2: /* fixed-size lacing */
1628 case 0x3: /* EBML lacing */
1629 if (size == 0)
1630 goto invalid_lacing;
1631 laces = GST_READ_UINT8 (data) + 1;
1632 data += 1;
1633 size -= 1;
1634 lace_size = g_new0 (gint, laces);
1635
1636 switch ((flags & 0x06) >> 1) {
1637 case 0x1: /* xiph lacing */ {
1638 guint temp, total = 0;
1639
1640 for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
1641 while (1) {
1642 if (size == 0)
1643 goto invalid_lacing;
1644 temp = GST_READ_UINT8 (data);
1645 lace_size[n] += temp;
1646 data += 1;
1647 size -= 1;
1648 if (temp != 0xff)
1649 break;
1650 }
1651 total += lace_size[n];
1652 }
1653 lace_size[n] = size - total;
1654 break;
1655 }
1656
1657 case 0x2: /* fixed-size lacing */
1658 for (n = 0; n < laces; n++)
1659 lace_size[n] = size / laces;
1660 break;
1661
1662 case 0x3: /* EBML lacing */ {
1663 guint total;
1664
1665 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
1666 goto data_error;
1667 data += n;
1668 size -= n;
1669 total = lace_size[0] = num;
1670 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
1671 gint64 snum;
1672 gint r;
1673
1674 if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0)
1675 goto data_error;
1676 data += r;
1677 size -= r;
1678 lace_size[n] = lace_size[n - 1] + snum;
1679 total += lace_size[n];
1680 }
1681 if (n < laces)
1682 lace_size[n] = size - total;
1683 break;
1684 }
1685 }
1686 break;
1687 }
1688
1689 if (ret != GST_FLOW_OK)
1690 break;
1691
1692 readblock = TRUE;
1693 break;
1694 }
1695
1696 case GST_MATROSKA_ID_BLOCKDURATION:{
1697 ret = gst_ebml_read_uint (ebml, &id, &block_duration);
1698 GST_DEBUG_OBJECT (parse, "BlockDuration: %" G_GUINT64_FORMAT,
1699 block_duration);
1700 break;
1701 }
1702
1703 case GST_MATROSKA_ID_REFERENCEBLOCK:{
1704 ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
1705 GST_DEBUG_OBJECT (parse, "ReferenceBlock: %" G_GINT64_FORMAT,
1706 referenceblock);
1707 break;
1708 }
1709
1710 case GST_MATROSKA_ID_CODECSTATE:{
1711 guint8 *data;
1712 guint64 data_len = 0;
1713
1714 if ((ret =
1715 gst_ebml_read_binary (ebml, &id, &data,
1716 &data_len)) != GST_FLOW_OK)
1717 break;
1718
1719 if (G_UNLIKELY (stream == NULL)) {
1720 GST_WARNING_OBJECT (parse,
1721 "Unexpected CodecState subelement - ignoring");
1722 break;
1723 }
1724
1725 g_free (stream->codec_state);
1726 stream->codec_state = data;
1727 stream->codec_state_size = data_len;
1728
1729 break;
1730 }
1731
1732 default:
1733 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
1734 "BlockGroup", id);
1735 break;
1736
1737 case GST_MATROSKA_ID_BLOCKVIRTUAL:
1738 case GST_MATROSKA_ID_BLOCKADDITIONS:
1739 case GST_MATROSKA_ID_REFERENCEPRIORITY:
1740 case GST_MATROSKA_ID_REFERENCEVIRTUAL:
1741 case GST_MATROSKA_ID_SLICES:
1742 GST_DEBUG_OBJECT (parse,
1743 "Skipping BlockGroup subelement 0x%x - ignoring", id);
1744 ret = gst_ebml_read_skip (ebml);
1745 break;
1746 }
1747
1748 if (is_simpleblock)
1749 break;
1750 }
1751
1752 /* reading a number or so could have failed */
1753 if (ret != GST_FLOW_OK)
1754 goto data_error;
1755
1756 if (ret == GST_FLOW_OK && readblock) {
1757 guint64 duration = 0;
1758 gint64 lace_time = 0;
1759 gboolean delta_unit;
1760
1761 stream = g_ptr_array_index (parse->common.src, stream_num);
1762
1763 if (cluster_time != GST_CLOCK_TIME_NONE) {
1764 /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
1765 * Drop unless the lace contains timestamp 0? */
1766 if (time < 0 && (-time) > cluster_time) {
1767 lace_time = 0;
1768 } else {
1769 if (stream->timecodescale == 1.0)
1770 lace_time = (cluster_time + time) * parse->common.time_scale;
1771 else
1772 lace_time =
1773 gst_util_guint64_to_gdouble ((cluster_time + time) *
1774 parse->common.time_scale) * stream->timecodescale;
1775 }
1776 } else {
1777 lace_time = GST_CLOCK_TIME_NONE;
1778 }
1779
1780 if (lace_time != GST_CLOCK_TIME_NONE) {
1781 parse->last_timestamp = lace_time;
1782 }
1783 /* need to refresh segment info ASAP */
1784 if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
1785 GstSegment segment;
1786 GST_DEBUG_OBJECT (parse,
1787 "generating segment starting at %" GST_TIME_FORMAT,
1788 GST_TIME_ARGS (lace_time));
1789 /* pretend we seeked here */
1790 gst_segment_do_seek (&parse->common.segment, parse->common.segment.rate,
1791 GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
1792 GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
1793 /* now convey our segment notion downstream */
1794 segment = parse->common.segment;
1795 segment.position = segment.start;
1796 gst_matroska_parse_send_event (parse, gst_event_new_segment (&segment));
1797 parse->need_newsegment = FALSE;
1798 }
1799
1800 if (block_duration) {
1801 if (stream->timecodescale == 1.0)
1802 duration = gst_util_uint64_scale (block_duration,
1803 parse->common.time_scale, 1);
1804 else
1805 duration =
1806 gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
1807 (gst_util_uint64_scale (block_duration, parse->common.time_scale,
1808 1)) * stream->timecodescale);
1809 } else if (stream->default_duration) {
1810 duration = stream->default_duration * laces;
1811 }
1812 /* else duration is diff between timecode of this and next block */
1813
1814 /* For SimpleBlock, look at the keyframe bit in flags. Otherwise,
1815 a ReferenceBlock implies that this is not a keyframe. In either
1816 case, it only makes sense for video streams. */
1817 delta_unit = stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
1818 ((is_simpleblock && !(flags & 0x80)) || referenceblock);
1819
1820 if (delta_unit && stream->set_discont) {
1821 /* When doing seeks or such, we need to restart on key frames or
1822 * decoders might choke. */
1823 GST_DEBUG_OBJECT (parse, "skipping delta unit");
1824 goto done;
1825 }
1826
1827 for (n = 0; n < laces; n++) {
1828 if (G_UNLIKELY (lace_size[n] > size)) {
1829 GST_WARNING_OBJECT (parse, "Invalid lace size");
1830 break;
1831 }
1832
1833 /* QoS for video track with an index. the assumption is that
1834 index entries point to keyframes, but if that is not true we
1835 will instad skip until the next keyframe. */
1836 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
1837 stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
1838 stream->index_table && parse->common.segment.rate > 0.0) {
1839 GstMatroskaTrackVideoContext *videocontext =
1840 (GstMatroskaTrackVideoContext *) stream;
1841 GstClockTime earliest_time;
1842 GstClockTime earliest_stream_time;
1843
1844 GST_OBJECT_LOCK (parse);
1845 earliest_time = videocontext->earliest_time;
1846 GST_OBJECT_UNLOCK (parse);
1847 earliest_stream_time =
1848 gst_segment_position_from_running_time (&parse->common.segment,
1849 GST_FORMAT_TIME, earliest_time);
1850
1851 if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
1852 GST_CLOCK_TIME_IS_VALID (earliest_stream_time) &&
1853 lace_time <= earliest_stream_time) {
1854 /* find index entry (keyframe) <= earliest_stream_time */
1855 GstMatroskaIndex *entry =
1856 gst_util_array_binary_search (stream->index_table->data,
1857 stream->index_table->len, sizeof (GstMatroskaIndex),
1858 (GCompareDataFunc) gst_matroska_index_seek_find,
1859 GST_SEARCH_MODE_BEFORE, &earliest_stream_time, NULL);
1860
1861 /* if that entry (keyframe) is after the current the current
1862 buffer, we can skip pushing (and thus decoding) all
1863 buffers until that keyframe. */
1864 if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
1865 entry->time > lace_time) {
1866 GST_LOG_OBJECT (parse, "Skipping lace before late keyframe");
1867 stream->set_discont = TRUE;
1868 goto next_lace;
1869 }
1870 }
1871 }
1872 #if 0
1873 sub = gst_buffer_create_sub (buf,
1874 GST_BUFFER_SIZE (buf) - size, lace_size[n]);
1875 GST_DEBUG_OBJECT (parse, "created subbuffer %p", sub);
1876
1877 if (delta_unit)
1878 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
1879 else
1880 GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
1881
1882 if (stream->encodings != NULL && stream->encodings->len > 0)
1883 sub = gst_matroska_decode_buffer (stream, sub);
1884
1885 if (sub == NULL) {
1886 GST_WARNING_OBJECT (parse, "Decoding buffer failed");
1887 goto next_lace;
1888 }
1889
1890 GST_BUFFER_TIMESTAMP (sub) = lace_time;
1891
1892 if (GST_CLOCK_TIME_IS_VALID (lace_time)) {
1893 GstClockTime last_stop_end;
1894
1895 /* Check if this stream is after segment stop */
1896 if (GST_CLOCK_TIME_IS_VALID (parse->common.segment.stop) &&
1897 lace_time >= parse->common.segment.stop) {
1898 GST_DEBUG_OBJECT (parse,
1899 "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index,
1900 GST_TIME_ARGS (parse->common.segment.stop));
1901 gst_buffer_unref (sub);
1902 goto eos;
1903 }
1904 if (offset >= stream->to_offset) {
1905 GST_DEBUG_OBJECT (parse, "Stream %d after playback section",
1906 stream->index);
1907 gst_buffer_unref (sub);
1908 goto eos;
1909 }
1910
1911 /* handle gaps, e.g. non-zero start-time, or an cue index entry
1912 * that landed us with timestamps not quite intended */
1913 if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
1914 parse->segment.rate > 0.0) {
1915 GstClockTimeDiff diff;
1916
1917 /* only send newsegments with increasing start times,
1918 * otherwise if these go back and forth downstream (sinks) increase
1919 * accumulated time and running_time */
1920 diff = GST_CLOCK_DIFF (parse->segment.last_stop, lace_time);
1921 if (diff > 2 * GST_SECOND && lace_time > parse->segment.start &&
1922 (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) ||
1923 lace_time < parse->segment.stop)) {
1924 GST_DEBUG_OBJECT (parse,
1925 "Gap of %" G_GINT64_FORMAT " ns detected in"
1926 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
1927 "Sending updated NEWSEGMENT events", diff,
1928 stream->index, GST_TIME_ARGS (stream->pos),
1929 GST_TIME_ARGS (lace_time));
1930 /* send newsegment events such that the gap is not accounted in
1931 * accum time, hence running_time */
1932 /* close ahead of gap */
1933 gst_matroska_parse_send_event (parse,
1934 gst_event_new_new_segment (TRUE, parse->segment.rate,
1935 parse->segment.format, parse->segment.last_stop,
1936 parse->segment.last_stop, parse->segment.last_stop));
1937 /* skip gap */
1938 gst_matroska_parse_send_event (parse,
1939 gst_event_new_new_segment (FALSE, parse->segment.rate,
1940 parse->segment.format, lace_time, parse->segment.stop,
1941 lace_time));
1942 /* align segment view with downstream,
1943 * prevents double-counting accum when closing segment */
1944 gst_segment_set_newsegment (&parse->segment, FALSE,
1945 parse->segment.rate, parse->segment.format, lace_time,
1946 parse->segment.stop, lace_time);
1947 parse->segment.last_stop = lace_time;
1948 }
1949 }
1950
1951 if (!GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)
1952 || parse->segment.last_stop < lace_time) {
1953 parse->segment.last_stop = lace_time;
1954 }
1955
1956 last_stop_end = lace_time;
1957 if (duration) {
1958 GST_BUFFER_DURATION (sub) = duration / laces;
1959 last_stop_end += GST_BUFFER_DURATION (sub);
1960 }
1961
1962 if (!GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) ||
1963 parse->last_stop_end < last_stop_end)
1964 parse->last_stop_end = last_stop_end;
1965
1966 if (parse->segment.duration == -1 ||
1967 parse->segment.duration < lace_time) {
1968 gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME,
1969 last_stop_end);
1970 gst_element_post_message (GST_ELEMENT_CAST (parse),
1971 gst_message_new_duration (GST_OBJECT_CAST (parse),
1972 GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
1973 }
1974 }
1975
1976 stream->pos = lace_time;
1977
1978 gst_matroska_parse_sync_streams (parse);
1979
1980 if (stream->set_discont) {
1981 GST_DEBUG_OBJECT (parse, "marking DISCONT");
1982 GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
1983 stream->set_discont = FALSE;
1984 }
1985
1986 /* reverse playback book-keeping */
1987 if (!GST_CLOCK_TIME_IS_VALID (stream->from_time))
1988 stream->from_time = lace_time;
1989 if (stream->from_offset == -1)
1990 stream->from_offset = offset;
1991
1992 GST_DEBUG_OBJECT (parse,
1993 "Pushing lace %d, data of size %d for stream %d, time=%"
1994 GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
1995 GST_BUFFER_SIZE (sub), stream_num,
1996 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
1997 GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
1998
1999 if (parse->element_index) {
2000 if (stream->index_writer_id == -1)
2001 gst_index_get_writer_id (parse->element_index,
2002 GST_OBJECT (stream->pad), &stream->index_writer_id);
2003
2004 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2005 G_GUINT64_FORMAT " for writer id %d",
2006 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
2007 stream->index_writer_id);
2008 gst_index_add_association (parse->element_index,
2009 stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
2010 GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
2011 GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
2012 cluster_offset, NULL);
2013 }
2014
2015 gst_buffer_set_caps (sub, GST_PAD_CAPS (parse->srcpad));
2016
2017 /* Postprocess the buffers depending on the codec used */
2018 if (stream->postprocess_frame) {
2019 GST_LOG_OBJECT (parse, "running post process");
2020 ret = stream->postprocess_frame (GST_ELEMENT (parse), stream, &sub);
2021 }
2022
2023 ret = gst_pad_push (stream->pad, sub);
2024 if (parse->segment.rate < 0) {
2025 if (lace_time > parse->segment.stop && ret == GST_FLOW_EOS) {
2026 /* In reverse playback we can get a GST_FLOW_EOS when
2027 * we are at the end of the segment, so we just need to jump
2028 * back to the previous section. */
2029 GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
2030 ret = GST_FLOW_OK;
2031 }
2032 }
2033 /* combine flows */
2034 ret = gst_matroska_parse_combine_flows (parse, stream, ret);
2035 #endif
2036
2037 next_lace:
2038 size -= lace_size[n];
2039 if (lace_time != GST_CLOCK_TIME_NONE && duration)
2040 lace_time += duration / laces;
2041 else
2042 lace_time = GST_CLOCK_TIME_NONE;
2043 }
2044 }
2045
2046 done:
2047 if (buf) {
2048 gst_buffer_unmap (buf, &map);
2049 gst_buffer_unref (buf);
2050 }
2051 g_free (lace_size);
2052
2053 return ret;
2054
2055 /* EXITS */
2056 invalid_lacing:
2057 {
2058 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
2059 /* non-fatal, try next block(group) */
2060 ret = GST_FLOW_OK;
2061 goto done;
2062 }
2063 data_error:
2064 {
2065 GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Data error"));
2066 /* non-fatal, try next block(group) */
2067 ret = GST_FLOW_OK;
2068 goto done;
2069 }
2070 }
2071
2072 /* return FALSE if block(group) should be skipped (due to a seek) */
2073 static inline gboolean
gst_matroska_parse_seek_block(GstMatroskaParse * parse)2074 gst_matroska_parse_seek_block (GstMatroskaParse * parse)
2075 {
2076 if (G_UNLIKELY (parse->seek_block)) {
2077 if (!(--parse->seek_block)) {
2078 return TRUE;
2079 } else {
2080 GST_LOG_OBJECT (parse, "should skip block due to seek");
2081 return FALSE;
2082 }
2083 } else {
2084 return TRUE;
2085 }
2086 }
2087
2088 static GstFlowReturn
gst_matroska_parse_parse_contents_seekentry(GstMatroskaParse * parse,GstEbmlRead * ebml)2089 gst_matroska_parse_parse_contents_seekentry (GstMatroskaParse * parse,
2090 GstEbmlRead * ebml)
2091 {
2092 GstFlowReturn ret;
2093 guint64 seek_pos = (guint64) - 1;
2094 guint32 seek_id = 0;
2095 guint32 id;
2096
2097 DEBUG_ELEMENT_START (parse, ebml, "Seek");
2098
2099 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2100 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
2101 return ret;
2102 }
2103
2104 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2105 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2106 break;
2107
2108 switch (id) {
2109 case GST_MATROSKA_ID_SEEKID:
2110 {
2111 guint64 t;
2112
2113 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
2114 break;
2115
2116 GST_DEBUG_OBJECT (parse, "SeekID: %" G_GUINT64_FORMAT, t);
2117 seek_id = t;
2118 break;
2119 }
2120
2121 case GST_MATROSKA_ID_SEEKPOSITION:
2122 {
2123 guint64 t;
2124
2125 if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
2126 break;
2127
2128 if (t > G_MAXINT64) {
2129 GST_WARNING_OBJECT (parse,
2130 "Too large SeekPosition %" G_GUINT64_FORMAT, t);
2131 break;
2132 }
2133
2134 GST_DEBUG_OBJECT (parse, "SeekPosition: %" G_GUINT64_FORMAT, t);
2135 seek_pos = t;
2136 break;
2137 }
2138
2139 default:
2140 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
2141 "SeekHead", id);
2142 break;
2143 }
2144 }
2145
2146 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2147 return ret;
2148
2149 if (!seek_id || seek_pos == (guint64) - 1) {
2150 GST_WARNING_OBJECT (parse, "Incomplete seekhead entry (0x%x/%"
2151 G_GUINT64_FORMAT ")", seek_id, seek_pos);
2152 return GST_FLOW_OK;
2153 }
2154
2155 switch (seek_id) {
2156 case GST_MATROSKA_ID_SEEKHEAD:
2157 {
2158 }
2159 case GST_MATROSKA_ID_CUES:
2160 case GST_MATROSKA_ID_TAGS:
2161 case GST_MATROSKA_ID_TRACKS:
2162 case GST_MATROSKA_ID_SEGMENTINFO:
2163 case GST_MATROSKA_ID_ATTACHMENTS:
2164 case GST_MATROSKA_ID_CHAPTERS:
2165 {
2166 guint64 length;
2167
2168 /* remember */
2169 length = gst_matroska_read_common_get_length (&parse->common);
2170
2171 if (length == (guint64) - 1) {
2172 GST_DEBUG_OBJECT (parse, "no upstream length, skipping SeakHead entry");
2173 break;
2174 }
2175
2176 /* check for validity */
2177 if (seek_pos + parse->common.ebml_segment_start + 12 >= length) {
2178 GST_WARNING_OBJECT (parse,
2179 "SeekHead reference lies outside file!" " (%"
2180 G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
2181 G_GUINT64_FORMAT ")", seek_pos, parse->common.ebml_segment_start,
2182 length);
2183 break;
2184 }
2185
2186 /* only pick up index location when streaming */
2187 if (seek_id == GST_MATROSKA_ID_CUES) {
2188 parse->index_offset = seek_pos + parse->common.ebml_segment_start;
2189 GST_DEBUG_OBJECT (parse, "Cues located at offset %" G_GUINT64_FORMAT,
2190 parse->index_offset);
2191 }
2192 break;
2193 }
2194
2195 default:
2196 GST_DEBUG_OBJECT (parse, "Ignoring Seek entry for ID=0x%x", seek_id);
2197 break;
2198 }
2199 DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
2200
2201 return ret;
2202 }
2203
2204 static GstFlowReturn
gst_matroska_parse_parse_contents(GstMatroskaParse * parse,GstEbmlRead * ebml)2205 gst_matroska_parse_parse_contents (GstMatroskaParse * parse, GstEbmlRead * ebml)
2206 {
2207 GstFlowReturn ret = GST_FLOW_OK;
2208 guint32 id;
2209
2210 DEBUG_ELEMENT_START (parse, ebml, "SeekHead");
2211
2212 if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2213 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
2214 return ret;
2215 }
2216
2217 while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2218 if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2219 break;
2220
2221 switch (id) {
2222 case GST_MATROSKA_ID_SEEKENTRY:
2223 {
2224 ret = gst_matroska_parse_parse_contents_seekentry (parse, ebml);
2225 /* Ignore EOS and errors here */
2226 if (ret != GST_FLOW_OK) {
2227 GST_DEBUG_OBJECT (parse, "Ignoring %s", gst_flow_get_name (ret));
2228 ret = GST_FLOW_OK;
2229 }
2230 break;
2231 }
2232
2233 default:
2234 ret = gst_matroska_read_common_parse_skip (&parse->common, ebml,
2235 "SeekHead", id);
2236 break;
2237 }
2238 }
2239
2240 DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
2241
2242 return ret;
2243 }
2244
2245 #define GST_FLOW_OVERFLOW GST_FLOW_CUSTOM_ERROR
2246
2247 #define MAX_BLOCK_SIZE (15 * 1024 * 1024)
2248
2249 static inline GstFlowReturn
gst_matroska_parse_check_read_size(GstMatroskaParse * parse,guint64 bytes)2250 gst_matroska_parse_check_read_size (GstMatroskaParse * parse, guint64 bytes)
2251 {
2252 if (G_UNLIKELY (bytes > MAX_BLOCK_SIZE)) {
2253 /* only a few blocks are expected/allowed to be large,
2254 * and will be recursed into, whereas others will be read and must fit */
2255 /* fatal in streaming case, as we can't step over easily */
2256 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2257 ("reading large block of size %" G_GUINT64_FORMAT " not supported; "
2258 "file might be corrupt.", bytes));
2259 return GST_FLOW_ERROR;
2260 } else {
2261 return GST_FLOW_OK;
2262 }
2263 }
2264
2265 #if 0
2266 /* returns TRUE if we truely are in error state, and should give up */
2267 static inline gboolean
2268 gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
2269 {
2270 gint64 pos;
2271
2272 /* sigh, one last attempt above and beyond call of duty ...;
2273 * search for cluster mark following current pos */
2274 pos = parse->common.offset;
2275 GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
2276 if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
2277 /* did not work, give up */
2278 return TRUE;
2279 } else {
2280 GST_DEBUG_OBJECT (parse, "... found at %" G_GUINT64_FORMAT, pos);
2281 /* try that position */
2282 parse->common.offset = pos;
2283 return FALSE;
2284 }
2285 }
2286 #endif
2287
2288 /* initializes @ebml with @bytes from input stream at current offset.
2289 * Returns EOS if insufficient available,
2290 * ERROR if too much was attempted to read. */
2291 static inline GstFlowReturn
gst_matroska_parse_take(GstMatroskaParse * parse,guint64 bytes,GstEbmlRead * ebml)2292 gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes,
2293 GstEbmlRead * ebml)
2294 {
2295 GstBuffer *buffer = NULL;
2296 GstFlowReturn ret = GST_FLOW_OK;
2297
2298 GST_LOG_OBJECT (parse, "taking %" G_GUINT64_FORMAT " bytes for parsing",
2299 bytes);
2300 ret = gst_matroska_parse_check_read_size (parse, bytes);
2301 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2302 /* otherwise fatal */
2303 ret = GST_FLOW_ERROR;
2304 goto exit;
2305 }
2306 if (gst_adapter_available (parse->common.adapter) < bytes)
2307 return GST_FLOW_EOS;
2308
2309 buffer = gst_adapter_take_buffer (parse->common.adapter, bytes);
2310 if (G_LIKELY (buffer)) {
2311 gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer,
2312 parse->common.offset);
2313 parse->common.offset += bytes;
2314 } else {
2315 ret = GST_FLOW_ERROR;
2316 }
2317 exit:
2318
2319 return ret;
2320 }
2321
2322 static void
gst_matroska_parse_check_seekability(GstMatroskaParse * parse)2323 gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
2324 {
2325 GstQuery *query;
2326 gboolean seekable = FALSE;
2327 gint64 start = -1, stop = -1;
2328
2329 query = gst_query_new_seeking (GST_FORMAT_BYTES);
2330 if (!gst_pad_peer_query (parse->common.sinkpad, query)) {
2331 GST_DEBUG_OBJECT (parse, "seeking query failed");
2332 goto done;
2333 }
2334
2335 gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
2336
2337 /* try harder to query upstream size if we didn't get it the first time */
2338 if (seekable && stop == -1) {
2339 GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
2340 gst_pad_peer_query_duration (parse->common.sinkpad, GST_FORMAT_BYTES,
2341 &stop);
2342 }
2343
2344 /* if upstream doesn't know the size, it's likely that it's not seekable in
2345 * practice even if it technically may be seekable */
2346 if (seekable && (start != 0 || stop <= start)) {
2347 GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
2348 seekable = FALSE;
2349 }
2350
2351 done:
2352 GST_INFO_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
2353 G_GUINT64_FORMAT ")", seekable, start, stop);
2354 parse->seekable = seekable;
2355
2356 gst_query_unref (query);
2357 }
2358
2359 #if 0
2360 static GstFlowReturn
2361 gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
2362 {
2363 guint32 id;
2364 guint64 before_pos;
2365 guint64 length;
2366 guint needed;
2367 GstFlowReturn ret = GST_FLOW_OK;
2368
2369 GST_WARNING_OBJECT (parse,
2370 "Found Cluster element before Tracks, searching Tracks");
2371
2372 /* remember */
2373 before_pos = parse->common.offset;
2374
2375 /* Search Tracks element */
2376 while (TRUE) {
2377 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
2378 GST_ELEMENT_CAST (parse), &id, &length, &needed);
2379 if (ret != GST_FLOW_OK)
2380 break;
2381
2382 if (id != GST_MATROSKA_ID_TRACKS) {
2383 /* we may be skipping large cluster here, so forego size check etc */
2384 /* ... but we can't skip undefined size; force error */
2385 if (length == G_MAXUINT64) {
2386 ret = gst_matroska_parse_check_read_size (parse, length);
2387 break;
2388 } else {
2389 parse->common.offset += needed;
2390 parse->offset += length;
2391 }
2392 continue;
2393 }
2394
2395 /* will lead to track parsing ... */
2396 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
2397 break;
2398 }
2399
2400 /* seek back */
2401 parse->offset = before_pos;
2402
2403 return ret;
2404 }
2405 #endif
2406
2407 #define GST_READ_CHECK(stmt) \
2408 G_STMT_START { \
2409 if (G_UNLIKELY ((ret = (stmt)) != GST_FLOW_OK)) { \
2410 if (ret == GST_FLOW_OVERFLOW) { \
2411 ret = GST_FLOW_OK; \
2412 } \
2413 goto read_error; \
2414 } \
2415 } G_STMT_END
2416
2417 static void
gst_matroska_parse_accumulate_streamheader(GstMatroskaParse * parse,GstBuffer * buffer)2418 gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse,
2419 GstBuffer * buffer)
2420 {
2421 if (parse->pushed_headers) {
2422 GST_WARNING_OBJECT (parse,
2423 "Accumulating headers, but headers are already pushed");
2424 }
2425
2426 if (parse->streamheader) {
2427 parse->streamheader = gst_buffer_append (parse->streamheader,
2428 gst_buffer_ref (buffer));
2429 } else {
2430 parse->streamheader = gst_buffer_ref (buffer);
2431 }
2432
2433 GST_DEBUG ("%" G_GSIZE_FORMAT, gst_buffer_get_size (parse->streamheader));
2434 }
2435
2436 static GstFlowReturn
gst_matroska_parse_output(GstMatroskaParse * parse,GstBuffer * buffer,gboolean keyframe)2437 gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
2438 gboolean keyframe)
2439 {
2440 GstFlowReturn ret;
2441
2442 if (!parse->pushed_headers) {
2443 GstCaps *caps;
2444 GstStructure *s;
2445 GValue streamheader = { 0 };
2446 GValue bufval = { 0 };
2447 GstBuffer *buf;
2448
2449 caps = gst_pad_get_current_caps (parse->common.sinkpad);
2450 if (caps == NULL) {
2451 caps = gst_matroska_parse_forge_caps (parse->common.is_webm,
2452 parse->common.has_video);
2453 } else
2454 caps = gst_caps_make_writable (caps);
2455
2456 s = gst_caps_get_structure (caps, 0);
2457 g_value_init (&streamheader, GST_TYPE_ARRAY);
2458 g_value_init (&bufval, GST_TYPE_BUFFER);
2459 buf = gst_buffer_copy (parse->streamheader);
2460 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
2461 gst_value_set_buffer (&bufval, buf);
2462 gst_buffer_unref (buf);
2463 gst_value_array_append_value (&streamheader, &bufval);
2464 g_value_unset (&bufval);
2465 gst_structure_set_value (s, "streamheader", &streamheader);
2466 g_value_unset (&streamheader);
2467 //gst_caps_replace (parse->caps, caps);
2468 gst_pad_set_caps (parse->srcpad, caps);
2469
2470 if (parse->need_newsegment) {
2471 gst_pad_push_event (parse->srcpad,
2472 gst_event_new_segment (&parse->common.segment));
2473 parse->need_newsegment = FALSE;
2474 }
2475
2476 buf = gst_buffer_copy (parse->streamheader);
2477 gst_caps_unref (caps);
2478
2479 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
2480 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
2481 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
2482
2483 ret = gst_pad_push (parse->srcpad, buf);
2484 if (ret != GST_FLOW_OK) {
2485 GST_WARNING_OBJECT (parse, "Failed to push buffer");
2486 return ret;
2487 }
2488
2489 parse->pushed_headers = TRUE;
2490 }
2491
2492 if (!keyframe) {
2493 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2494 } else {
2495 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2496 }
2497 if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE) {
2498 parse->last_timestamp = GST_BUFFER_TIMESTAMP (buffer);
2499 } else {
2500 GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp;
2501 }
2502
2503 return gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
2504 }
2505
2506 static GstFlowReturn
gst_matroska_parse_parse_id(GstMatroskaParse * parse,guint32 id,guint64 length,guint needed)2507 gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
2508 guint64 length, guint needed)
2509 {
2510 GstEbmlRead ebml = { 0, };
2511 GstFlowReturn ret = GST_FLOW_OK;
2512 guint64 read;
2513 //GstBuffer *buffer;
2514
2515 GST_DEBUG_OBJECT (parse, "Parsing Element id 0x%x, "
2516 "size %" G_GUINT64_FORMAT ", prefix %d", id, length, needed);
2517
2518 #if 0
2519 if (gst_adapter_available (parse->adapter) >= length + needed) {
2520 buffer = gst_adapter_take_buffer (parse->adapter, length + needed);
2521 gst_pad_push (parse->srcpad, buffer);
2522 } else {
2523 ret = GST_FLOW_EOS;
2524 }
2525 //GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2526
2527 return ret;
2528 #endif
2529
2530
2531
2532 /* if we plan to read and parse this element, we need prefix (id + length)
2533 * and the contents */
2534 /* mind about overflow wrap-around when dealing with undefined size */
2535 read = length;
2536 if (G_LIKELY (length != G_MAXUINT64))
2537 read += needed;
2538
2539 switch (parse->common.state) {
2540 case GST_MATROSKA_READ_STATE_START:
2541 switch (id) {
2542 case GST_EBML_ID_HEADER:
2543 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2544 ret = gst_matroska_read_common_parse_header (&parse->common, &ebml);
2545 if (ret != GST_FLOW_OK)
2546 goto parse_failed;
2547 parse->common.state = GST_MATROSKA_READ_STATE_SEGMENT;
2548 gst_matroska_parse_check_seekability (parse);
2549 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2550 break;
2551 default:
2552 goto invalid_header;
2553 break;
2554 }
2555 break;
2556 case GST_MATROSKA_READ_STATE_SEGMENT:
2557 switch (id) {
2558 case GST_MATROSKA_ID_SEGMENT:
2559 /* eat segment prefix */
2560 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
2561 GST_DEBUG_OBJECT (parse,
2562 "Found Segment start at offset %" G_GUINT64_FORMAT " with size %"
2563 G_GUINT64_FORMAT, parse->common.offset, length);
2564 /* seeks are from the beginning of the segment,
2565 * after the segment ID/length */
2566 parse->common.ebml_segment_start = parse->common.offset;
2567 if (length == 0)
2568 length = G_MAXUINT64;
2569 parse->common.ebml_segment_length = length;
2570 parse->common.state = GST_MATROSKA_READ_STATE_HEADER;
2571 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2572 break;
2573 default:
2574 GST_WARNING_OBJECT (parse,
2575 "Expected a Segment ID (0x%x), but received 0x%x!",
2576 GST_MATROSKA_ID_SEGMENT, id);
2577 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
2578 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2579 break;
2580 }
2581 break;
2582 case GST_MATROSKA_READ_STATE_SCANNING:
2583 if (id != GST_MATROSKA_ID_CLUSTER &&
2584 id != GST_MATROSKA_ID_CLUSTERTIMECODE) {
2585 /* we need to skip byte per byte if we are scanning for a new cluster */
2586 read = 1;
2587 goto skip;
2588 } else {
2589 GST_LOG_OBJECT (parse, "Resync done, new cluster found!");
2590 parse->common.start_resync_offset = -1;
2591 parse->common.state = parse->common.state_to_restore;
2592 }
2593 /* fall-through */
2594 case GST_MATROSKA_READ_STATE_HEADER:
2595 case GST_MATROSKA_READ_STATE_DATA:
2596 case GST_MATROSKA_READ_STATE_SEEK:
2597 switch (id) {
2598 case GST_MATROSKA_ID_SEGMENTINFO:
2599 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2600 if (!parse->common.segmentinfo_parsed) {
2601 ret = gst_matroska_read_common_parse_info (&parse->common,
2602 GST_ELEMENT_CAST (parse), &ebml);
2603 if (ret == GST_FLOW_OK)
2604 gst_matroska_parse_send_tags (parse);
2605 }
2606 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2607 break;
2608 case GST_MATROSKA_ID_TRACKS:
2609 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2610 if (!parse->tracks_parsed) {
2611 ret = gst_matroska_parse_parse_tracks (parse, &ebml);
2612 }
2613 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2614 break;
2615 case GST_MATROSKA_ID_CLUSTER:
2616 if (G_UNLIKELY (!parse->tracks_parsed)) {
2617 GST_DEBUG_OBJECT (parse, "Cluster before Track");
2618 goto not_streamable;
2619 }
2620 if (G_UNLIKELY (parse->common.state
2621 == GST_MATROSKA_READ_STATE_HEADER)) {
2622 parse->common.state = GST_MATROSKA_READ_STATE_DATA;
2623 parse->first_cluster_offset = parse->common.offset;
2624 GST_DEBUG_OBJECT (parse, "signaling no more pads");
2625 }
2626 parse->cluster_time = GST_CLOCK_TIME_NONE;
2627 parse->cluster_offset = parse->common.offset;
2628 if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
2629 GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
2630 " not found in Cluster, trying next Cluster's first block instead",
2631 parse->seek_block);
2632 parse->seek_block = 0;
2633 }
2634 parse->seek_first = FALSE;
2635 /* record next cluster for recovery */
2636 if (read != G_MAXUINT64)
2637 parse->next_cluster_offset = parse->cluster_offset + read;
2638 /* eat cluster prefix */
2639 GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
2640 ret = gst_matroska_parse_output (parse, ebml.buf, TRUE);
2641 //gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2642 break;
2643 case GST_MATROSKA_ID_CLUSTERTIMECODE:
2644 {
2645 guint64 num;
2646
2647 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2648 if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK)
2649 goto parse_failed;
2650 GST_DEBUG_OBJECT (parse, "ClusterTimeCode: %" G_GUINT64_FORMAT, num);
2651 parse->cluster_time = num;
2652 #if 0
2653 if (parse->common.element_index) {
2654 if (parse->common.element_index_writer_id == -1)
2655 gst_index_get_writer_id (parse->common.element_index,
2656 GST_OBJECT (parse), &parse->common.element_index_writer_id);
2657 GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2658 G_GUINT64_FORMAT " for writer id %d",
2659 GST_TIME_ARGS (parse->cluster_time), parse->cluster_offset,
2660 parse->common.element_index_writer_id);
2661 gst_index_add_association (parse->common.element_index,
2662 parse->common.element_index_writer_id,
2663 GST_ASSOCIATION_FLAG_KEY_UNIT,
2664 GST_FORMAT_TIME, parse->cluster_time,
2665 GST_FORMAT_BYTES, parse->cluster_offset, NULL);
2666 }
2667 #endif
2668 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2669 break;
2670 }
2671 case GST_MATROSKA_ID_BLOCKGROUP:
2672 if (!gst_matroska_parse_seek_block (parse))
2673 goto skip;
2674 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2675 DEBUG_ELEMENT_START (parse, &ebml, "BlockGroup");
2676 if ((ret = gst_ebml_read_master (&ebml, &id)) == GST_FLOW_OK) {
2677 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
2678 &ebml, parse->cluster_time, parse->cluster_offset, FALSE);
2679 }
2680 DEBUG_ELEMENT_STOP (parse, &ebml, "BlockGroup", ret);
2681 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2682 break;
2683 case GST_MATROSKA_ID_SIMPLEBLOCK:
2684 if (!gst_matroska_parse_seek_block (parse))
2685 goto skip;
2686 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2687 DEBUG_ELEMENT_START (parse, &ebml, "SimpleBlock");
2688 ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
2689 &ebml, parse->cluster_time, parse->cluster_offset, TRUE);
2690 DEBUG_ELEMENT_STOP (parse, &ebml, "SimpleBlock", ret);
2691 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2692 break;
2693 case GST_MATROSKA_ID_ATTACHMENTS:
2694 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2695 if (!parse->common.attachments_parsed) {
2696 ret = gst_matroska_read_common_parse_attachments (&parse->common,
2697 GST_ELEMENT_CAST (parse), &ebml);
2698 if (ret == GST_FLOW_OK)
2699 gst_matroska_parse_send_tags (parse);
2700 }
2701 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2702 break;
2703 case GST_MATROSKA_ID_TAGS:
2704 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2705 ret = gst_matroska_read_common_parse_metadata (&parse->common,
2706 GST_ELEMENT_CAST (parse), &ebml);
2707 if (ret == GST_FLOW_OK)
2708 gst_matroska_parse_send_tags (parse);
2709 gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
2710 break;
2711 case GST_MATROSKA_ID_CHAPTERS:
2712 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2713 ret = gst_matroska_read_common_parse_chapters (&parse->common, &ebml);
2714 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2715 break;
2716 case GST_MATROSKA_ID_SEEKHEAD:
2717 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2718 ret = gst_matroska_parse_parse_contents (parse, &ebml);
2719 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2720 break;
2721 case GST_MATROSKA_ID_CUES:
2722 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2723 if (!parse->common.index_parsed) {
2724 ret = gst_matroska_read_common_parse_index (&parse->common, &ebml);
2725 /* only push based; delayed index building */
2726 if (ret == GST_FLOW_OK
2727 && parse->common.state == GST_MATROSKA_READ_STATE_SEEK) {
2728 GstEvent *event;
2729
2730 GST_OBJECT_LOCK (parse);
2731 event = parse->seek_event;
2732 parse->seek_event = NULL;
2733 GST_OBJECT_UNLOCK (parse);
2734
2735 g_assert (event);
2736 /* unlikely to fail, since we managed to seek to this point */
2737 if (!gst_matroska_parse_handle_seek_event (parse, NULL, event))
2738 goto seek_failed;
2739 /* resume data handling, main thread clear to seek again */
2740 GST_OBJECT_LOCK (parse);
2741 parse->common.state = GST_MATROSKA_READ_STATE_DATA;
2742 GST_OBJECT_UNLOCK (parse);
2743 }
2744 }
2745 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2746 break;
2747 case GST_MATROSKA_ID_POSITION:
2748 case GST_MATROSKA_ID_PREVSIZE:
2749 case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
2750 case GST_MATROSKA_ID_SILENTTRACKS:
2751 GST_DEBUG_OBJECT (parse,
2752 "Skipping Cluster subelement 0x%x - ignoring", id);
2753 /* fall-through */
2754 default:
2755 skip:
2756 GST_DEBUG_OBJECT (parse, "skipping Element 0x%x", id);
2757 GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
2758 gst_matroska_parse_output (parse, ebml.buf, FALSE);
2759 break;
2760 }
2761 break;
2762 }
2763
2764 if (ret == GST_FLOW_PARSE)
2765 goto parse_failed;
2766
2767 exit:
2768 gst_ebml_read_clear (&ebml);
2769 return ret;
2770
2771 /* ERRORS */
2772 read_error:
2773 {
2774 /* simply exit, maybe not enough data yet */
2775 /* no ebml to clear if read error */
2776 return ret;
2777 }
2778 parse_failed:
2779 {
2780 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2781 ("Failed to parse Element 0x%x", id));
2782 ret = GST_FLOW_ERROR;
2783 goto exit;
2784 }
2785 not_streamable:
2786 {
2787 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2788 ("File layout does not permit streaming"));
2789 ret = GST_FLOW_ERROR;
2790 goto exit;
2791 }
2792 #if 0
2793 no_tracks:
2794 {
2795 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2796 ("No Tracks element found"));
2797 ret = GST_FLOW_ERROR;
2798 goto exit;
2799 }
2800 #endif
2801 invalid_header:
2802 {
2803 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Invalid header"));
2804 ret = GST_FLOW_ERROR;
2805 goto exit;
2806 }
2807 seek_failed:
2808 {
2809 GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Failed to seek"));
2810 ret = GST_FLOW_ERROR;
2811 goto exit;
2812 }
2813 }
2814
2815 #if 0
2816 static void
2817 gst_matroska_parse_loop (GstPad * pad)
2818 {
2819 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
2820 GstFlowReturn ret;
2821 guint32 id;
2822 guint64 length;
2823 guint needed;
2824
2825 /* If we have to close a segment, send a new segment to do this now */
2826 if (G_LIKELY (parse->common.state == GST_MATROSKA_READ_STATE_DATA)) {
2827 if (G_UNLIKELY (parse->close_segment)) {
2828 gst_matroska_parse_send_event (parse, parse->close_segment);
2829 parse->close_segment = NULL;
2830 }
2831 if (G_UNLIKELY (parse->new_segment)) {
2832 gst_matroska_parse_send_event (parse, parse->new_segment);
2833 parse->new_segment = NULL;
2834 }
2835 }
2836
2837 ret = gst_matroska_read_common_peek_id_length_pull (&parse->common,
2838 GST_ELEMENT_CAST (parse), &id, &length, &needed);
2839 if (ret == GST_FLOW_EOS)
2840 goto eos;
2841 if (ret != GST_FLOW_OK) {
2842 if (gst_matroska_parse_check_parse_error (parse))
2843 goto pause;
2844 else
2845 return;
2846 }
2847
2848 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
2849 "size %" G_GUINT64_FORMAT ", needed %d", parse->offset, id,
2850 length, needed);
2851
2852 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
2853 if (ret == GST_FLOW_EOS)
2854 goto eos;
2855 if (ret != GST_FLOW_OK)
2856 goto pause;
2857
2858 /* check if we're at the end of a configured segment */
2859 if (G_LIKELY (parse->src->len)) {
2860 guint i;
2861
2862 g_assert (parse->num_streams == parse->src->len);
2863 for (i = 0; i < parse->src->len; i++) {
2864 GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
2865 GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
2866 GST_TIME_ARGS (context->pos));
2867 if (context->eos == FALSE)
2868 goto next;
2869 }
2870
2871 GST_INFO_OBJECT (parse, "All streams are EOS");
2872 ret = GST_FLOW_EOS;
2873 goto eos;
2874 }
2875
2876 next:
2877 if (G_UNLIKELY (parse->offset ==
2878 gst_matroska_read_common_get_length (&parse->common))) {
2879 GST_LOG_OBJECT (parse, "Reached end of stream");
2880 ret = GST_FLOW_EOS;
2881 goto eos;
2882 }
2883
2884 return;
2885
2886 /* ERRORS */
2887 eos:
2888 {
2889 if (parse->segment.rate < 0.0) {
2890 ret = gst_matroska_parse_seek_to_previous_keyframe (parse);
2891 if (ret == GST_FLOW_OK)
2892 return;
2893 }
2894 /* fall-through */
2895 }
2896 pause:
2897 {
2898 const gchar *reason = gst_flow_get_name (ret);
2899 gboolean push_eos = FALSE;
2900
2901 GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
2902 parse->segment_running = FALSE;
2903 gst_pad_pause_task (parse->common.sinkpad);
2904
2905 if (ret == GST_FLOW_EOS) {
2906 /* perform EOS logic */
2907
2908 /* Close the segment, i.e. update segment stop with the duration
2909 * if no stop was set */
2910 if (GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) &&
2911 !GST_CLOCK_TIME_IS_VALID (parse->segment.stop)) {
2912 GstEvent *event =
2913 gst_event_new_new_segment_full (TRUE, parse->segment.rate,
2914 parse->segment.applied_rate, parse->segment.format,
2915 parse->segment.start,
2916 MAX (parse->last_stop_end, parse->segment.start),
2917 parse->segment.time);
2918 gst_matroska_parse_send_event (parse, event);
2919 }
2920
2921 if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2922 gint64 stop;
2923
2924 /* for segment playback we need to post when (in stream time)
2925 * we stopped, this is either stop (when set) or the duration. */
2926 if ((stop = parse->segment.stop) == -1)
2927 stop = parse->last_stop_end;
2928
2929 GST_LOG_OBJECT (parse, "Sending segment done, at end of segment");
2930 gst_element_post_message (GST_ELEMENT (parse),
2931 gst_message_new_segment_done (GST_OBJECT (parse), GST_FORMAT_TIME,
2932 stop));
2933 gst_matroska_parse_send_event (parse,
2934 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
2935 } else {
2936 push_eos = TRUE;
2937 }
2938 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2939 /* for fatal errors we post an error message */
2940 GST_ELEMENT_FLOW_ERROR (parse, ret);
2941 push_eos = TRUE;
2942 }
2943 if (push_eos) {
2944 /* send EOS, and prevent hanging if no streams yet */
2945 GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
2946 if (!gst_matroska_parse_send_event (parse, gst_event_new_eos ()) &&
2947 (ret == GST_FLOW_EOS)) {
2948 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
2949 (NULL), ("got eos but no streams (yet)"));
2950 }
2951 }
2952 return;
2953 }
2954 }
2955 #endif
2956
2957 /*
2958 * Create and push a flushing seek event upstream
2959 */
2960 static gboolean
perform_seek_to_offset(GstMatroskaParse * parse,guint64 offset)2961 perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
2962 {
2963 GstEvent *event;
2964 gboolean res = 0;
2965
2966 GST_DEBUG_OBJECT (parse, "Seeking to %" G_GUINT64_FORMAT, offset);
2967
2968 event =
2969 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
2970 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
2971 GST_SEEK_TYPE_NONE, -1);
2972
2973 res = gst_pad_push_event (parse->common.sinkpad, event);
2974
2975 /* newsegment event will update offset */
2976 return res;
2977 }
2978
2979 /*
2980 * Forge empty default caps when all we know is the stream's EBML
2981 * type and whether it has video or not.
2982 *
2983 * FIXME: Do something with video/x-matroska-3d if possible
2984 */
2985 static GstCaps *
gst_matroska_parse_forge_caps(gboolean is_webm,gboolean has_video)2986 gst_matroska_parse_forge_caps (gboolean is_webm, gboolean has_video)
2987 {
2988 GstCaps *caps;
2989
2990 if (is_webm) {
2991 if (has_video)
2992 caps = gst_caps_new_empty_simple ("video/webm");
2993 else
2994 caps = gst_caps_new_empty_simple ("audio/webm");
2995 } else {
2996 if (has_video)
2997 caps = gst_caps_new_empty_simple ("video/x-matroska");
2998 else
2999 caps = gst_caps_new_empty_simple ("audio/x-matroska");
3000 }
3001 return caps;
3002 }
3003
3004 static GstFlowReturn
gst_matroska_parse_chain(GstPad * pad,GstObject * parent,GstBuffer * buffer)3005 gst_matroska_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
3006 {
3007 GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
3008 guint available;
3009 GstFlowReturn ret = GST_FLOW_OK;
3010 guint needed = 0;
3011 guint32 id;
3012 guint64 length;
3013
3014 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buffer))) {
3015 GST_DEBUG_OBJECT (parse, "got DISCONT");
3016 gst_adapter_clear (parse->common.adapter);
3017 GST_OBJECT_LOCK (parse);
3018 gst_matroska_read_common_reset_streams (&parse->common,
3019 GST_CLOCK_TIME_NONE, FALSE);
3020 GST_OBJECT_UNLOCK (parse);
3021 }
3022
3023 gst_adapter_push (parse->common.adapter, buffer);
3024 buffer = NULL;
3025
3026 next:
3027 available = gst_adapter_available (parse->common.adapter);
3028
3029 ret = gst_matroska_read_common_peek_id_length_push (&parse->common,
3030 GST_ELEMENT_CAST (parse), &id, &length, &needed);
3031 if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)) {
3032 if (parse->common.ebml_segment_length != G_MAXUINT64
3033 && parse->common.offset >=
3034 parse->common.ebml_segment_start + parse->common.ebml_segment_length) {
3035 return GST_FLOW_EOS;
3036 } else {
3037 /*
3038 * parsing error: we need to flush a byte from the adapter if the id is
3039 * not a cluster and so on until we found a new cluser or the
3040 * INVALID_DATA_THRESHOLD is exceeded, we reuse gst_matroska_parse_parse_id
3041 * setting the state to GST_MATROSKA_READ_STATE_SCANNING so the bytes
3042 * are skipped until a new cluster is found
3043 */
3044 gint64 bytes_scanned;
3045 if (parse->common.start_resync_offset == -1) {
3046 parse->common.start_resync_offset = parse->common.offset;
3047 parse->common.state_to_restore = parse->common.state;
3048 }
3049 bytes_scanned = parse->common.offset - parse->common.start_resync_offset;
3050 if (bytes_scanned <= INVALID_DATA_THRESHOLD) {
3051 GST_WARNING_OBJECT (parse,
3052 "parse error, looking for next cluster, actual offset %"
3053 G_GUINT64_FORMAT ", start resync offset %" G_GUINT64_FORMAT,
3054 parse->common.offset, parse->common.start_resync_offset);
3055 parse->common.state = GST_MATROSKA_READ_STATE_SCANNING;
3056 ret = GST_FLOW_OK;
3057 } else {
3058 GST_WARNING_OBJECT (parse,
3059 "unrecoverable parse error, next cluster not found and threshold "
3060 "exceeded, bytes scanned %" G_GINT64_FORMAT, bytes_scanned);
3061 return ret;
3062 }
3063 }
3064 }
3065
3066 GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
3067 "size %" G_GUINT64_FORMAT ", needed %d, available %d",
3068 parse->common.offset, id, length, needed, available);
3069
3070 if (needed > available)
3071 return GST_FLOW_OK;
3072
3073 ret = gst_matroska_parse_parse_id (parse, id, length, needed);
3074 if (ret == GST_FLOW_EOS) {
3075 /* need more data */
3076 return GST_FLOW_OK;
3077 } else if (ret != GST_FLOW_OK) {
3078 return ret;
3079 } else
3080 goto next;
3081 }
3082
3083 static gboolean
gst_matroska_parse_handle_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)3084 gst_matroska_parse_handle_sink_event (GstPad * pad, GstObject * parent,
3085 GstEvent * event)
3086 {
3087 gboolean res = TRUE;
3088 GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
3089
3090 GST_DEBUG_OBJECT (parse,
3091 "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
3092
3093 switch (GST_EVENT_TYPE (event)) {
3094 case GST_EVENT_SEGMENT:
3095 {
3096 const GstSegment *segment;
3097
3098 /* some debug output */
3099 gst_event_parse_segment (event, &segment);
3100 GST_DEBUG_OBJECT (parse,
3101 "received format %d newsegment %" GST_SEGMENT_FORMAT,
3102 segment->format, segment);
3103
3104 if (parse->common.state < GST_MATROSKA_READ_STATE_DATA) {
3105 GST_DEBUG_OBJECT (parse, "still starting");
3106 goto exit;
3107 }
3108
3109 /* we only expect a BYTE segment, e.g. following a seek */
3110 if (segment->format != GST_FORMAT_BYTES) {
3111 GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
3112 goto exit;
3113 }
3114
3115 GST_DEBUG_OBJECT (parse, "clearing segment state");
3116 /* clear current segment leftover */
3117 gst_adapter_clear (parse->common.adapter);
3118 /* and some streaming setup */
3119 parse->common.offset = segment->start;
3120 /* do not know where we are;
3121 * need to come across a cluster and generate newsegment */
3122 parse->common.segment.position = GST_CLOCK_TIME_NONE;
3123 parse->cluster_time = GST_CLOCK_TIME_NONE;
3124 parse->cluster_offset = 0;
3125 parse->need_newsegment = TRUE;
3126 /* but keep some of the upstream segment */
3127 parse->common.segment.rate = segment->rate;
3128 exit:
3129 /* chain will send initial newsegment after pads have been added,
3130 * or otherwise come up with one */
3131 GST_DEBUG_OBJECT (parse, "eating event");
3132 gst_event_unref (event);
3133 res = TRUE;
3134 break;
3135 }
3136 case GST_EVENT_EOS:
3137 {
3138 if (parse->common.state != GST_MATROSKA_READ_STATE_DATA
3139 && parse->common.state != GST_MATROSKA_READ_STATE_SCANNING) {
3140 gst_event_unref (event);
3141 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
3142 (NULL), ("got eos and didn't receive a complete header object"));
3143 } else if (parse->common.num_streams == 0) {
3144 GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
3145 (NULL), ("got eos but no streams (yet)"));
3146 } else {
3147 gst_matroska_parse_send_event (parse, event);
3148 }
3149 break;
3150 }
3151 case GST_EVENT_FLUSH_STOP:
3152 {
3153 gst_adapter_clear (parse->common.adapter);
3154 GST_OBJECT_LOCK (parse);
3155 gst_matroska_read_common_reset_streams (&parse->common,
3156 GST_CLOCK_TIME_NONE, TRUE);
3157 GST_OBJECT_UNLOCK (parse);
3158 parse->common.segment.position = GST_CLOCK_TIME_NONE;
3159 parse->cluster_time = GST_CLOCK_TIME_NONE;
3160 parse->cluster_offset = 0;
3161 /* fall-through */
3162 }
3163 default:
3164 res = gst_pad_event_default (pad, parent, event);
3165 break;
3166 }
3167
3168 return res;
3169 }
3170
3171 #if 0
3172 static void
3173 gst_matroska_parse_set_index (GstElement * element, GstIndex * index)
3174 {
3175 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
3176
3177 GST_OBJECT_LOCK (parse);
3178 if (parse->common.element_index)
3179 gst_object_unref (parse->common.element_index);
3180 parse->common.element_index = index ? gst_object_ref (index) : NULL;
3181 GST_OBJECT_UNLOCK (parse);
3182 GST_DEBUG_OBJECT (parse, "Set index %" GST_PTR_FORMAT,
3183 parse->common.element_index);
3184 }
3185
3186 static GstIndex *
3187 gst_matroska_parse_get_index (GstElement * element)
3188 {
3189 GstIndex *result = NULL;
3190 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
3191
3192 GST_OBJECT_LOCK (parse);
3193 if (parse->common.element_index)
3194 result = gst_object_ref (parse->common.element_index);
3195 GST_OBJECT_UNLOCK (parse);
3196
3197 GST_DEBUG_OBJECT (parse, "Returning index %" GST_PTR_FORMAT, result);
3198
3199 return result;
3200 }
3201 #endif
3202
3203 static GstStateChangeReturn
gst_matroska_parse_change_state(GstElement * element,GstStateChange transition)3204 gst_matroska_parse_change_state (GstElement * element,
3205 GstStateChange transition)
3206 {
3207 GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
3208 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3209
3210 /* handle upwards state changes here */
3211 switch (transition) {
3212 default:
3213 break;
3214 }
3215
3216 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3217
3218 /* handle downwards state changes */
3219 switch (transition) {
3220 case GST_STATE_CHANGE_PAUSED_TO_READY:
3221 gst_matroska_parse_reset (GST_ELEMENT (parse));
3222 break;
3223 default:
3224 break;
3225 }
3226
3227 return ret;
3228 }
3229
3230 gboolean
gst_matroska_parse_plugin_init(GstPlugin * plugin)3231 gst_matroska_parse_plugin_init (GstPlugin * plugin)
3232 {
3233 gst_riff_init ();
3234
3235 /* create an elementfactory for the matroska_parse element */
3236 if (!gst_element_register (plugin, "matroskaparse",
3237 GST_RANK_NONE, GST_TYPE_MATROSKA_PARSE))
3238 return FALSE;
3239
3240 return TRUE;
3241 }
3242