1 /* GStreamer
2 * Copyright (C) 2008-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * SECTION:element-mxfdemux
22 * @title: mxfdemux
23 *
24 * mxfdemux demuxes an MXF file into the different contained streams.
25 *
26 * ## Example launch line
27 * |[
28 * gst-launch-1.0 -v filesrc location=/path/to/mxf ! mxfdemux ! audioconvert ! autoaudiosink
29 * ]| This pipeline demuxes an MXF file and outputs one of the contained raw audio streams.
30 *
31 */
32
33 /* TODO:
34 * - Handle timecode tracks correctly (where is this documented?)
35 * - Handle drop-frame field of timecode tracks
36 * - Handle Generic container system items
37 * - Implement correct support for clip-wrapped essence elements.
38 * - Post structural metadata and descriptive metadata trees as a message on the bus
39 * and send them downstream as event.
40 * - Multichannel audio needs channel layouts, define them (SMPTE S320M?).
41 * - Correctly handle the different rectangles and aspect-ratio for video
42 * - Add more support for non-standard MXF used by Avid (bug #561922).
43 * - Fix frame layout stuff, i.e. interlaced/progressive
44 * - In pull mode first find the first buffer for every pad before pushing
45 * to prevent jumpy playback in the beginning due to resynchronization.
46 *
47 * - Implement SMPTE D11 essence and the digital cinema/MXF specs
48 */
49
50 #ifdef HAVE_CONFIG_H
51 #include "config.h"
52 #endif
53
54 #include "mxfdemux.h"
55 #include "mxfessence.h"
56
57 #include <string.h>
58
59 static GstStaticPadTemplate mxf_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
60 GST_PAD_SINK,
61 GST_PAD_ALWAYS,
62 GST_STATIC_CAPS ("application/mxf")
63 );
64
65 static GstStaticPadTemplate mxf_src_template =
66 GST_STATIC_PAD_TEMPLATE ("track_%u",
67 GST_PAD_SRC,
68 GST_PAD_SOMETIMES,
69 GST_STATIC_CAPS_ANY);
70
71 GST_DEBUG_CATEGORY_STATIC (mxfdemux_debug);
72 #define GST_CAT_DEFAULT mxfdemux_debug
73
74 static GstFlowReturn
75 gst_mxf_demux_pull_klv_packet (GstMXFDemux * demux, guint64 offset, MXFUL * key,
76 GstBuffer ** outbuf, guint * read);
77 static GstFlowReturn
78 gst_mxf_demux_handle_index_table_segment (GstMXFDemux * demux,
79 const MXFUL * key, GstBuffer * buffer, guint64 offset);
80
81 static void collect_index_table_segments (GstMXFDemux * demux);
82
83 GType gst_mxf_demux_pad_get_type (void);
84 G_DEFINE_TYPE (GstMXFDemuxPad, gst_mxf_demux_pad, GST_TYPE_PAD);
85
86 static void
gst_mxf_demux_pad_finalize(GObject * object)87 gst_mxf_demux_pad_finalize (GObject * object)
88 {
89 GstMXFDemuxPad *pad = GST_MXF_DEMUX_PAD (object);
90
91 if (pad->tags) {
92 gst_tag_list_unref (pad->tags);
93 pad->tags = NULL;
94 }
95
96 G_OBJECT_CLASS (gst_mxf_demux_pad_parent_class)->finalize (object);
97 }
98
99 static void
gst_mxf_demux_pad_class_init(GstMXFDemuxPadClass * klass)100 gst_mxf_demux_pad_class_init (GstMXFDemuxPadClass * klass)
101 {
102 GObjectClass *gobject_class = (GObjectClass *) klass;
103
104 gobject_class->finalize = gst_mxf_demux_pad_finalize;
105 }
106
107 static void
gst_mxf_demux_pad_init(GstMXFDemuxPad * pad)108 gst_mxf_demux_pad_init (GstMXFDemuxPad * pad)
109 {
110 pad->position = 0;
111 pad->current_material_track_position = 0;
112 }
113
114 enum
115 {
116 PROP_0,
117 PROP_PACKAGE,
118 PROP_MAX_DRIFT,
119 PROP_STRUCTURE
120 };
121
122 static gboolean gst_mxf_demux_sink_event (GstPad * pad, GstObject * parent,
123 GstEvent * event);
124 static gboolean gst_mxf_demux_src_event (GstPad * pad, GstObject * parent,
125 GstEvent * event);
126 static gboolean gst_mxf_demux_src_query (GstPad * pad, GstObject * parent,
127 GstQuery * query);
128
129 #define gst_mxf_demux_parent_class parent_class
130 G_DEFINE_TYPE (GstMXFDemux, gst_mxf_demux, GST_TYPE_ELEMENT);
131
132 static void
gst_mxf_demux_remove_pad(GstMXFDemuxPad * pad,GstMXFDemux * demux)133 gst_mxf_demux_remove_pad (GstMXFDemuxPad * pad, GstMXFDemux * demux)
134 {
135 gst_flow_combiner_remove_pad (demux->flowcombiner, GST_PAD_CAST (pad));
136 gst_element_remove_pad (GST_ELEMENT (demux), GST_PAD_CAST (pad));
137 }
138
139 static void
gst_mxf_demux_remove_pads(GstMXFDemux * demux)140 gst_mxf_demux_remove_pads (GstMXFDemux * demux)
141 {
142 g_ptr_array_foreach (demux->src, (GFunc) gst_mxf_demux_remove_pad, demux);
143 g_ptr_array_foreach (demux->src, (GFunc) gst_object_unref, NULL);
144 g_ptr_array_set_size (demux->src, 0);
145 }
146
147 static void
gst_mxf_demux_partition_free(GstMXFDemuxPartition * partition)148 gst_mxf_demux_partition_free (GstMXFDemuxPartition * partition)
149 {
150 mxf_partition_pack_reset (&partition->partition);
151 mxf_primer_pack_reset (&partition->primer);
152
153 g_free (partition);
154 }
155
156 static void
gst_mxf_demux_reset_mxf_state(GstMXFDemux * demux)157 gst_mxf_demux_reset_mxf_state (GstMXFDemux * demux)
158 {
159 guint i;
160
161 GST_DEBUG_OBJECT (demux, "Resetting MXF state");
162
163 g_list_foreach (demux->partitions, (GFunc) gst_mxf_demux_partition_free,
164 NULL);
165 g_list_free (demux->partitions);
166 demux->partitions = NULL;
167
168 demux->current_partition = NULL;
169
170 for (i = 0; i < demux->essence_tracks->len; i++) {
171 GstMXFDemuxEssenceTrack *t =
172 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
173
174 if (t->offsets)
175 g_array_free (t->offsets, TRUE);
176
177 g_free (t->mapping_data);
178
179 if (t->tags)
180 gst_tag_list_unref (t->tags);
181
182 if (t->caps)
183 gst_caps_unref (t->caps);
184 }
185 g_array_set_size (demux->essence_tracks, 0);
186 }
187
188 static void
gst_mxf_demux_reset_linked_metadata(GstMXFDemux * demux)189 gst_mxf_demux_reset_linked_metadata (GstMXFDemux * demux)
190 {
191 guint i;
192
193 for (i = 0; i < demux->src->len; i++) {
194 GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i);
195
196 pad->material_track = NULL;
197 pad->material_package = NULL;
198 pad->current_component = NULL;
199 }
200
201 for (i = 0; i < demux->essence_tracks->len; i++) {
202 GstMXFDemuxEssenceTrack *track =
203 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
204
205 track->source_package = NULL;
206 track->source_track = NULL;
207 }
208
209 demux->current_package = NULL;
210 }
211
212 static void
gst_mxf_demux_reset_metadata(GstMXFDemux * demux)213 gst_mxf_demux_reset_metadata (GstMXFDemux * demux)
214 {
215 GST_DEBUG_OBJECT (demux, "Resetting metadata");
216
217 g_rw_lock_writer_lock (&demux->metadata_lock);
218
219 demux->update_metadata = TRUE;
220 demux->metadata_resolved = FALSE;
221
222 gst_mxf_demux_reset_linked_metadata (demux);
223
224 demux->preface = NULL;
225
226 if (demux->metadata) {
227 g_hash_table_destroy (demux->metadata);
228 }
229 demux->metadata = mxf_metadata_hash_table_new ();
230
231 if (demux->tags) {
232 gst_tag_list_unref (demux->tags);
233 demux->tags = NULL;
234 }
235
236 g_rw_lock_writer_unlock (&demux->metadata_lock);
237 }
238
239 static void
gst_mxf_demux_reset(GstMXFDemux * demux)240 gst_mxf_demux_reset (GstMXFDemux * demux)
241 {
242 GST_DEBUG_OBJECT (demux, "cleaning up MXF demuxer");
243
244 demux->flushing = FALSE;
245
246 demux->footer_partition_pack_offset = 0;
247 demux->offset = 0;
248
249 demux->pull_footer_metadata = TRUE;
250
251 demux->run_in = -1;
252
253 memset (&demux->current_package_uid, 0, sizeof (MXFUMID));
254
255 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
256
257 if (demux->close_seg_event) {
258 gst_event_unref (demux->close_seg_event);
259 demux->close_seg_event = NULL;
260 }
261
262 gst_adapter_clear (demux->adapter);
263
264 gst_mxf_demux_remove_pads (demux);
265
266 if (demux->random_index_pack) {
267 g_array_free (demux->random_index_pack, TRUE);
268 demux->random_index_pack = NULL;
269 }
270
271 if (demux->pending_index_table_segments) {
272 GList *l;
273
274 for (l = demux->pending_index_table_segments; l; l = l->next) {
275 MXFIndexTableSegment *s = l->data;
276 mxf_index_table_segment_reset (s);
277 g_free (s);
278 }
279 g_list_free (demux->pending_index_table_segments);
280 demux->pending_index_table_segments = NULL;
281 }
282
283 if (demux->index_tables) {
284 GList *l;
285
286 for (l = demux->index_tables; l; l = l->next) {
287 GstMXFDemuxIndexTable *t = l->data;
288 g_array_free (t->offsets, TRUE);
289 g_free (t);
290 }
291 g_list_free (demux->index_tables);
292 demux->index_tables = NULL;
293 }
294
295 demux->index_table_segments_collected = FALSE;
296
297 gst_mxf_demux_reset_mxf_state (demux);
298 gst_mxf_demux_reset_metadata (demux);
299
300 demux->have_group_id = FALSE;
301 demux->group_id = G_MAXUINT;
302 }
303
304 static GstFlowReturn
gst_mxf_demux_pull_range(GstMXFDemux * demux,guint64 offset,guint size,GstBuffer ** buffer)305 gst_mxf_demux_pull_range (GstMXFDemux * demux, guint64 offset,
306 guint size, GstBuffer ** buffer)
307 {
308 GstFlowReturn ret;
309
310 ret = gst_pad_pull_range (demux->sinkpad, offset, size, buffer);
311 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
312 GST_WARNING_OBJECT (demux,
313 "failed when pulling %u bytes from offset %" G_GUINT64_FORMAT ": %s",
314 size, offset, gst_flow_get_name (ret));
315 *buffer = NULL;
316 return ret;
317 }
318
319 if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
320 GST_WARNING_OBJECT (demux,
321 "partial pull got %" G_GSIZE_FORMAT " when expecting %u from offset %"
322 G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
323 gst_buffer_unref (*buffer);
324 ret = GST_FLOW_EOS;
325 *buffer = NULL;
326 return ret;
327 }
328
329 return ret;
330 }
331
332 static gboolean
gst_mxf_demux_push_src_event(GstMXFDemux * demux,GstEvent * event)333 gst_mxf_demux_push_src_event (GstMXFDemux * demux, GstEvent * event)
334 {
335 gboolean ret = TRUE;
336 guint i;
337
338 GST_DEBUG_OBJECT (demux, "Pushing '%s' event downstream",
339 GST_EVENT_TYPE_NAME (event));
340
341 for (i = 0; i < demux->src->len; i++) {
342 GstMXFDemuxPad *pad = GST_MXF_DEMUX_PAD (g_ptr_array_index (demux->src, i));
343
344 if (pad->eos && GST_EVENT_TYPE (event) == GST_EVENT_EOS)
345 continue;
346
347 ret |= gst_pad_push_event (GST_PAD_CAST (pad), gst_event_ref (event));
348 }
349
350 gst_event_unref (event);
351
352 return ret;
353 }
354
355 static GstMXFDemuxPad *
gst_mxf_demux_get_earliest_pad(GstMXFDemux * demux)356 gst_mxf_demux_get_earliest_pad (GstMXFDemux * demux)
357 {
358 guint i;
359 GstClockTime earliest = GST_CLOCK_TIME_NONE;
360 GstMXFDemuxPad *pad = NULL;
361
362 for (i = 0; i < demux->src->len; i++) {
363 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
364
365 if (!p->eos && p->position < earliest) {
366 earliest = p->position;
367 pad = p;
368 }
369 }
370
371 return pad;
372 }
373
374 static gint
gst_mxf_demux_partition_compare(GstMXFDemuxPartition * a,GstMXFDemuxPartition * b)375 gst_mxf_demux_partition_compare (GstMXFDemuxPartition * a,
376 GstMXFDemuxPartition * b)
377 {
378 if (a->partition.this_partition < b->partition.this_partition)
379 return -1;
380 else if (a->partition.this_partition > b->partition.this_partition)
381 return 1;
382 else
383 return 0;
384 }
385
386 static GstFlowReturn
gst_mxf_demux_handle_partition_pack(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer)387 gst_mxf_demux_handle_partition_pack (GstMXFDemux * demux, const MXFUL * key,
388 GstBuffer * buffer)
389 {
390 MXFPartitionPack partition;
391 GList *l;
392 GstMXFDemuxPartition *p = NULL;
393 GstMapInfo map;
394 gboolean ret;
395
396 GST_DEBUG_OBJECT (demux,
397 "Handling partition pack of size %" G_GSIZE_FORMAT " at offset %"
398 G_GUINT64_FORMAT, gst_buffer_get_size (buffer), demux->offset);
399
400 for (l = demux->partitions; l; l = l->next) {
401 GstMXFDemuxPartition *tmp = l->data;
402
403 if (tmp->partition.this_partition + demux->run_in == demux->offset &&
404 tmp->partition.major_version == 0x0001) {
405 GST_DEBUG_OBJECT (demux, "Partition already parsed");
406 p = tmp;
407 goto out;
408 }
409 }
410
411
412 gst_buffer_map (buffer, &map, GST_MAP_READ);
413 ret = mxf_partition_pack_parse (key, &partition, map.data, map.size);
414 gst_buffer_unmap (buffer, &map);
415 if (!ret) {
416 GST_ERROR_OBJECT (demux, "Parsing partition pack failed");
417 return GST_FLOW_ERROR;
418 }
419
420 if (partition.this_partition != demux->offset + demux->run_in) {
421 GST_WARNING_OBJECT (demux, "Partition with incorrect offset");
422 partition.this_partition = demux->offset + demux->run_in;
423 }
424
425 if (partition.type == MXF_PARTITION_PACK_HEADER)
426 demux->footer_partition_pack_offset = partition.footer_partition;
427
428 for (l = demux->partitions; l; l = l->next) {
429 GstMXFDemuxPartition *tmp = l->data;
430
431 if (tmp->partition.this_partition + demux->run_in == demux->offset) {
432 p = tmp;
433 break;
434 }
435 }
436
437 if (p) {
438 mxf_partition_pack_reset (&p->partition);
439 memcpy (&p->partition, &partition, sizeof (MXFPartitionPack));
440 } else {
441 p = g_new0 (GstMXFDemuxPartition, 1);
442 memcpy (&p->partition, &partition, sizeof (MXFPartitionPack));
443 demux->partitions =
444 g_list_insert_sorted (demux->partitions, p,
445 (GCompareFunc) gst_mxf_demux_partition_compare);
446 }
447
448 for (l = demux->partitions; l; l = l->next) {
449 GstMXFDemuxPartition *a, *b;
450
451 if (l->next == NULL)
452 break;
453
454 a = l->data;
455 b = l->next->data;
456
457 b->partition.prev_partition = a->partition.this_partition;
458 }
459
460 out:
461 demux->current_partition = p;
462
463 return GST_FLOW_OK;
464 }
465
466 static GstFlowReturn
gst_mxf_demux_handle_primer_pack(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer)467 gst_mxf_demux_handle_primer_pack (GstMXFDemux * demux, const MXFUL * key,
468 GstBuffer * buffer)
469 {
470 GstMapInfo map;
471 gboolean ret;
472
473 GST_DEBUG_OBJECT (demux,
474 "Handling primer pack of size %" G_GSIZE_FORMAT " at offset %"
475 G_GUINT64_FORMAT, gst_buffer_get_size (buffer), demux->offset);
476
477 if (G_UNLIKELY (!demux->current_partition)) {
478 GST_ERROR_OBJECT (demux, "Primer pack before partition pack");
479 return GST_FLOW_ERROR;
480 }
481
482 if (G_UNLIKELY (demux->current_partition->primer.mappings)) {
483 GST_DEBUG_OBJECT (demux, "Primer pack already exists");
484 return GST_FLOW_OK;
485 }
486
487 gst_buffer_map (buffer, &map, GST_MAP_READ);
488 ret = mxf_primer_pack_parse (key, &demux->current_partition->primer,
489 map.data, map.size);
490 gst_buffer_unmap (buffer, &map);
491 if (!ret) {
492 GST_ERROR_OBJECT (demux, "Parsing primer pack failed");
493 return GST_FLOW_ERROR;
494 }
495
496 demux->current_partition->primer.offset = demux->offset;
497
498 return GST_FLOW_OK;
499 }
500
501 static GstFlowReturn
gst_mxf_demux_resolve_references(GstMXFDemux * demux)502 gst_mxf_demux_resolve_references (GstMXFDemux * demux)
503 {
504 GstFlowReturn ret = GST_FLOW_OK;
505 GHashTableIter iter;
506 MXFMetadataBase *m = NULL;
507 GstStructure *structure;
508
509 g_rw_lock_writer_lock (&demux->metadata_lock);
510
511 GST_DEBUG_OBJECT (demux, "Resolve metadata references");
512 demux->update_metadata = FALSE;
513
514 if (!demux->metadata) {
515 GST_ERROR_OBJECT (demux, "No metadata yet");
516 g_rw_lock_writer_unlock (&demux->metadata_lock);
517 return GST_FLOW_ERROR;
518 }
519
520 g_hash_table_iter_init (&iter, demux->metadata);
521 while (g_hash_table_iter_next (&iter, NULL, (gpointer) & m)) {
522 m->resolved = MXF_METADATA_BASE_RESOLVE_STATE_NONE;
523 }
524
525 g_hash_table_iter_init (&iter, demux->metadata);
526 while (g_hash_table_iter_next (&iter, NULL, (gpointer) & m)) {
527 gboolean resolved;
528
529 resolved = mxf_metadata_base_resolve (m, demux->metadata);
530
531 /* Resolving can fail for anything but the preface, as the preface
532 * will resolve everything required */
533 if (!resolved && MXF_IS_METADATA_PREFACE (m)) {
534 ret = GST_FLOW_ERROR;
535 goto error;
536 }
537 }
538
539 demux->metadata_resolved = TRUE;
540
541 structure =
542 mxf_metadata_base_to_structure (MXF_METADATA_BASE (demux->preface));
543 if (!demux->tags)
544 demux->tags = gst_tag_list_new_empty ();
545
546 gst_tag_list_add (demux->tags, GST_TAG_MERGE_REPLACE, GST_TAG_MXF_STRUCTURE,
547 structure, NULL);
548
549 gst_structure_free (structure);
550
551 g_rw_lock_writer_unlock (&demux->metadata_lock);
552
553 return ret;
554
555 error:
556 demux->metadata_resolved = FALSE;
557 g_rw_lock_writer_unlock (&demux->metadata_lock);
558
559 return ret;
560 }
561
562 static MXFMetadataGenericPackage *
gst_mxf_demux_find_package(GstMXFDemux * demux,const MXFUMID * umid)563 gst_mxf_demux_find_package (GstMXFDemux * demux, const MXFUMID * umid)
564 {
565 MXFMetadataGenericPackage *ret = NULL;
566 guint i;
567
568 if (demux->preface->content_storage
569 && demux->preface->content_storage->packages) {
570 for (i = 0; i < demux->preface->content_storage->n_packages; i++) {
571 MXFMetadataGenericPackage *p =
572 demux->preface->content_storage->packages[i];
573
574 if (!p)
575 continue;
576
577 if (mxf_umid_is_equal (&p->package_uid, umid)) {
578 ret = p;
579 break;
580 }
581 }
582 }
583
584 return ret;
585 }
586
587 static MXFMetadataGenericPackage *
gst_mxf_demux_choose_package(GstMXFDemux * demux)588 gst_mxf_demux_choose_package (GstMXFDemux * demux)
589 {
590 MXFMetadataGenericPackage *ret = NULL;
591 guint i;
592
593 if (demux->requested_package_string) {
594 MXFUMID umid = { {0,}
595 };
596
597 if (!mxf_umid_from_string (demux->requested_package_string, &umid)) {
598 GST_ERROR_OBJECT (demux, "Invalid requested package");
599 }
600 g_free (demux->requested_package_string);
601 demux->requested_package_string = NULL;
602
603 ret = gst_mxf_demux_find_package (demux, &umid);
604 }
605
606 if (!ret && !mxf_umid_is_zero (&demux->current_package_uid))
607 ret = gst_mxf_demux_find_package (demux, &demux->current_package_uid);
608
609 if (ret && (MXF_IS_METADATA_MATERIAL_PACKAGE (ret)
610 || (MXF_IS_METADATA_SOURCE_PACKAGE (ret)
611 && MXF_METADATA_SOURCE_PACKAGE (ret)->top_level)))
612 goto done;
613 else if (ret)
614 GST_WARNING_OBJECT (demux,
615 "Current package is not a material package or top-level source package, choosing the first best");
616 else if (!mxf_umid_is_zero (&demux->current_package_uid))
617 GST_WARNING_OBJECT (demux,
618 "Current package not found, choosing the first best");
619
620 ret = demux->preface->primary_package;
621 if (ret && (MXF_IS_METADATA_MATERIAL_PACKAGE (ret)
622 || (MXF_IS_METADATA_SOURCE_PACKAGE (ret)
623 && MXF_METADATA_SOURCE_PACKAGE (ret)->top_level)))
624 goto done;
625 ret = NULL;
626
627 for (i = 0; i < demux->preface->content_storage->n_packages; i++) {
628 if (demux->preface->content_storage->packages[i] &&
629 MXF_IS_METADATA_MATERIAL_PACKAGE (demux->preface->content_storage->
630 packages[i])) {
631 ret =
632 MXF_METADATA_GENERIC_PACKAGE (demux->preface->content_storage->
633 packages[i]);
634 break;
635 }
636 }
637
638 if (!ret) {
639 GST_ERROR_OBJECT (demux, "No material package");
640 return NULL;
641 }
642
643 done:
644 if (mxf_umid_is_equal (&ret->package_uid, &demux->current_package_uid)) {
645 gchar current_package_string[96];
646
647 gst_mxf_demux_remove_pads (demux);
648 memcpy (&demux->current_package_uid, &ret->package_uid, 32);
649
650 mxf_umid_to_string (&ret->package_uid, current_package_string);
651 demux->current_package_string = g_strdup (current_package_string);
652 g_object_notify (G_OBJECT (demux), "package");
653
654 if (!demux->tags)
655 demux->tags = gst_tag_list_new_empty ();
656 gst_tag_list_add (demux->tags, GST_TAG_MERGE_REPLACE, GST_TAG_MXF_UMID,
657 demux->current_package_string, NULL);
658 }
659 demux->current_package = ret;
660
661 return ret;
662 }
663
664 static GstFlowReturn
gst_mxf_demux_update_essence_tracks(GstMXFDemux * demux)665 gst_mxf_demux_update_essence_tracks (GstMXFDemux * demux)
666 {
667 guint i, j, k;
668
669 g_return_val_if_fail (demux->preface->content_storage, GST_FLOW_ERROR);
670 g_return_val_if_fail (demux->preface->content_storage->essence_container_data,
671 GST_FLOW_ERROR);
672
673 for (i = 0; i < demux->preface->content_storage->n_essence_container_data;
674 i++) {
675 MXFMetadataEssenceContainerData *edata;
676 MXFMetadataSourcePackage *package;
677
678 if (demux->preface->content_storage->essence_container_data[i] == NULL)
679 continue;
680
681 edata = demux->preface->content_storage->essence_container_data[i];
682
683 if (!edata->linked_package) {
684 GST_WARNING_OBJECT (demux, "Linked package not resolved");
685 continue;
686 }
687
688 package = edata->linked_package;
689
690 if (!package->parent.tracks) {
691 GST_WARNING_OBJECT (demux, "Linked package with no resolved tracks");
692 continue;
693 }
694
695 for (j = 0; j < package->parent.n_tracks; j++) {
696 MXFMetadataTimelineTrack *track;
697 GstMXFDemuxEssenceTrack *etrack = NULL;
698 GstCaps *caps = NULL;
699 gboolean new = FALSE;
700
701 if (!package->parent.tracks[j]
702 || !MXF_IS_METADATA_TIMELINE_TRACK (package->parent.tracks[j]))
703 continue;
704
705 track = MXF_METADATA_TIMELINE_TRACK (package->parent.tracks[j]);
706 if ((track->parent.type & 0xf0) != 0x30)
707 continue;
708
709 if (track->edit_rate.n <= 0 || track->edit_rate.d <= 0) {
710 GST_WARNING_OBJECT (demux, "Invalid edit rate");
711 continue;
712 }
713
714 for (k = 0; k < demux->essence_tracks->len; k++) {
715 GstMXFDemuxEssenceTrack *tmp =
716 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack,
717 k);
718
719 if (tmp->track_number == track->parent.track_number &&
720 tmp->body_sid == edata->body_sid) {
721 if (tmp->track_id != track->parent.track_id ||
722 !mxf_umid_is_equal (&tmp->source_package_uid,
723 &package->parent.package_uid)) {
724 GST_ERROR_OBJECT (demux, "There already exists a different track "
725 "with this track number and body sid but a different source "
726 "or source track id -- ignoring");
727 continue;
728 }
729 etrack = tmp;
730 break;
731 }
732 }
733
734 if (!etrack) {
735 GstMXFDemuxEssenceTrack tmp;
736
737 memset (&tmp, 0, sizeof (tmp));
738 tmp.body_sid = edata->body_sid;
739 tmp.index_sid = edata->index_sid;
740 tmp.track_number = track->parent.track_number;
741 tmp.track_id = track->parent.track_id;
742 memcpy (&tmp.source_package_uid, &package->parent.package_uid, 32);
743
744 if (demux->current_partition->partition.body_sid == edata->body_sid &&
745 demux->current_partition->partition.body_offset == 0)
746 tmp.position = 0;
747 else
748 tmp.position = -1;
749
750 g_array_append_val (demux->essence_tracks, tmp);
751 etrack =
752 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack,
753 demux->essence_tracks->len - 1);
754 new = TRUE;
755 }
756
757 etrack->source_package = NULL;
758 etrack->source_track = NULL;
759
760 if (!track->parent.sequence) {
761 GST_WARNING_OBJECT (demux, "Source track has no sequence");
762 goto next;
763 }
764
765 if (track->parent.n_descriptor == 0) {
766 GST_WARNING_OBJECT (demux, "Source track has no descriptors");
767 goto next;
768 }
769
770 if (track->parent.sequence->duration > etrack->duration)
771 etrack->duration = track->parent.sequence->duration;
772
773 g_free (etrack->mapping_data);
774 etrack->mapping_data = NULL;
775 etrack->handler = NULL;
776 etrack->handle_func = NULL;
777 if (etrack->tags)
778 gst_tag_list_unref (etrack->tags);
779 etrack->tags = NULL;
780
781 etrack->handler = mxf_essence_element_handler_find (track);
782 if (!etrack->handler) {
783 gchar essence_container[48];
784 gchar essence_compression[48];
785 gchar *name;
786
787 GST_WARNING_OBJECT (demux,
788 "No essence element handler for track %u found", i);
789
790 mxf_ul_to_string (&track->parent.descriptor[0]->essence_container,
791 essence_container);
792
793 if (track->parent.type == MXF_METADATA_TRACK_PICTURE_ESSENCE) {
794 if (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (track->parent.
795 descriptor[0]))
796 mxf_ul_to_string (&MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR
797 (track->parent.descriptor[0])->picture_essence_coding,
798 essence_compression);
799
800 name =
801 g_strdup_printf ("video/x-mxf-%s-%s", essence_container,
802 essence_compression);
803 } else if (track->parent.type == MXF_METADATA_TRACK_SOUND_ESSENCE) {
804 if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->parent.
805 descriptor[0]))
806 mxf_ul_to_string (&MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR
807 (track->parent.descriptor[0])->sound_essence_compression,
808 essence_compression);
809
810 name =
811 g_strdup_printf ("audio/x-mxf-%s-%s", essence_container,
812 essence_compression);
813 } else if (track->parent.type == MXF_METADATA_TRACK_DATA_ESSENCE) {
814 if (MXF_IS_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (track->parent.
815 descriptor[0]))
816 mxf_ul_to_string (&MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR
817 (track->parent.descriptor[0])->data_essence_coding,
818 essence_compression);
819
820 name =
821 g_strdup_printf ("application/x-mxf-%s-%s", essence_container,
822 essence_compression);
823 } else {
824 name = NULL;
825 g_assert_not_reached ();
826 }
827
828 caps = gst_caps_new_empty_simple (name);
829 g_free (name);
830 etrack->intra_only = FALSE;
831 } else {
832 caps =
833 etrack->handler->create_caps (track, &etrack->tags,
834 &etrack->intra_only, &etrack->handle_func, &etrack->mapping_data);
835 }
836
837 GST_DEBUG_OBJECT (demux, "Created caps %" GST_PTR_FORMAT, caps);
838
839 if (!caps && new) {
840 GST_WARNING_OBJECT (demux, "No caps created, ignoring stream");
841 g_free (etrack->mapping_data);
842 etrack->mapping_data = NULL;
843 if (etrack->tags)
844 gst_tag_list_unref (etrack->tags);
845 etrack->tags = NULL;
846 goto next;
847 } else if (!caps) {
848 GST_WARNING_OBJECT (demux, "Couldn't create updated caps for stream");
849 } else if (!etrack->caps || !gst_caps_is_equal (etrack->caps, caps)) {
850 if (etrack->caps)
851 gst_caps_unref (etrack->caps);
852 etrack->caps = caps;
853 } else {
854 gst_caps_unref (caps);
855 caps = NULL;
856 }
857
858 if (etrack->handler != NULL) {
859 MXFEssenceWrapping track_wrapping;
860
861 track_wrapping = etrack->handler->get_track_wrapping (track);
862 if (track_wrapping == MXF_ESSENCE_WRAPPING_CLIP_WRAPPING) {
863 GST_ELEMENT_ERROR (demux, STREAM, NOT_IMPLEMENTED, (NULL),
864 ("Clip essence wrapping is not implemented yet."));
865 return GST_FLOW_ERROR;
866 } else if (track_wrapping == MXF_ESSENCE_WRAPPING_CUSTOM_WRAPPING) {
867 GST_ELEMENT_ERROR (demux, STREAM, NOT_IMPLEMENTED, (NULL),
868 ("Custom essence wrappings are not supported."));
869 return GST_FLOW_ERROR;
870 }
871 }
872
873 etrack->source_package = package;
874 etrack->source_track = track;
875 continue;
876
877 next:
878 if (new) {
879 g_free (etrack->mapping_data);
880 if (etrack->tags)
881 gst_tag_list_unref (etrack->tags);
882 if (etrack->caps)
883 gst_caps_unref (etrack->caps);
884
885 g_array_remove_index (demux->essence_tracks,
886 demux->essence_tracks->len - 1);
887 }
888 }
889 }
890
891 if (demux->essence_tracks->len == 0) {
892 GST_ERROR_OBJECT (demux, "No valid essence tracks in this file");
893 return GST_FLOW_ERROR;
894 }
895
896 for (i = 0; i < demux->essence_tracks->len; i++) {
897 GstMXFDemuxEssenceTrack *etrack =
898 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
899
900 if (!etrack->source_package || !etrack->source_track || !etrack->caps) {
901 GST_ERROR_OBJECT (demux, "Failed to update essence track %u", i);
902 return GST_FLOW_ERROR;
903 }
904
905 }
906
907 return GST_FLOW_OK;
908 }
909
910 static GstFlowReturn
gst_mxf_demux_update_tracks(GstMXFDemux * demux)911 gst_mxf_demux_update_tracks (GstMXFDemux * demux)
912 {
913 MXFMetadataGenericPackage *current_package = NULL;
914 guint i, j, k;
915 gboolean first_run;
916 guint component_index;
917 GstFlowReturn ret;
918 GList *pads = NULL, *l;
919 GstVideoTimeCode start_timecode = GST_VIDEO_TIME_CODE_INIT;
920
921 g_rw_lock_writer_lock (&demux->metadata_lock);
922 GST_DEBUG_OBJECT (demux, "Updating tracks");
923
924 if ((ret = gst_mxf_demux_update_essence_tracks (demux)) != GST_FLOW_OK) {
925 goto error;
926 }
927
928 current_package = gst_mxf_demux_choose_package (demux);
929
930 if (!current_package) {
931 GST_ERROR_OBJECT (demux, "Unable to find current package");
932 ret = GST_FLOW_ERROR;
933 goto error;
934 } else if (!current_package->tracks) {
935 GST_ERROR_OBJECT (demux, "Current package has no (resolved) tracks");
936 ret = GST_FLOW_ERROR;
937 goto error;
938 } else if (!current_package->n_essence_tracks) {
939 GST_ERROR_OBJECT (demux, "Current package has no essence tracks");
940 ret = GST_FLOW_ERROR;
941 goto error;
942 }
943
944 first_run = (demux->src->len == 0);
945
946 /* For material packages, there must be one timecode track with one
947 * continuous timecode. For source packages there might be multiple,
948 * discontinuous timecode components.
949 * TODO: Support multiple timecode components
950 */
951 for (i = 0; i < current_package->n_tracks; i++) {
952 MXFMetadataTimelineTrack *track = NULL;
953 MXFMetadataSequence *sequence = NULL;
954 MXFMetadataTimecodeComponent *component = NULL;
955
956 if (!current_package->tracks[i]) {
957 GST_WARNING_OBJECT (demux, "Unresolved track");
958 continue;
959 }
960
961 if (!MXF_IS_METADATA_TIMELINE_TRACK (current_package->tracks[i])) {
962 GST_DEBUG_OBJECT (demux, "No timeline track");
963 continue;
964 }
965
966
967 track = MXF_METADATA_TIMELINE_TRACK (current_package->tracks[i]);
968
969 if (!track->parent.sequence)
970 continue;
971 sequence = track->parent.sequence;
972 if (sequence->n_structural_components != 1 ||
973 !sequence->structural_components[0]
974 ||
975 !MXF_IS_METADATA_TIMECODE_COMPONENT (sequence->structural_components
976 [0]))
977 continue;
978
979 component =
980 MXF_METADATA_TIMECODE_COMPONENT (sequence->structural_components[0]);
981
982 /* Not a timecode track */
983 if (track->parent.type && (track->parent.type & 0xf0) != 0x10)
984 continue;
985
986 /* Main timecode track must have id 1, all others must be 0 */
987 if (track->parent.track_id != 1)
988 continue;
989
990 gst_video_time_code_init (&start_timecode, track->edit_rate.n,
991 track->edit_rate.d, NULL, (component->drop_frame
992 ?
993 GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME
994 : GST_VIDEO_TIME_CODE_FLAGS_NONE), 0, 0, 0, 0, 0);
995 gst_video_time_code_add_frames (&start_timecode, track->origin);
996 gst_video_time_code_add_frames (&start_timecode, component->start_timecode);
997 break;
998 }
999
1000 for (i = 0; i < current_package->n_tracks; i++) {
1001 MXFMetadataTimelineTrack *track = NULL;
1002 MXFMetadataSequence *sequence;
1003 MXFMetadataSourceClip *component = NULL;
1004 MXFMetadataSourcePackage *source_package = NULL;
1005 MXFMetadataTimelineTrack *source_track = NULL;
1006 GstMXFDemuxEssenceTrack *etrack = NULL;
1007 GstMXFDemuxPad *pad = NULL;
1008 GstCaps *pad_caps;
1009
1010 GST_DEBUG_OBJECT (demux, "Handling track %u", i);
1011
1012 if (!current_package->tracks[i]) {
1013 GST_WARNING_OBJECT (demux, "Unresolved track");
1014 continue;
1015 }
1016
1017 if (!MXF_IS_METADATA_TIMELINE_TRACK (current_package->tracks[i])) {
1018 GST_DEBUG_OBJECT (demux, "No timeline track");
1019 continue;
1020 }
1021
1022 track = MXF_METADATA_TIMELINE_TRACK (current_package->tracks[i]);
1023
1024 if (!first_run) {
1025 /* Find pad from track_id */
1026 for (j = 0; j < demux->src->len; j++) {
1027 GstMXFDemuxPad *tmp = g_ptr_array_index (demux->src, j);
1028
1029 if (tmp->track_id == track->parent.track_id) {
1030 pad = tmp;
1031 break;
1032 }
1033 }
1034 }
1035
1036 if (pad)
1037 component_index = pad->current_component_index;
1038 else
1039 component_index = 0;
1040
1041 if (!track->parent.sequence) {
1042 GST_WARNING_OBJECT (demux, "Track with no sequence");
1043 if (!pad) {
1044 continue;
1045 } else {
1046 ret = GST_FLOW_ERROR;
1047 goto error;
1048 }
1049 }
1050
1051 sequence = track->parent.sequence;
1052
1053 if (MXF_IS_METADATA_SOURCE_PACKAGE (current_package)) {
1054 GST_DEBUG_OBJECT (demux, "Playing source package");
1055
1056 component = NULL;
1057 source_package = MXF_METADATA_SOURCE_PACKAGE (current_package);
1058 source_track = track;
1059 } else if (sequence->structural_components
1060 &&
1061 MXF_IS_METADATA_SOURCE_CLIP (sequence->structural_components
1062 [component_index])) {
1063 GST_DEBUG_OBJECT (demux, "Playing material package");
1064
1065 component =
1066 MXF_METADATA_SOURCE_CLIP (sequence->structural_components
1067 [component_index]);
1068 if (!component) {
1069 GST_WARNING_OBJECT (demux, "NULL component in non-source package");
1070 if (!pad) {
1071 continue;
1072 } else {
1073 ret = GST_FLOW_ERROR;
1074 goto error;
1075 }
1076 }
1077
1078 if (component->source_package && component->source_package->top_level &&
1079 MXF_METADATA_GENERIC_PACKAGE (component->source_package)->tracks) {
1080 MXFMetadataGenericPackage *tmp_pkg =
1081 MXF_METADATA_GENERIC_PACKAGE (component->source_package);
1082
1083 source_package = component->source_package;
1084
1085 for (k = 0; k < tmp_pkg->n_tracks; k++) {
1086 MXFMetadataTrack *tmp = tmp_pkg->tracks[k];
1087
1088 if (tmp->track_id == component->source_track_id) {
1089 source_track = MXF_METADATA_TIMELINE_TRACK (tmp);
1090 break;
1091 }
1092 }
1093 }
1094 }
1095
1096 if (track->parent.type && (track->parent.type & 0xf0) != 0x30) {
1097 GST_DEBUG_OBJECT (demux, "No essence track");
1098 if (!pad) {
1099 continue;
1100 } else {
1101 ret = GST_FLOW_ERROR;
1102 goto error;
1103 }
1104 }
1105
1106 if (!source_package || track->parent.type == MXF_METADATA_TRACK_UNKNOWN
1107 || !source_track) {
1108 GST_WARNING_OBJECT (demux,
1109 "No source package or track type for track found");
1110 if (!pad) {
1111 continue;
1112 } else {
1113 ret = GST_FLOW_ERROR;
1114 goto error;
1115 }
1116 }
1117
1118 for (k = 0; k < demux->essence_tracks->len; k++) {
1119 GstMXFDemuxEssenceTrack *tmp =
1120 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, k);
1121
1122 if (tmp->source_package == source_package &&
1123 tmp->source_track == source_track) {
1124 etrack = tmp;
1125 break;
1126 }
1127 }
1128
1129 if (!etrack) {
1130 GST_WARNING_OBJECT (demux, "No essence track for this track found");
1131 if (!pad) {
1132 continue;
1133 } else {
1134 ret = GST_FLOW_ERROR;
1135 goto error;
1136 }
1137 }
1138
1139 if (track->edit_rate.n <= 0 || track->edit_rate.d <= 0 ||
1140 source_track->edit_rate.n <= 0 || source_track->edit_rate.d <= 0) {
1141 GST_WARNING_OBJECT (demux, "Track has an invalid edit rate");
1142 if (!pad) {
1143 continue;
1144 } else {
1145 ret = GST_FLOW_ERROR;
1146 goto error;
1147 }
1148 }
1149
1150 if (MXF_IS_METADATA_MATERIAL_PACKAGE (current_package) && !component) {
1151 GST_WARNING_OBJECT (demux,
1152 "Playing material package but found no component for track");
1153 if (!pad) {
1154 continue;
1155 } else {
1156 ret = GST_FLOW_ERROR;
1157 goto error;
1158 }
1159 }
1160
1161 if (!source_package->descriptor) {
1162 GST_WARNING_OBJECT (demux, "Source package has no descriptors");
1163 if (!pad) {
1164 continue;
1165 } else {
1166 ret = GST_FLOW_ERROR;
1167 goto error;
1168 }
1169 }
1170
1171 if (!source_track->parent.descriptor) {
1172 GST_WARNING_OBJECT (demux, "No descriptor found for track");
1173 if (!pad) {
1174 continue;
1175 } else {
1176 ret = GST_FLOW_ERROR;
1177 goto error;
1178 }
1179 }
1180
1181 if (!pad && first_run) {
1182 GstPadTemplate *templ;
1183 gchar *pad_name;
1184
1185 templ =
1186 gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (demux),
1187 "track_%u");
1188 pad_name = g_strdup_printf ("track_%u", track->parent.track_id);
1189
1190 g_assert (templ != NULL);
1191
1192 /* Create pad */
1193 pad = (GstMXFDemuxPad *) g_object_new (GST_TYPE_MXF_DEMUX_PAD,
1194 "name", pad_name, "direction", GST_PAD_SRC, "template", templ, NULL);
1195 pad->need_segment = TRUE;
1196 pad->eos = FALSE;
1197 g_free (pad_name);
1198
1199 if (demux->tags)
1200 pad->tags = gst_tag_list_copy (demux->tags);
1201 }
1202
1203 if (!pad) {
1204 GST_WARNING_OBJECT (demux,
1205 "Not the first pad addition run, ignoring new track");
1206 continue;
1207 }
1208
1209 /* Update pad */
1210 pad->track_id = track->parent.track_id;
1211
1212 pad->material_package = current_package;
1213 pad->material_track = track;
1214
1215 pad->start_timecode = start_timecode;
1216
1217 /* If we just added the pad initialize for the current component */
1218 if (first_run && MXF_IS_METADATA_MATERIAL_PACKAGE (current_package)) {
1219 pad->current_component_index = 0;
1220 pad->current_component_start = source_track->origin;
1221 pad->current_component_start_position = 0;
1222
1223 if (component->parent.duration >= -1)
1224 pad->current_component_duration = component->parent.duration;
1225 else
1226 pad->current_component_duration = -1;
1227
1228 if (track->edit_rate.n != source_track->edit_rate.n ||
1229 track->edit_rate.d != source_track->edit_rate.d) {
1230 pad->current_component_start +=
1231 gst_util_uint64_scale (component->start_position,
1232 source_track->edit_rate.n * track->edit_rate.d,
1233 source_track->edit_rate.d * track->edit_rate.n);
1234
1235 if (pad->current_component_duration != -1)
1236 pad->current_component_duration =
1237 gst_util_uint64_scale (pad->current_component_duration,
1238 source_track->edit_rate.n * track->edit_rate.d,
1239 source_track->edit_rate.d * track->edit_rate.n);
1240 } else {
1241 pad->current_component_start += component->start_position;
1242 }
1243 pad->current_essence_track_position = pad->current_component_start;
1244 }
1245
1246 /* NULL iff playing a source package */
1247 pad->current_component = component;
1248
1249 pad->current_essence_track = etrack;
1250
1251 if (etrack->tags) {
1252 if (pad->tags)
1253 gst_tag_list_insert (pad->tags, etrack->tags, GST_TAG_MERGE_REPLACE);
1254 else
1255 pad->tags = gst_tag_list_copy (etrack->tags);
1256 }
1257
1258 pad_caps = gst_pad_get_current_caps (GST_PAD_CAST (pad));
1259 if (pad_caps && !gst_caps_is_equal (pad_caps, etrack->caps)) {
1260 gst_pad_set_caps (GST_PAD_CAST (pad), etrack->caps);
1261 } else if (!pad_caps) {
1262 GstEvent *event;
1263 gchar *stream_id;
1264
1265 gst_pad_set_event_function (GST_PAD_CAST (pad),
1266 GST_DEBUG_FUNCPTR (gst_mxf_demux_src_event));
1267
1268 gst_pad_set_query_function (GST_PAD_CAST (pad),
1269 GST_DEBUG_FUNCPTR (gst_mxf_demux_src_query));
1270
1271 gst_pad_use_fixed_caps (GST_PAD_CAST (pad));
1272 gst_pad_set_active (GST_PAD_CAST (pad), TRUE);
1273
1274 stream_id =
1275 gst_pad_create_stream_id_printf (GST_PAD_CAST (pad),
1276 GST_ELEMENT_CAST (demux), "%03u", pad->track_id);
1277
1278 event =
1279 gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
1280 if (event) {
1281 if (gst_event_parse_group_id (event, &demux->group_id))
1282 demux->have_group_id = TRUE;
1283 else
1284 demux->have_group_id = FALSE;
1285 gst_event_unref (event);
1286 } else if (!demux->have_group_id) {
1287 demux->have_group_id = TRUE;
1288 demux->group_id = gst_util_group_id_next ();
1289 }
1290 event = gst_event_new_stream_start (stream_id);
1291 if (demux->have_group_id)
1292 gst_event_set_group_id (event, demux->group_id);
1293
1294 gst_pad_push_event (GST_PAD_CAST (pad), event);
1295 g_free (stream_id);
1296
1297 gst_pad_set_caps (GST_PAD_CAST (pad), etrack->caps);
1298
1299 pads = g_list_prepend (pads, gst_object_ref (pad));
1300
1301 g_ptr_array_add (demux->src, pad);
1302 pad->discont = TRUE;
1303 }
1304 if (pad_caps)
1305 gst_caps_unref (pad_caps);
1306 }
1307
1308 if (demux->src->len > 0) {
1309 for (i = 0; i < demux->src->len; i++) {
1310 GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i);
1311
1312 if (!pad->material_track || !pad->material_package) {
1313 GST_ERROR_OBJECT (demux, "Unable to update existing pad");
1314 ret = GST_FLOW_ERROR;
1315 goto error;
1316 }
1317 }
1318 } else {
1319 GST_ERROR_OBJECT (demux, "Couldn't create any streams");
1320 ret = GST_FLOW_ERROR;
1321 goto error;
1322 }
1323
1324 g_rw_lock_writer_unlock (&demux->metadata_lock);
1325
1326 for (l = pads; l; l = l->next) {
1327 gst_flow_combiner_add_pad (demux->flowcombiner, l->data);
1328 gst_element_add_pad (GST_ELEMENT_CAST (demux), l->data);
1329 }
1330 g_list_free (pads);
1331
1332 if (first_run)
1333 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1334
1335 return GST_FLOW_OK;
1336
1337 error:
1338 g_rw_lock_writer_unlock (&demux->metadata_lock);
1339 return ret;
1340 }
1341
1342 static GstFlowReturn
gst_mxf_demux_handle_metadata(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer)1343 gst_mxf_demux_handle_metadata (GstMXFDemux * demux, const MXFUL * key,
1344 GstBuffer * buffer)
1345 {
1346 guint16 type;
1347 MXFMetadata *metadata = NULL, *old = NULL;
1348 GstMapInfo map;
1349 GstFlowReturn ret = GST_FLOW_OK;
1350
1351 type = GST_READ_UINT16_BE (key->u + 13);
1352
1353 GST_DEBUG_OBJECT (demux,
1354 "Handling metadata of size %" G_GSIZE_FORMAT " at offset %"
1355 G_GUINT64_FORMAT " of type 0x%04x", gst_buffer_get_size (buffer),
1356 demux->offset, type);
1357
1358 if (G_UNLIKELY (!demux->current_partition)) {
1359 GST_ERROR_OBJECT (demux, "Partition pack doesn't exist");
1360 return GST_FLOW_ERROR;
1361 }
1362
1363 if (G_UNLIKELY (!demux->current_partition->primer.mappings)) {
1364 GST_ERROR_OBJECT (demux, "Primer pack doesn't exists");
1365 return GST_FLOW_ERROR;
1366 }
1367
1368 if (demux->current_partition->parsed_metadata) {
1369 GST_DEBUG_OBJECT (demux, "Metadata of this partition was already parsed");
1370 return GST_FLOW_OK;
1371 }
1372
1373 if (gst_buffer_get_size (buffer) == 0)
1374 return GST_FLOW_OK;
1375
1376 gst_buffer_map (buffer, &map, GST_MAP_READ);
1377 metadata =
1378 mxf_metadata_new (type, &demux->current_partition->primer, demux->offset,
1379 map.data, map.size);
1380 gst_buffer_unmap (buffer, &map);
1381
1382 if (!metadata) {
1383 GST_WARNING_OBJECT (demux,
1384 "Unknown or unhandled metadata of type 0x%04x", type);
1385 return GST_FLOW_OK;
1386 }
1387
1388 old =
1389 g_hash_table_lookup (demux->metadata,
1390 &MXF_METADATA_BASE (metadata)->instance_uid);
1391
1392 if (old && G_TYPE_FROM_INSTANCE (old) != G_TYPE_FROM_INSTANCE (metadata)) {
1393 #ifndef GST_DISABLE_GST_DEBUG
1394 gchar str[48];
1395 #endif
1396
1397 GST_DEBUG_OBJECT (demux,
1398 "Metadata with instance uid %s already exists and has different type '%s',"
1399 " expected '%s'",
1400 mxf_uuid_to_string (&MXF_METADATA_BASE (metadata)->instance_uid, str),
1401 g_type_name (G_TYPE_FROM_INSTANCE (old)),
1402 g_type_name (G_TYPE_FROM_INSTANCE (metadata)));
1403 g_object_unref (metadata);
1404 return GST_FLOW_ERROR;
1405 } else if (old
1406 && MXF_METADATA_BASE (old)->offset >=
1407 MXF_METADATA_BASE (metadata)->offset) {
1408 #ifndef GST_DISABLE_GST_DEBUG
1409 gchar str[48];
1410 #endif
1411
1412 GST_DEBUG_OBJECT (demux,
1413 "Metadata with instance uid %s already exists and is newer",
1414 mxf_uuid_to_string (&MXF_METADATA_BASE (metadata)->instance_uid, str));
1415 g_object_unref (metadata);
1416 return GST_FLOW_OK;
1417 }
1418
1419 g_rw_lock_writer_lock (&demux->metadata_lock);
1420 demux->update_metadata = TRUE;
1421
1422 if (MXF_IS_METADATA_PREFACE (metadata)) {
1423 demux->preface = MXF_METADATA_PREFACE (metadata);
1424 }
1425
1426 gst_mxf_demux_reset_linked_metadata (demux);
1427
1428 g_hash_table_replace (demux->metadata,
1429 &MXF_METADATA_BASE (metadata)->instance_uid, metadata);
1430 g_rw_lock_writer_unlock (&demux->metadata_lock);
1431
1432 return ret;
1433 }
1434
1435 static GstFlowReturn
gst_mxf_demux_handle_descriptive_metadata(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer)1436 gst_mxf_demux_handle_descriptive_metadata (GstMXFDemux * demux,
1437 const MXFUL * key, GstBuffer * buffer)
1438 {
1439 guint32 type;
1440 guint8 scheme;
1441 GstMapInfo map;
1442 GstFlowReturn ret = GST_FLOW_OK;
1443 MXFDescriptiveMetadata *m = NULL, *old = NULL;
1444
1445 scheme = GST_READ_UINT8 (key->u + 12);
1446 type = GST_READ_UINT24_BE (key->u + 13);
1447
1448 GST_DEBUG_OBJECT (demux,
1449 "Handling descriptive metadata of size %" G_GSIZE_FORMAT " at offset %"
1450 G_GUINT64_FORMAT " with scheme 0x%02x and type 0x%06x",
1451 gst_buffer_get_size (buffer), demux->offset, scheme, type);
1452
1453 if (G_UNLIKELY (!demux->current_partition)) {
1454 GST_ERROR_OBJECT (demux, "Partition pack doesn't exist");
1455 return GST_FLOW_ERROR;
1456 }
1457
1458 if (G_UNLIKELY (!demux->current_partition->primer.mappings)) {
1459 GST_ERROR_OBJECT (demux, "Primer pack doesn't exists");
1460 return GST_FLOW_ERROR;
1461 }
1462
1463 if (demux->current_partition->parsed_metadata) {
1464 GST_DEBUG_OBJECT (demux, "Metadata of this partition was already parsed");
1465 return GST_FLOW_OK;
1466 }
1467
1468 gst_buffer_map (buffer, &map, GST_MAP_READ);
1469 m = mxf_descriptive_metadata_new (scheme, type,
1470 &demux->current_partition->primer, demux->offset, map.data, map.size);
1471 gst_buffer_unmap (buffer, &map);
1472
1473 if (!m) {
1474 GST_WARNING_OBJECT (demux,
1475 "Unknown or unhandled descriptive metadata of scheme 0x%02x and type 0x%06x",
1476 scheme, type);
1477 return GST_FLOW_OK;
1478 }
1479
1480 old =
1481 g_hash_table_lookup (demux->metadata,
1482 &MXF_METADATA_BASE (m)->instance_uid);
1483
1484 if (old && G_TYPE_FROM_INSTANCE (old) != G_TYPE_FROM_INSTANCE (m)) {
1485 #ifndef GST_DISABLE_GST_DEBUG
1486 gchar str[48];
1487 #endif
1488
1489 GST_DEBUG_OBJECT (demux,
1490 "Metadata with instance uid %s already exists and has different type '%s',"
1491 " expected '%s'",
1492 mxf_uuid_to_string (&MXF_METADATA_BASE (m)->instance_uid, str),
1493 g_type_name (G_TYPE_FROM_INSTANCE (old)),
1494 g_type_name (G_TYPE_FROM_INSTANCE (m)));
1495 g_object_unref (m);
1496 return GST_FLOW_ERROR;
1497 } else if (old
1498 && MXF_METADATA_BASE (old)->offset >= MXF_METADATA_BASE (m)->offset) {
1499 #ifndef GST_DISABLE_GST_DEBUG
1500 gchar str[48];
1501 #endif
1502
1503 GST_DEBUG_OBJECT (demux,
1504 "Metadata with instance uid %s already exists and is newer",
1505 mxf_uuid_to_string (&MXF_METADATA_BASE (m)->instance_uid, str));
1506 g_object_unref (m);
1507 return GST_FLOW_OK;
1508 }
1509
1510 g_rw_lock_writer_lock (&demux->metadata_lock);
1511
1512 demux->update_metadata = TRUE;
1513 gst_mxf_demux_reset_linked_metadata (demux);
1514
1515 g_hash_table_replace (demux->metadata, &MXF_METADATA_BASE (m)->instance_uid,
1516 m);
1517
1518 g_rw_lock_writer_unlock (&demux->metadata_lock);
1519
1520 return ret;
1521 }
1522
1523 static GstFlowReturn
gst_mxf_demux_handle_generic_container_system_item(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer)1524 gst_mxf_demux_handle_generic_container_system_item (GstMXFDemux * demux,
1525 const MXFUL * key, GstBuffer * buffer)
1526 {
1527 GST_DEBUG_OBJECT (demux,
1528 "Handling generic container system item of size %" G_GSIZE_FORMAT
1529 " at offset %" G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
1530 demux->offset);
1531
1532 if (demux->current_partition->essence_container_offset == 0)
1533 demux->current_partition->essence_container_offset =
1534 demux->offset - demux->current_partition->partition.this_partition -
1535 demux->run_in;
1536
1537 /* TODO: parse this */
1538 return GST_FLOW_OK;
1539 }
1540
1541 static GstFlowReturn
gst_mxf_demux_pad_set_component(GstMXFDemux * demux,GstMXFDemuxPad * pad,guint i)1542 gst_mxf_demux_pad_set_component (GstMXFDemux * demux, GstMXFDemuxPad * pad,
1543 guint i)
1544 {
1545 GstFlowReturn ret = GST_FLOW_OK;
1546 GstCaps *pad_caps;
1547 MXFMetadataSequence *sequence;
1548 guint k;
1549 MXFMetadataSourcePackage *source_package = NULL;
1550 MXFMetadataTimelineTrack *source_track = NULL;
1551 gboolean update = (pad->current_component_index != i);
1552
1553 pad->current_component_index = i;
1554
1555 sequence = pad->material_track->parent.sequence;
1556
1557 if (pad->current_component_index >= sequence->n_structural_components) {
1558 GST_DEBUG_OBJECT (demux, "After last structural component");
1559 pad->current_component_index = sequence->n_structural_components - 1;
1560 ret = GST_FLOW_EOS;
1561 }
1562
1563 GST_DEBUG_OBJECT (demux, "Switching to component %u",
1564 pad->current_component_index);
1565
1566 pad->current_component =
1567 MXF_METADATA_SOURCE_CLIP (sequence->structural_components[pad->
1568 current_component_index]);
1569 if (pad->current_component == NULL) {
1570 GST_ERROR_OBJECT (demux, "No such structural component");
1571 return GST_FLOW_ERROR;
1572 }
1573
1574 if (!pad->current_component->source_package
1575 || !pad->current_component->source_package->top_level
1576 || !MXF_METADATA_GENERIC_PACKAGE (pad->current_component->
1577 source_package)->tracks) {
1578 GST_ERROR_OBJECT (demux, "Invalid component");
1579 return GST_FLOW_ERROR;
1580 }
1581
1582 source_package = pad->current_component->source_package;
1583
1584 for (k = 0; k < source_package->parent.n_tracks; k++) {
1585 MXFMetadataTrack *tmp = source_package->parent.tracks[k];
1586
1587 if (tmp->track_id == pad->current_component->source_track_id) {
1588 source_track = MXF_METADATA_TIMELINE_TRACK (tmp);
1589 break;
1590 }
1591 }
1592
1593 if (!source_track) {
1594 GST_ERROR_OBJECT (demux, "No source track found");
1595 return GST_FLOW_ERROR;
1596 }
1597
1598 pad->current_essence_track = NULL;
1599
1600 for (k = 0; k < demux->essence_tracks->len; k++) {
1601 GstMXFDemuxEssenceTrack *tmp =
1602 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, k);
1603
1604 if (tmp->source_package == source_package &&
1605 tmp->source_track == source_track) {
1606 pad->current_essence_track = tmp;
1607 break;
1608 }
1609 }
1610
1611 if (!pad->current_essence_track) {
1612 GST_ERROR_OBJECT (demux, "No corresponding essence track found");
1613 return GST_FLOW_ERROR;
1614 }
1615
1616 if (!source_package->descriptor) {
1617 GST_ERROR_OBJECT (demux, "Source package has no descriptors");
1618 return GST_FLOW_ERROR;
1619 }
1620
1621 if (!source_track->parent.descriptor) {
1622 GST_ERROR_OBJECT (demux, "No descriptor found for track");
1623 return GST_FLOW_ERROR;
1624 }
1625
1626 if (source_track->edit_rate.n <= 0 || source_track->edit_rate.d <= 0) {
1627 GST_ERROR_OBJECT (demux, "Source track has invalid edit rate");
1628 return GST_FLOW_ERROR;
1629 }
1630
1631 pad->current_component_start_position = 0;
1632 for (k = 0; k < i; k++) {
1633 pad->current_component_start_position +=
1634 MXF_METADATA_SOURCE_CLIP (sequence->structural_components[k])->
1635 parent.duration;
1636 }
1637
1638 if (pad->current_component->parent.duration >= -1)
1639 pad->current_component_duration = pad->current_component->parent.duration;
1640 else
1641 pad->current_component_duration = -1;
1642
1643 if (pad->material_track->edit_rate.n != source_track->edit_rate.n ||
1644 pad->material_track->edit_rate.d != source_track->edit_rate.d) {
1645 pad->current_component_start +=
1646 gst_util_uint64_scale (pad->current_component->start_position,
1647 source_track->edit_rate.n * pad->material_track->edit_rate.d,
1648 source_track->edit_rate.d * pad->material_track->edit_rate.n);
1649
1650 if (pad->current_component_duration != -1)
1651 pad->current_component_duration =
1652 gst_util_uint64_scale (pad->current_component_duration,
1653 source_track->edit_rate.n * pad->material_track->edit_rate.d,
1654 source_track->edit_rate.d * pad->material_track->edit_rate.n);
1655 } else {
1656 pad->current_component_start += pad->current_component->start_position;
1657 }
1658 pad->current_essence_track_position = pad->current_component_start;
1659
1660 pad_caps = gst_pad_get_current_caps (GST_PAD_CAST (pad));
1661 if (!pad_caps
1662 || !gst_caps_is_equal (pad_caps, pad->current_essence_track->caps)) {
1663 gst_pad_set_caps (GST_PAD_CAST (pad), pad->current_essence_track->caps);
1664 }
1665 if (pad_caps)
1666 gst_caps_unref (pad_caps);
1667
1668 if (update) {
1669 if (pad->tags) {
1670 if (pad->current_essence_track->tags)
1671 gst_tag_list_insert (pad->tags, pad->current_essence_track->tags,
1672 GST_TAG_MERGE_REPLACE);
1673 } else {
1674 if (pad->current_essence_track->tags)
1675 pad->tags = gst_tag_list_copy (pad->current_essence_track->tags);
1676 }
1677 }
1678
1679 if (ret == GST_FLOW_EOS) {
1680 pad->current_essence_track_position += pad->current_component_duration;
1681 }
1682
1683 return ret;
1684 }
1685
1686 static GstFlowReturn
gst_mxf_demux_handle_generic_container_essence_element(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer,gboolean peek)1687 gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
1688 const MXFUL * key, GstBuffer * buffer, gboolean peek)
1689 {
1690 GstFlowReturn ret = GST_FLOW_OK;
1691 guint32 track_number;
1692 guint i;
1693 GstBuffer *inbuf = NULL;
1694 GstBuffer *outbuf = NULL;
1695 GstMXFDemuxEssenceTrack *etrack = NULL;
1696 gboolean keyframe = TRUE;
1697 /* As in GstMXFDemuxIndex */
1698 guint64 pts = G_MAXUINT64, dts = G_MAXUINT64;
1699
1700 GST_DEBUG_OBJECT (demux,
1701 "Handling generic container essence element of size %" G_GSIZE_FORMAT
1702 " at offset %" G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
1703 demux->offset);
1704
1705 GST_DEBUG_OBJECT (demux, " type = 0x%02x", key->u[12]);
1706 GST_DEBUG_OBJECT (demux, " essence element count = 0x%02x", key->u[13]);
1707 GST_DEBUG_OBJECT (demux, " essence element type = 0x%02x", key->u[14]);
1708 GST_DEBUG_OBJECT (demux, " essence element number = 0x%02x", key->u[15]);
1709
1710 if (demux->current_partition->essence_container_offset == 0)
1711 demux->current_partition->essence_container_offset =
1712 demux->offset - demux->current_partition->partition.this_partition -
1713 demux->run_in;
1714
1715 if (!demux->current_package) {
1716 GST_ERROR_OBJECT (demux, "No package selected yet");
1717 return GST_FLOW_ERROR;
1718 }
1719
1720 if (demux->src->len == 0) {
1721 GST_ERROR_OBJECT (demux, "No streams created yet");
1722 return GST_FLOW_ERROR;
1723 }
1724
1725 if (demux->essence_tracks->len == 0) {
1726 GST_ERROR_OBJECT (demux, "No essence streams found in the metadata");
1727 return GST_FLOW_ERROR;
1728 }
1729
1730 track_number = GST_READ_UINT32_BE (&key->u[12]);
1731
1732 for (i = 0; i < demux->essence_tracks->len; i++) {
1733 GstMXFDemuxEssenceTrack *tmp =
1734 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
1735
1736 if (tmp->body_sid == demux->current_partition->partition.body_sid &&
1737 (tmp->track_number == track_number || tmp->track_number == 0)) {
1738 etrack = tmp;
1739 break;
1740 }
1741 }
1742
1743 if (!etrack) {
1744 GST_WARNING_OBJECT (demux,
1745 "No essence track for this essence element found");
1746 return GST_FLOW_OK;
1747 }
1748
1749 if (etrack->position == -1) {
1750 GST_DEBUG_OBJECT (demux,
1751 "Unknown essence track position, looking into index");
1752 if (etrack->offsets) {
1753 for (i = 0; i < etrack->offsets->len; i++) {
1754 GstMXFDemuxIndex *idx =
1755 &g_array_index (etrack->offsets, GstMXFDemuxIndex, i);
1756
1757 if (idx->initialized && idx->offset != 0
1758 && idx->offset == demux->offset - demux->run_in) {
1759 etrack->position = i;
1760 break;
1761 }
1762 }
1763 }
1764
1765 if (etrack->position == -1) {
1766 GST_WARNING_OBJECT (demux, "Essence track position not in index");
1767 return GST_FLOW_OK;
1768 }
1769 }
1770
1771 if (etrack->offsets && etrack->offsets->len > etrack->position) {
1772 GstMXFDemuxIndex *index =
1773 &g_array_index (etrack->offsets, GstMXFDemuxIndex, etrack->position);
1774 if (index->initialized && index->offset != 0)
1775 keyframe = index->keyframe;
1776 if (index->initialized && index->pts != G_MAXUINT64)
1777 pts = index->pts;
1778 if (index->initialized && index->dts != G_MAXUINT64)
1779 dts = index->dts;
1780 }
1781
1782 /* Create subbuffer to be able to change metadata */
1783 inbuf =
1784 gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0,
1785 gst_buffer_get_size (buffer));
1786
1787 if (!keyframe)
1788 GST_BUFFER_FLAG_SET (inbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1789
1790 if (etrack->handle_func) {
1791 /* Takes ownership of inbuf */
1792 ret =
1793 etrack->handle_func (key, inbuf, etrack->caps,
1794 etrack->source_track, etrack->mapping_data, &outbuf);
1795 inbuf = NULL;
1796 } else {
1797 outbuf = inbuf;
1798 inbuf = NULL;
1799 ret = GST_FLOW_OK;
1800 }
1801
1802 if (ret != GST_FLOW_OK) {
1803 GST_ERROR_OBJECT (demux, "Failed to handle essence element");
1804 if (outbuf) {
1805 gst_buffer_unref (outbuf);
1806 outbuf = NULL;
1807 }
1808 return ret;
1809 }
1810
1811 if (outbuf)
1812 keyframe = !GST_BUFFER_FLAG_IS_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1813
1814 /* Prefer keyframe information from index tables over everything else */
1815 if (demux->index_tables) {
1816 GList *l;
1817 GstMXFDemuxIndexTable *index_table = NULL;
1818
1819 for (l = demux->index_tables; l; l = l->next) {
1820 GstMXFDemuxIndexTable *tmp = l->data;
1821
1822 if (tmp->body_sid == etrack->body_sid
1823 && tmp->index_sid == etrack->index_sid) {
1824 index_table = tmp;
1825 break;
1826 }
1827 }
1828
1829 if (index_table && index_table->offsets->len > etrack->position) {
1830 GstMXFDemuxIndex *index =
1831 &g_array_index (index_table->offsets, GstMXFDemuxIndex,
1832 etrack->position);
1833 if (index->initialized && index->offset != 0) {
1834 keyframe = index->keyframe;
1835
1836 if (outbuf) {
1837 if (keyframe)
1838 GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1839 else
1840 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1841 }
1842 }
1843
1844 if (index->initialized && index->pts != G_MAXUINT64)
1845 pts = index->pts;
1846 if (index->initialized && index->dts != G_MAXUINT64)
1847 dts = index->dts;
1848 }
1849 }
1850
1851 if (!etrack->offsets)
1852 etrack->offsets = g_array_new (FALSE, TRUE, sizeof (GstMXFDemuxIndex));
1853
1854 {
1855 if (etrack->offsets->len > etrack->position) {
1856 GstMXFDemuxIndex *index =
1857 &g_array_index (etrack->offsets, GstMXFDemuxIndex, etrack->position);
1858
1859 index->offset = demux->offset - demux->run_in;
1860 index->initialized = TRUE;
1861 index->pts = pts;
1862 index->dts = dts;
1863 index->keyframe = keyframe;
1864 } else if (etrack->position < G_MAXINT) {
1865 GstMXFDemuxIndex index;
1866
1867 index.offset = demux->offset - demux->run_in;
1868 index.initialized = TRUE;
1869 index.pts = pts;
1870 index.dts = dts;
1871 index.keyframe = keyframe;
1872 if (etrack->offsets->len < etrack->position)
1873 g_array_set_size (etrack->offsets, etrack->position + 1);
1874 g_array_insert_val (etrack->offsets, etrack->position, index);
1875 }
1876 }
1877
1878 if (peek)
1879 goto out;
1880
1881 if (!outbuf) {
1882 GST_DEBUG_OBJECT (demux, "No output buffer created");
1883 goto out;
1884 }
1885
1886 inbuf = outbuf;
1887 outbuf = NULL;
1888
1889 for (i = 0; i < demux->src->len; i++) {
1890 GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i);
1891
1892 if (pad->current_essence_track != etrack)
1893 continue;
1894
1895 if (pad->eos) {
1896 GST_DEBUG_OBJECT (demux, "Pad is already EOS");
1897 continue;
1898 }
1899
1900 if (etrack->position != pad->current_essence_track_position) {
1901 GST_DEBUG_OBJECT (demux, "Not at current component's position");
1902 continue;
1903 }
1904
1905 {
1906 GstMXFDemuxPad *earliest = gst_mxf_demux_get_earliest_pad (demux);
1907
1908 if (earliest && earliest != pad && earliest->position < pad->position &&
1909 pad->position - earliest->position > demux->max_drift) {
1910 GST_DEBUG_OBJECT (demux, "Pad is too far ahead of time");
1911 continue;
1912 }
1913 }
1914
1915 /* Create another subbuffer to have writable metadata */
1916 outbuf =
1917 gst_buffer_copy_region (inbuf, GST_BUFFER_COPY_ALL, 0,
1918 gst_buffer_get_size (inbuf));
1919
1920 GST_BUFFER_DTS (outbuf) = pad->position;
1921 if (etrack->intra_only) {
1922 GST_BUFFER_PTS (outbuf) = pad->position;
1923 } else if (pts != G_MAXUINT64) {
1924 GST_BUFFER_PTS (outbuf) = gst_util_uint64_scale (pts * GST_SECOND,
1925 pad->current_essence_track->source_track->edit_rate.d,
1926 pad->current_essence_track->source_track->edit_rate.n);
1927 GST_BUFFER_PTS (outbuf) +=
1928 gst_util_uint64_scale (pad->current_component_start_position *
1929 GST_SECOND, pad->material_track->edit_rate.d,
1930 pad->material_track->edit_rate.n);
1931 } else {
1932 GST_BUFFER_PTS (outbuf) = GST_CLOCK_TIME_NONE;
1933 }
1934
1935 GST_BUFFER_DURATION (outbuf) =
1936 gst_util_uint64_scale (GST_SECOND,
1937 pad->current_essence_track->source_track->edit_rate.d,
1938 pad->current_essence_track->source_track->edit_rate.n);
1939 GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE;
1940 GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
1941
1942 if (pad->material_track->parent.type == MXF_METADATA_TRACK_PICTURE_ESSENCE
1943 && pad->start_timecode.config.fps_n != 0
1944 && pad->start_timecode.config.fps_d != 0) {
1945 if (etrack->intra_only) {
1946 GstVideoTimeCode timecode = pad->start_timecode;
1947
1948 gst_video_time_code_add_frames (&timecode,
1949 pad->current_material_track_position);
1950 gst_buffer_add_video_time_code_meta (outbuf, &timecode);
1951 } else if (pts != G_MAXUINT64) {
1952 GstVideoTimeCode timecode = pad->start_timecode;
1953
1954 gst_video_time_code_add_frames (&timecode,
1955 pad->current_component_start_position);
1956 gst_video_time_code_add_frames (&timecode,
1957 gst_util_uint64_scale (pts,
1958 pad->material_track->edit_rate.n *
1959 pad->current_essence_track->source_track->edit_rate.d,
1960 pad->material_track->edit_rate.d *
1961 pad->current_essence_track->source_track->edit_rate.n));
1962 gst_buffer_add_video_time_code_meta (outbuf, &timecode);
1963 }
1964
1965 }
1966
1967 /* Update accumulated error and compensate */
1968 {
1969 guint64 abs_error =
1970 (GST_SECOND * pad->current_essence_track->source_track->edit_rate.d) %
1971 pad->current_essence_track->source_track->edit_rate.n;
1972 pad->position_accumulated_error +=
1973 ((gdouble) abs_error) /
1974 ((gdouble) pad->current_essence_track->source_track->edit_rate.n);
1975 }
1976 if (pad->position_accumulated_error >= 1.0) {
1977 GST_BUFFER_DURATION (outbuf) += 1;
1978 pad->position_accumulated_error -= 1.0;
1979 }
1980
1981 if (pad->need_segment) {
1982 GstEvent *e;
1983
1984 if (demux->close_seg_event)
1985 gst_pad_push_event (GST_PAD_CAST (pad),
1986 gst_event_ref (demux->close_seg_event));
1987
1988 e = gst_event_new_segment (&demux->segment);
1989 gst_event_set_seqnum (e, demux->seqnum);
1990 gst_pad_push_event (GST_PAD_CAST (pad), e);
1991 pad->need_segment = FALSE;
1992 }
1993
1994 if (pad->tags) {
1995 gst_pad_push_event (GST_PAD_CAST (pad), gst_event_new_tag (pad->tags));
1996 pad->tags = NULL;
1997 }
1998
1999 pad->position += GST_BUFFER_DURATION (outbuf);
2000 pad->current_material_track_position++;
2001
2002 GST_DEBUG_OBJECT (demux,
2003 "Pushing buffer of size %" G_GSIZE_FORMAT " for track %u: pts %"
2004 GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT
2005 " position %" G_GUINT64_FORMAT, gst_buffer_get_size (outbuf),
2006 pad->material_track->parent.track_id,
2007 GST_TIME_ARGS (GST_BUFFER_PTS (outbuf)),
2008 GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
2009 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
2010 pad->current_essence_track_position);
2011
2012 if (pad->discont) {
2013 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
2014 pad->discont = FALSE;
2015 }
2016
2017 ret = gst_pad_push (GST_PAD_CAST (pad), outbuf);
2018 outbuf = NULL;
2019 ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
2020 GST_LOG_OBJECT (demux, "combined return %s", gst_flow_get_name (ret));
2021
2022 if (pad->position > demux->segment.position)
2023 demux->segment.position = pad->position;
2024
2025 if (ret != GST_FLOW_OK)
2026 goto out;
2027
2028 pad->current_essence_track_position++;
2029
2030 if (pad->current_component) {
2031 if (pad->current_component_duration > 0 &&
2032 pad->current_essence_track_position - pad->current_component_start
2033 >= pad->current_component_duration) {
2034 GST_DEBUG_OBJECT (demux, "Switching to next component");
2035
2036 ret =
2037 gst_mxf_demux_pad_set_component (demux, pad,
2038 pad->current_component_index + 1);
2039 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS) {
2040 GST_ERROR_OBJECT (demux, "Switching component failed");
2041 }
2042 } else if (etrack->duration > 0
2043 && pad->current_essence_track_position >= etrack->duration) {
2044 GST_DEBUG_OBJECT (demux,
2045 "Current component position after end of essence track");
2046 ret = GST_FLOW_EOS;
2047 }
2048 } else if (etrack->duration > 0
2049 && pad->current_essence_track_position == etrack->duration) {
2050 GST_DEBUG_OBJECT (demux, "At the end of the essence track");
2051 ret = GST_FLOW_EOS;
2052 }
2053
2054 if (ret == GST_FLOW_EOS) {
2055 GstEvent *e;
2056
2057 GST_DEBUG_OBJECT (demux, "EOS for track");
2058 pad->eos = TRUE;
2059 e = gst_event_new_eos ();
2060 gst_event_set_seqnum (e, demux->seqnum);
2061 gst_pad_push_event (GST_PAD_CAST (pad), e);
2062 ret = GST_FLOW_OK;
2063 }
2064
2065 if (ret != GST_FLOW_OK)
2066 goto out;
2067 }
2068
2069 out:
2070 if (inbuf)
2071 gst_buffer_unref (inbuf);
2072
2073 if (outbuf)
2074 gst_buffer_unref (outbuf);
2075
2076 etrack->position++;
2077
2078 return ret;
2079 }
2080
2081 static void
read_partition_header(GstMXFDemux * demux)2082 read_partition_header (GstMXFDemux * demux)
2083 {
2084 GstBuffer *buf;
2085 MXFUL key;
2086 guint read;
2087
2088 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf, &read)
2089 != GST_FLOW_OK)
2090 return;
2091
2092 if (!mxf_is_partition_pack (&key)) {
2093 gst_buffer_unref (buf);
2094 return;
2095 }
2096
2097 if (gst_mxf_demux_handle_partition_pack (demux, &key, buf) != GST_FLOW_OK) {
2098 gst_buffer_unref (buf);
2099 return;
2100 }
2101 demux->offset += read;
2102 gst_buffer_unref (buf);
2103
2104 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf, &read)
2105 != GST_FLOW_OK)
2106 return;
2107
2108 while (mxf_is_fill (&key)) {
2109 demux->offset += read;
2110 gst_buffer_unref (buf);
2111 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf, &read)
2112 != GST_FLOW_OK)
2113 return;
2114 }
2115
2116 if (!mxf_is_index_table_segment (&key)
2117 && demux->current_partition->partition.header_byte_count) {
2118 gst_buffer_unref (buf);
2119 demux->offset += demux->current_partition->partition.header_byte_count;
2120 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf, &read)
2121 != GST_FLOW_OK)
2122 return;
2123 }
2124
2125 while (mxf_is_fill (&key)) {
2126 demux->offset += read;
2127 gst_buffer_unref (buf);
2128 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf, &read)
2129 != GST_FLOW_OK)
2130 return;
2131 }
2132
2133 if (demux->current_partition->partition.index_byte_count
2134 && mxf_is_index_table_segment (&key)) {
2135 guint64 index_end_offset =
2136 demux->offset + demux->current_partition->partition.index_byte_count;
2137
2138 while (demux->offset < index_end_offset) {
2139 if (mxf_is_index_table_segment (&key)) {
2140 gst_mxf_demux_handle_index_table_segment (demux, &key, buf,
2141 demux->offset);
2142 }
2143 demux->offset += read;
2144
2145 gst_buffer_unref (buf);
2146 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf,
2147 &read)
2148 != GST_FLOW_OK)
2149 return;
2150 }
2151 }
2152
2153 while (mxf_is_fill (&key)) {
2154 demux->offset += read;
2155 gst_buffer_unref (buf);
2156 if (gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buf, &read)
2157 != GST_FLOW_OK)
2158 return;
2159 }
2160
2161 if (mxf_is_generic_container_system_item (&key) ||
2162 mxf_is_generic_container_essence_element (&key) ||
2163 mxf_is_avid_essence_container_essence_element (&key)) {
2164 if (demux->current_partition->essence_container_offset == 0)
2165 demux->current_partition->essence_container_offset =
2166 demux->offset - demux->current_partition->partition.this_partition -
2167 demux->run_in;
2168 }
2169
2170 gst_buffer_unref (buf);
2171 }
2172
2173 static GstFlowReturn
gst_mxf_demux_handle_random_index_pack(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer)2174 gst_mxf_demux_handle_random_index_pack (GstMXFDemux * demux, const MXFUL * key,
2175 GstBuffer * buffer)
2176 {
2177 guint i;
2178 GList *l;
2179 GstMapInfo map;
2180 gboolean ret;
2181
2182 GST_DEBUG_OBJECT (demux,
2183 "Handling random index pack of size %" G_GSIZE_FORMAT " at offset %"
2184 G_GUINT64_FORMAT, gst_buffer_get_size (buffer), demux->offset);
2185
2186 if (demux->random_index_pack) {
2187 GST_DEBUG_OBJECT (demux, "Already parsed random index pack");
2188 return GST_FLOW_OK;
2189 }
2190
2191 gst_buffer_map (buffer, &map, GST_MAP_READ);
2192 ret =
2193 mxf_random_index_pack_parse (key, map.data, map.size,
2194 &demux->random_index_pack);
2195 gst_buffer_unmap (buffer, &map);
2196
2197 if (!ret) {
2198 GST_ERROR_OBJECT (demux, "Parsing random index pack failed");
2199 return GST_FLOW_ERROR;
2200 }
2201
2202 for (i = 0; i < demux->random_index_pack->len; i++) {
2203 GstMXFDemuxPartition *p = NULL;
2204 MXFRandomIndexPackEntry *e =
2205 &g_array_index (demux->random_index_pack, MXFRandomIndexPackEntry, i);
2206
2207 if (e->offset < demux->run_in) {
2208 GST_ERROR_OBJECT (demux, "Invalid random index pack entry");
2209 return GST_FLOW_ERROR;
2210 }
2211
2212 for (l = demux->partitions; l; l = l->next) {
2213 GstMXFDemuxPartition *tmp = l->data;
2214
2215 if (tmp->partition.this_partition + demux->run_in == e->offset) {
2216 p = tmp;
2217 break;
2218 }
2219 }
2220
2221 if (!p) {
2222 p = g_new0 (GstMXFDemuxPartition, 1);
2223 p->partition.this_partition = e->offset - demux->run_in;
2224 p->partition.body_sid = e->body_sid;
2225 demux->partitions =
2226 g_list_insert_sorted (demux->partitions, p,
2227 (GCompareFunc) gst_mxf_demux_partition_compare);
2228 }
2229 }
2230
2231 for (l = demux->partitions; l; l = l->next) {
2232 GstMXFDemuxPartition *a, *b;
2233
2234 if (l->next == NULL)
2235 break;
2236
2237 a = l->data;
2238 b = l->next->data;
2239
2240 b->partition.prev_partition = a->partition.this_partition;
2241 }
2242
2243 return GST_FLOW_OK;
2244 }
2245
2246 static GstFlowReturn
gst_mxf_demux_handle_index_table_segment(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer,guint64 offset)2247 gst_mxf_demux_handle_index_table_segment (GstMXFDemux * demux,
2248 const MXFUL * key, GstBuffer * buffer, guint64 offset)
2249 {
2250 MXFIndexTableSegment *segment;
2251 GstMapInfo map;
2252 gboolean ret;
2253
2254 GST_DEBUG_OBJECT (demux,
2255 "Handling index table segment of size %" G_GSIZE_FORMAT " at offset %"
2256 G_GUINT64_FORMAT, gst_buffer_get_size (buffer), offset);
2257
2258 segment = g_new0 (MXFIndexTableSegment, 1);
2259
2260 gst_buffer_map (buffer, &map, GST_MAP_READ);
2261 ret = mxf_index_table_segment_parse (key, segment, map.data, map.size);
2262 gst_buffer_unmap (buffer, &map);
2263
2264 if (!ret) {
2265 GST_ERROR_OBJECT (demux, "Parsing index table segment failed");
2266 g_free (segment);
2267 return GST_FLOW_ERROR;
2268 }
2269
2270 demux->pending_index_table_segments =
2271 g_list_prepend (demux->pending_index_table_segments, segment);
2272
2273 return GST_FLOW_OK;
2274 }
2275
2276 static GstFlowReturn
gst_mxf_demux_pull_klv_packet(GstMXFDemux * demux,guint64 offset,MXFUL * key,GstBuffer ** outbuf,guint * read)2277 gst_mxf_demux_pull_klv_packet (GstMXFDemux * demux, guint64 offset, MXFUL * key,
2278 GstBuffer ** outbuf, guint * read)
2279 {
2280 GstBuffer *buffer = NULL;
2281 const guint8 *data;
2282 guint64 data_offset = 0;
2283 guint64 length;
2284 GstFlowReturn ret = GST_FLOW_OK;
2285 GstMapInfo map;
2286 #ifndef GST_DISABLE_GST_DEBUG
2287 gchar str[48];
2288 #endif
2289
2290 memset (key, 0, sizeof (MXFUL));
2291
2292 /* Pull 16 byte key and first byte of BER encoded length */
2293 if ((ret =
2294 gst_mxf_demux_pull_range (demux, offset, 17, &buffer)) != GST_FLOW_OK)
2295 goto beach;
2296
2297 gst_buffer_map (buffer, &map, GST_MAP_READ);
2298
2299 memcpy (key, map.data, 16);
2300
2301 GST_DEBUG_OBJECT (demux, "Got KLV packet with key %s", mxf_ul_to_string (key,
2302 str));
2303
2304 /* Decode BER encoded packet length */
2305 if ((map.data[16] & 0x80) == 0) {
2306 length = map.data[16];
2307 data_offset = 17;
2308 } else {
2309 guint slen = map.data[16] & 0x7f;
2310
2311 data_offset = 16 + 1 + slen;
2312
2313 gst_buffer_unmap (buffer, &map);
2314 gst_buffer_unref (buffer);
2315 buffer = NULL;
2316
2317 /* Must be at most 8 according to SMPTE-379M 5.3.4 */
2318 if (slen > 8) {
2319 GST_ERROR_OBJECT (demux, "Invalid KLV packet length: %u", slen);
2320 ret = GST_FLOW_ERROR;
2321 goto beach;
2322 }
2323
2324 /* Now pull the length of the packet */
2325 if ((ret = gst_mxf_demux_pull_range (demux, offset + 17, slen,
2326 &buffer)) != GST_FLOW_OK)
2327 goto beach;
2328
2329 gst_buffer_map (buffer, &map, GST_MAP_READ);
2330
2331 data = map.data;
2332 length = 0;
2333 while (slen) {
2334 length = (length << 8) | *data;
2335 data++;
2336 slen--;
2337 }
2338 }
2339
2340 gst_buffer_unmap (buffer, &map);
2341 gst_buffer_unref (buffer);
2342 buffer = NULL;
2343
2344 /* GStreamer's buffer sizes are stored in a guint so we
2345 * limit ourself to G_MAXUINT large buffers */
2346 if (length > G_MAXUINT) {
2347 GST_ERROR_OBJECT (demux,
2348 "Unsupported KLV packet length: %" G_GUINT64_FORMAT, length);
2349 ret = GST_FLOW_ERROR;
2350 goto beach;
2351 }
2352
2353 GST_DEBUG_OBJECT (demux, "KLV packet with key %s has length "
2354 "%" G_GUINT64_FORMAT, mxf_ul_to_string (key, str), length);
2355
2356 /* Pull the complete KLV packet */
2357 if ((ret = gst_mxf_demux_pull_range (demux, offset + data_offset, length,
2358 &buffer)) != GST_FLOW_OK)
2359 goto beach;
2360
2361 *outbuf = buffer;
2362 buffer = NULL;
2363 if (read)
2364 *read = data_offset + length;
2365
2366 beach:
2367 if (buffer)
2368 gst_buffer_unref (buffer);
2369
2370 return ret;
2371 }
2372
2373 static void
gst_mxf_demux_pull_random_index_pack(GstMXFDemux * demux)2374 gst_mxf_demux_pull_random_index_pack (GstMXFDemux * demux)
2375 {
2376 GstBuffer *buffer;
2377 gint64 filesize = -1;
2378 GstFormat fmt = GST_FORMAT_BYTES;
2379 guint32 pack_size;
2380 guint64 old_offset = demux->offset;
2381 MXFUL key;
2382 GstMapInfo map;
2383 GstFlowReturn flow_ret;
2384
2385 if (!gst_pad_peer_query_duration (demux->sinkpad, fmt, &filesize) ||
2386 fmt != GST_FORMAT_BYTES || filesize == -1) {
2387 GST_DEBUG_OBJECT (demux, "Can't query upstream size");
2388 return;
2389 }
2390
2391 g_assert (filesize > 4);
2392
2393 buffer = NULL;
2394 if (gst_mxf_demux_pull_range (demux, filesize - 4, 4, &buffer) != GST_FLOW_OK) {
2395 GST_DEBUG_OBJECT (demux, "Failed pulling last 4 bytes");
2396 return;
2397 }
2398
2399 gst_buffer_map (buffer, &map, GST_MAP_READ);
2400 pack_size = GST_READ_UINT32_BE (map.data);
2401 gst_buffer_unmap (buffer, &map);
2402
2403 gst_buffer_unref (buffer);
2404
2405 if (pack_size < 20) {
2406 GST_DEBUG_OBJECT (demux, "Too small pack size (%u bytes)", pack_size);
2407 return;
2408 } else if (pack_size > filesize - 20) {
2409 GST_DEBUG_OBJECT (demux, "Too large pack size (%u bytes)", pack_size);
2410 return;
2411 }
2412
2413 buffer = NULL;
2414 if (gst_mxf_demux_pull_range (demux, filesize - pack_size, 16,
2415 &buffer) != GST_FLOW_OK) {
2416 GST_DEBUG_OBJECT (demux, "Failed pulling random index pack key");
2417 return;
2418 }
2419
2420 gst_buffer_map (buffer, &map, GST_MAP_READ);
2421 memcpy (&key, map.data, 16);
2422 gst_buffer_unmap (buffer, &map);
2423 gst_buffer_unref (buffer);
2424
2425 if (!mxf_is_random_index_pack (&key)) {
2426 GST_DEBUG_OBJECT (demux, "No random index pack");
2427 return;
2428 }
2429
2430 demux->offset = filesize - pack_size;
2431 if (gst_mxf_demux_pull_klv_packet (demux, filesize - pack_size, &key,
2432 &buffer, NULL) != GST_FLOW_OK) {
2433 GST_DEBUG_OBJECT (demux, "Failed pulling random index pack");
2434 return;
2435 }
2436
2437 flow_ret = gst_mxf_demux_handle_random_index_pack (demux, &key, buffer);
2438 gst_buffer_unref (buffer);
2439 demux->offset = old_offset;
2440
2441 if (flow_ret == GST_FLOW_OK && !demux->index_table_segments_collected) {
2442 collect_index_table_segments (demux);
2443 demux->index_table_segments_collected = TRUE;
2444 }
2445 }
2446
2447 static void
gst_mxf_demux_parse_footer_metadata(GstMXFDemux * demux)2448 gst_mxf_demux_parse_footer_metadata (GstMXFDemux * demux)
2449 {
2450 guint64 old_offset = demux->offset;
2451 MXFUL key;
2452 GstBuffer *buffer = NULL;
2453 guint read = 0;
2454 GstFlowReturn flow = GST_FLOW_OK;
2455 GstMXFDemuxPartition *old_partition = demux->current_partition;
2456
2457 demux->current_partition = NULL;
2458
2459 gst_mxf_demux_reset_metadata (demux);
2460
2461 if (demux->footer_partition_pack_offset != 0) {
2462 demux->offset = demux->run_in + demux->footer_partition_pack_offset;
2463 } else {
2464 MXFRandomIndexPackEntry *entry =
2465 &g_array_index (demux->random_index_pack, MXFRandomIndexPackEntry,
2466 demux->random_index_pack->len - 1);
2467 demux->offset = entry->offset;
2468 }
2469
2470 next_try:
2471 flow =
2472 gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
2473 &read);
2474 if (G_UNLIKELY (flow != GST_FLOW_OK))
2475 goto out;
2476
2477 if (!mxf_is_partition_pack (&key))
2478 goto out;
2479
2480 if (gst_mxf_demux_handle_partition_pack (demux, &key, buffer) != GST_FLOW_OK)
2481 goto out;
2482
2483 demux->offset += read;
2484 gst_buffer_unref (buffer);
2485 buffer = NULL;
2486
2487 if (demux->current_partition->partition.header_byte_count == 0) {
2488 if (demux->current_partition->partition.this_partition == 0)
2489 goto out;
2490
2491 demux->offset =
2492 demux->run_in + demux->current_partition->partition.prev_partition;
2493 goto next_try;
2494 }
2495
2496 while (TRUE) {
2497 flow =
2498 gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
2499 &read);
2500 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
2501 if (!demux->current_partition->partition.prev_partition)
2502 goto out;
2503 demux->offset =
2504 demux->run_in + demux->current_partition->partition.prev_partition;
2505 goto next_try;
2506 }
2507
2508 if (mxf_is_fill (&key)) {
2509 demux->offset += read;
2510 gst_buffer_unref (buffer);
2511 buffer = NULL;
2512 } else if (mxf_is_primer_pack (&key)) {
2513 if (!demux->current_partition->primer.mappings) {
2514 if (gst_mxf_demux_handle_primer_pack (demux, &key,
2515 buffer) != GST_FLOW_OK) {
2516 demux->offset += read;
2517 gst_buffer_unref (buffer);
2518 buffer = NULL;
2519 if (!demux->current_partition->partition.prev_partition)
2520 goto out;
2521 demux->offset =
2522 demux->run_in +
2523 demux->current_partition->partition.prev_partition;
2524 goto next_try;
2525 }
2526 }
2527 demux->offset += read;
2528 gst_buffer_unref (buffer);
2529 buffer = NULL;
2530 break;
2531 } else {
2532 gst_buffer_unref (buffer);
2533 buffer = NULL;
2534 if (!demux->current_partition->partition.prev_partition)
2535 goto out;
2536 demux->offset =
2537 demux->run_in + demux->current_partition->partition.prev_partition;
2538 goto next_try;
2539 }
2540 }
2541
2542 /* parse metadata */
2543 while (demux->offset <
2544 demux->run_in + demux->current_partition->primer.offset +
2545 demux->current_partition->partition.header_byte_count) {
2546 flow =
2547 gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
2548 &read);
2549 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
2550 if (!demux->current_partition->partition.prev_partition)
2551 goto out;
2552 demux->offset =
2553 demux->run_in + demux->current_partition->partition.prev_partition;
2554 goto next_try;
2555 }
2556
2557 if (mxf_is_metadata (&key)) {
2558 flow = gst_mxf_demux_handle_metadata (demux, &key, buffer);
2559 demux->offset += read;
2560 gst_buffer_unref (buffer);
2561 buffer = NULL;
2562
2563 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
2564 gst_mxf_demux_reset_metadata (demux);
2565 if (!demux->current_partition->partition.prev_partition)
2566 goto out;
2567 demux->offset =
2568 demux->run_in + demux->current_partition->partition.prev_partition;
2569 goto next_try;
2570 }
2571 } else if (mxf_is_descriptive_metadata (&key)) {
2572 gst_mxf_demux_handle_descriptive_metadata (demux, &key, buffer);
2573 demux->offset += read;
2574 gst_buffer_unref (buffer);
2575 buffer = NULL;
2576 } else if (mxf_is_fill (&key)) {
2577 demux->offset += read;
2578 gst_buffer_unref (buffer);
2579 buffer = NULL;
2580 } else if (mxf_is_generic_container_system_item (&key) ||
2581 mxf_is_generic_container_essence_element (&key) ||
2582 mxf_is_avid_essence_container_essence_element (&key)) {
2583 demux->offset += read;
2584 gst_buffer_unref (buffer);
2585 buffer = NULL;
2586 break;
2587 } else {
2588 demux->offset += read;
2589 gst_buffer_unref (buffer);
2590 buffer = NULL;
2591 }
2592 }
2593
2594 /* resolve references etc */
2595 if (!demux->preface || gst_mxf_demux_resolve_references (demux) !=
2596 GST_FLOW_OK || gst_mxf_demux_update_tracks (demux) != GST_FLOW_OK) {
2597 demux->current_partition->parsed_metadata = TRUE;
2598 if (!demux->current_partition->partition.prev_partition)
2599 goto out;
2600 demux->offset =
2601 demux->run_in + demux->current_partition->partition.prev_partition;
2602 goto next_try;
2603 }
2604
2605 out:
2606 if (buffer)
2607 gst_buffer_unref (buffer);
2608
2609 demux->offset = old_offset;
2610 demux->current_partition = old_partition;
2611 }
2612
2613 static GstFlowReturn
gst_mxf_demux_handle_klv_packet(GstMXFDemux * demux,const MXFUL * key,GstBuffer * buffer,gboolean peek)2614 gst_mxf_demux_handle_klv_packet (GstMXFDemux * demux, const MXFUL * key,
2615 GstBuffer * buffer, gboolean peek)
2616 {
2617 #ifndef GST_DISABLE_GST_DEBUG
2618 gchar key_str[48];
2619 #endif
2620 GstFlowReturn ret = GST_FLOW_OK;
2621
2622 if (demux->update_metadata
2623 && demux->preface
2624 && (demux->offset >=
2625 demux->run_in + demux->current_partition->primer.offset +
2626 demux->current_partition->partition.header_byte_count ||
2627 mxf_is_generic_container_system_item (key) ||
2628 mxf_is_generic_container_essence_element (key) ||
2629 mxf_is_avid_essence_container_essence_element (key))) {
2630 demux->current_partition->parsed_metadata = TRUE;
2631 if ((ret = gst_mxf_demux_resolve_references (demux)) != GST_FLOW_OK ||
2632 (ret = gst_mxf_demux_update_tracks (demux)) != GST_FLOW_OK) {
2633 goto beach;
2634 }
2635 } else if (demux->metadata_resolved && demux->requested_package_string) {
2636 if ((ret = gst_mxf_demux_update_tracks (demux)) != GST_FLOW_OK) {
2637 goto beach;
2638 }
2639 }
2640
2641 if (!mxf_is_mxf_packet (key)) {
2642 GST_WARNING_OBJECT (demux,
2643 "Skipping non-MXF packet of size %" G_GSIZE_FORMAT " at offset %"
2644 G_GUINT64_FORMAT ", key: %s", gst_buffer_get_size (buffer),
2645 demux->offset, mxf_ul_to_string (key, key_str));
2646 } else if (mxf_is_partition_pack (key)) {
2647 ret = gst_mxf_demux_handle_partition_pack (demux, key, buffer);
2648
2649 /* If this partition contains the start of an essence container
2650 * set the positions of all essence streams to 0
2651 */
2652 if (ret == GST_FLOW_OK && demux->current_partition
2653 && demux->current_partition->partition.body_sid != 0
2654 && demux->current_partition->partition.body_offset == 0) {
2655 guint i;
2656
2657 for (i = 0; i < demux->essence_tracks->len; i++) {
2658 GstMXFDemuxEssenceTrack *etrack =
2659 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
2660
2661 if (etrack->body_sid != demux->current_partition->partition.body_sid)
2662 continue;
2663
2664 etrack->position = 0;
2665 }
2666 }
2667 } else if (mxf_is_primer_pack (key)) {
2668 ret = gst_mxf_demux_handle_primer_pack (demux, key, buffer);
2669 } else if (mxf_is_metadata (key)) {
2670 ret = gst_mxf_demux_handle_metadata (demux, key, buffer);
2671 } else if (mxf_is_descriptive_metadata (key)) {
2672 ret = gst_mxf_demux_handle_descriptive_metadata (demux, key, buffer);
2673 } else if (mxf_is_generic_container_system_item (key)) {
2674 ret =
2675 gst_mxf_demux_handle_generic_container_system_item (demux, key, buffer);
2676 } else if (mxf_is_generic_container_essence_element (key) ||
2677 mxf_is_avid_essence_container_essence_element (key)) {
2678 ret =
2679 gst_mxf_demux_handle_generic_container_essence_element (demux, key,
2680 buffer, peek);
2681 } else if (mxf_is_random_index_pack (key)) {
2682 ret = gst_mxf_demux_handle_random_index_pack (demux, key, buffer);
2683
2684 if (ret == GST_FLOW_OK && demux->random_access
2685 && !demux->index_table_segments_collected) {
2686 collect_index_table_segments (demux);
2687 demux->index_table_segments_collected = TRUE;
2688 }
2689 } else if (mxf_is_index_table_segment (key)) {
2690 ret =
2691 gst_mxf_demux_handle_index_table_segment (demux, key, buffer,
2692 demux->offset);
2693 } else if (mxf_is_fill (key)) {
2694 GST_DEBUG_OBJECT (demux,
2695 "Skipping filler packet of size %" G_GSIZE_FORMAT " at offset %"
2696 G_GUINT64_FORMAT, gst_buffer_get_size (buffer), demux->offset);
2697 } else {
2698 GST_DEBUG_OBJECT (demux,
2699 "Skipping unknown packet of size %" G_GSIZE_FORMAT " at offset %"
2700 G_GUINT64_FORMAT ", key: %s", gst_buffer_get_size (buffer),
2701 demux->offset, mxf_ul_to_string (key, key_str));
2702 }
2703
2704 /* In pull mode try to get the last metadata */
2705 if (mxf_is_partition_pack (key) && ret == GST_FLOW_OK
2706 && demux->pull_footer_metadata
2707 && demux->random_access && demux->current_partition
2708 && demux->current_partition->partition.type == MXF_PARTITION_PACK_HEADER
2709 && (!demux->current_partition->partition.closed
2710 || !demux->current_partition->partition.complete)
2711 && (demux->footer_partition_pack_offset != 0 || demux->random_index_pack)) {
2712 GST_DEBUG_OBJECT (demux,
2713 "Open or incomplete header partition, trying to get final metadata from the last partitions");
2714 gst_mxf_demux_parse_footer_metadata (demux);
2715 demux->pull_footer_metadata = FALSE;
2716
2717 if (demux->current_partition->partition.body_sid != 0 &&
2718 demux->current_partition->partition.body_offset == 0) {
2719 guint i;
2720 for (i = 0; i < demux->essence_tracks->len; i++) {
2721 GstMXFDemuxEssenceTrack *etrack =
2722 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
2723
2724 if (etrack->body_sid != demux->current_partition->partition.body_sid)
2725 continue;
2726
2727 etrack->position = 0;
2728 }
2729 }
2730 }
2731
2732 beach:
2733 return ret;
2734 }
2735
2736 static void
gst_mxf_demux_set_partition_for_offset(GstMXFDemux * demux,guint64 offset)2737 gst_mxf_demux_set_partition_for_offset (GstMXFDemux * demux, guint64 offset)
2738 {
2739 GList *l;
2740
2741 /* This partition will already be parsed, otherwise
2742 * the position wouldn't be in the index */
2743 for (l = demux->partitions; l; l = l->next) {
2744 GstMXFDemuxPartition *p = l->data;
2745
2746 if (p->partition.this_partition + demux->run_in <= offset)
2747 demux->current_partition = p;
2748 }
2749 }
2750
2751 static guint64
find_offset(GArray * offsets,gint64 * position,gboolean keyframe)2752 find_offset (GArray * offsets, gint64 * position, gboolean keyframe)
2753 {
2754 GstMXFDemuxIndex *idx;
2755 guint64 current_offset = -1;
2756 gint64 current_position = *position;
2757
2758 if (!offsets || offsets->len <= *position)
2759 return -1;
2760
2761 idx = &g_array_index (offsets, GstMXFDemuxIndex, *position);
2762 if (idx->offset != 0 && (!keyframe || idx->keyframe)) {
2763 current_offset = idx->offset;
2764 } else if (idx->offset != 0) {
2765 current_position--;
2766 while (current_position >= 0) {
2767 idx = &g_array_index (offsets, GstMXFDemuxIndex, current_position);
2768 if (idx->offset == 0) {
2769 break;
2770 } else if (!idx->keyframe) {
2771 current_position--;
2772 continue;
2773 } else {
2774 current_offset = idx->offset;
2775 break;
2776 }
2777 }
2778 }
2779
2780 if (current_offset == -1)
2781 return -1;
2782
2783 *position = current_position;
2784 return current_offset;
2785 }
2786
2787 static guint64
find_closest_offset(GArray * offsets,gint64 * position,gboolean keyframe)2788 find_closest_offset (GArray * offsets, gint64 * position, gboolean keyframe)
2789 {
2790 GstMXFDemuxIndex *idx;
2791 gint64 current_position = *position;
2792
2793 if (!offsets || offsets->len == 0)
2794 return -1;
2795
2796 current_position = MIN (current_position, offsets->len - 1);
2797
2798 idx = &g_array_index (offsets, GstMXFDemuxIndex, current_position);
2799 while (idx->offset == 0 || (keyframe && !idx->keyframe)) {
2800 current_position--;
2801 if (current_position < 0)
2802 break;
2803 idx = &g_array_index (offsets, GstMXFDemuxIndex, current_position);
2804 }
2805
2806 if (idx->offset != 0 && (!keyframe || idx->keyframe)) {
2807 *position = current_position;
2808 return idx->offset;
2809 }
2810
2811 return -1;
2812 }
2813
2814 static guint64
gst_mxf_demux_find_essence_element(GstMXFDemux * demux,GstMXFDemuxEssenceTrack * etrack,gint64 * position,gboolean keyframe)2815 gst_mxf_demux_find_essence_element (GstMXFDemux * demux,
2816 GstMXFDemuxEssenceTrack * etrack, gint64 * position, gboolean keyframe)
2817 {
2818 GstFlowReturn ret = GST_FLOW_OK;
2819 guint64 old_offset = demux->offset;
2820 GstMXFDemuxPartition *old_partition = demux->current_partition;
2821 gint i;
2822 guint64 offset;
2823 gint64 requested_position = *position;
2824 GstMXFDemuxIndexTable *index_table = NULL;
2825
2826 GST_DEBUG_OBJECT (demux, "Trying to find essence element %" G_GINT64_FORMAT
2827 " of track %u with body_sid %u (keyframe %d)", *position,
2828 etrack->track_number, etrack->body_sid, keyframe);
2829
2830 if (demux->index_tables) {
2831 GList *l;
2832
2833 for (l = demux->index_tables; l; l = l->next) {
2834 GstMXFDemuxIndexTable *tmp = l->data;
2835
2836 if (tmp->body_sid == etrack->body_sid
2837 && tmp->index_sid == etrack->index_sid) {
2838 index_table = tmp;
2839 break;
2840 }
2841 }
2842 }
2843
2844 from_index:
2845
2846 if (etrack->duration > 0 && *position >= etrack->duration) {
2847 GST_WARNING_OBJECT (demux, "Position after end of essence track");
2848 return -1;
2849 }
2850
2851 /* First try to find an offset in our index */
2852 offset = find_offset (etrack->offsets, position, keyframe);
2853 if (offset != -1) {
2854 GST_DEBUG_OBJECT (demux,
2855 "Found edit unit %" G_GINT64_FORMAT " for %" G_GINT64_FORMAT
2856 " in generated index at offset %" G_GUINT64_FORMAT, *position,
2857 requested_position, offset);
2858 return offset;
2859 }
2860
2861 GST_DEBUG_OBJECT (demux, "Not found in index");
2862 if (!demux->random_access) {
2863 offset = find_closest_offset (etrack->offsets, position, keyframe);
2864 if (offset != -1) {
2865 GST_DEBUG_OBJECT (demux,
2866 "Starting with edit unit %" G_GINT64_FORMAT " for %" G_GINT64_FORMAT
2867 " in generated index at offset %" G_GUINT64_FORMAT, *position,
2868 requested_position, offset);
2869 return offset;
2870 }
2871
2872 if (index_table) {
2873 offset = find_closest_offset (index_table->offsets, position, keyframe);
2874 if (offset != -1) {
2875 GST_DEBUG_OBJECT (demux,
2876 "Starting with edit unit %" G_GINT64_FORMAT " for %" G_GINT64_FORMAT
2877 " in index at offset %" G_GUINT64_FORMAT, *position,
2878 requested_position, offset);
2879 return offset;
2880 }
2881 }
2882 } else if (demux->random_access) {
2883 gint64 index_start_position = *position;
2884
2885 demux->offset = demux->run_in;
2886
2887 offset =
2888 find_closest_offset (etrack->offsets, &index_start_position, FALSE);
2889 if (offset != -1) {
2890 demux->offset = offset + demux->run_in;
2891 GST_DEBUG_OBJECT (demux,
2892 "Starting with edit unit %" G_GINT64_FORMAT " for %" G_GINT64_FORMAT
2893 " in generated index at offset %" G_GUINT64_FORMAT,
2894 index_start_position, requested_position, offset);
2895 } else {
2896 index_start_position = -1;
2897 }
2898
2899 if (index_table) {
2900 gint64 tmp_position = *position;
2901
2902 offset = find_closest_offset (index_table->offsets, &tmp_position, TRUE);
2903 if (offset != -1 && tmp_position > index_start_position) {
2904 demux->offset = offset + demux->run_in;
2905 index_start_position = tmp_position;
2906 GST_DEBUG_OBJECT (demux,
2907 "Starting with edit unit %" G_GINT64_FORMAT " for %" G_GINT64_FORMAT
2908 " in index at offset %" G_GUINT64_FORMAT, index_start_position,
2909 requested_position, offset);
2910 }
2911 }
2912
2913 gst_mxf_demux_set_partition_for_offset (demux, demux->offset);
2914
2915 for (i = 0; i < demux->essence_tracks->len; i++) {
2916 GstMXFDemuxEssenceTrack *t =
2917 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
2918
2919 if (index_start_position != -1 && t == etrack)
2920 t->position = index_start_position;
2921 else
2922 t->position = (demux->offset == demux->run_in) ? 0 : -1;
2923 }
2924
2925 /* Else peek at all essence elements and complete our
2926 * index until we find the requested element
2927 */
2928 while (ret == GST_FLOW_OK) {
2929 GstBuffer *buffer = NULL;
2930 MXFUL key;
2931 guint read = 0;
2932
2933 ret =
2934 gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
2935 &read);
2936
2937 if (ret == GST_FLOW_EOS) {
2938 for (i = 0; i < demux->essence_tracks->len; i++) {
2939 GstMXFDemuxEssenceTrack *t =
2940 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack,
2941 i);
2942
2943 if (t->position > 0)
2944 t->duration = t->position;
2945 }
2946 /* For the searched track this is really our position */
2947 etrack->duration = etrack->position;
2948
2949 for (i = 0; i < demux->src->len; i++) {
2950 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
2951
2952 if (!p->eos
2953 && p->current_essence_track_position >=
2954 p->current_essence_track->duration) {
2955 GstEvent *e;
2956
2957 p->eos = TRUE;
2958 e = gst_event_new_eos ();
2959 gst_event_set_seqnum (e, demux->seqnum);
2960 gst_pad_push_event (GST_PAD_CAST (p), e);
2961 }
2962 }
2963 }
2964
2965 if (G_UNLIKELY (ret != GST_FLOW_OK) && etrack->position <= *position) {
2966 demux->offset = old_offset;
2967 demux->current_partition = old_partition;
2968 break;
2969 } else if (G_UNLIKELY (ret == GST_FLOW_OK)) {
2970 ret = gst_mxf_demux_handle_klv_packet (demux, &key, buffer, TRUE);
2971 gst_buffer_unref (buffer);
2972 }
2973
2974 /* If we found the position read it from the index again */
2975 if (((ret == GST_FLOW_OK && etrack->position == *position + 2) ||
2976 (ret == GST_FLOW_EOS && etrack->position == *position + 1))
2977 && etrack->offsets && etrack->offsets->len > *position
2978 && g_array_index (etrack->offsets, GstMXFDemuxIndex,
2979 *position).offset != 0) {
2980 GST_DEBUG_OBJECT (demux, "Found at offset %" G_GUINT64_FORMAT,
2981 demux->offset);
2982 demux->offset = old_offset;
2983 demux->current_partition = old_partition;
2984 goto from_index;
2985 }
2986 demux->offset += read;
2987 }
2988 demux->offset = old_offset;
2989 demux->current_partition = old_partition;
2990
2991 GST_DEBUG_OBJECT (demux, "Not found in this file");
2992 }
2993
2994 return -1;
2995 }
2996
2997 static GstFlowReturn
gst_mxf_demux_pull_and_handle_klv_packet(GstMXFDemux * demux)2998 gst_mxf_demux_pull_and_handle_klv_packet (GstMXFDemux * demux)
2999 {
3000 GstBuffer *buffer = NULL;
3001 MXFUL key;
3002 GstFlowReturn ret = GST_FLOW_OK;
3003 guint read = 0;
3004
3005 if (demux->src->len > 0) {
3006 if (!gst_mxf_demux_get_earliest_pad (demux)) {
3007 ret = GST_FLOW_EOS;
3008 GST_DEBUG_OBJECT (demux, "All tracks are EOS");
3009 goto beach;
3010 }
3011 }
3012
3013 ret =
3014 gst_mxf_demux_pull_klv_packet (demux, demux->offset, &key, &buffer,
3015 &read);
3016
3017 if (ret == GST_FLOW_EOS && demux->src->len > 0) {
3018 guint i;
3019 GstMXFDemuxPad *p = NULL;
3020
3021 for (i = 0; i < demux->essence_tracks->len; i++) {
3022 GstMXFDemuxEssenceTrack *t =
3023 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
3024
3025 if (t->position > 0)
3026 t->duration = t->position;
3027 }
3028
3029 for (i = 0; i < demux->src->len; i++) {
3030 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
3031
3032 if (!p->eos
3033 && p->current_essence_track_position >=
3034 p->current_essence_track->duration) {
3035 GstEvent *e;
3036
3037 p->eos = TRUE;
3038 e = gst_event_new_eos ();
3039 gst_event_set_seqnum (e, demux->seqnum);
3040 gst_pad_push_event (GST_PAD_CAST (p), e);
3041 }
3042 }
3043
3044 while ((p = gst_mxf_demux_get_earliest_pad (demux))) {
3045 guint64 offset;
3046 gint64 position;
3047
3048 position = p->current_essence_track_position;
3049
3050 offset =
3051 gst_mxf_demux_find_essence_element (demux, p->current_essence_track,
3052 &position, FALSE);
3053 if (offset == -1) {
3054 GstEvent *e;
3055
3056 GST_ERROR_OBJECT (demux, "Failed to find offset for essence track");
3057 p->eos = TRUE;
3058 e = gst_event_new_eos ();
3059 gst_event_set_seqnum (e, demux->seqnum);
3060 gst_pad_push_event (GST_PAD_CAST (p), e);
3061 continue;
3062 }
3063
3064 demux->offset = offset + demux->run_in;
3065 gst_mxf_demux_set_partition_for_offset (demux, demux->offset);
3066
3067 p->current_essence_track->position = position;
3068
3069 ret = GST_FLOW_OK;
3070 goto beach;
3071 }
3072 }
3073
3074 if (G_UNLIKELY (ret != GST_FLOW_OK))
3075 goto beach;
3076
3077 ret = gst_mxf_demux_handle_klv_packet (demux, &key, buffer, FALSE);
3078 demux->offset += read;
3079
3080 if (ret == GST_FLOW_OK && demux->src->len > 0
3081 && demux->essence_tracks->len > 0) {
3082 GstMXFDemuxPad *earliest = NULL;
3083 /* We allow time drifts of at most 500ms */
3084 while ((earliest = gst_mxf_demux_get_earliest_pad (demux)) &&
3085 demux->segment.position - earliest->position > demux->max_drift) {
3086 guint64 offset;
3087 gint64 position;
3088
3089 GST_WARNING_OBJECT (demux,
3090 "Found synchronization issue -- trying to solve");
3091
3092 position = earliest->current_essence_track_position;
3093
3094 /* FIXME: This can probably be improved by using the
3095 * offset of position-1 if it's in the same partition
3096 * or the start of the position otherwise.
3097 * This way we won't skip elements from the same essence
3098 * container as etrack->position
3099 */
3100 offset =
3101 gst_mxf_demux_find_essence_element (demux,
3102 earliest->current_essence_track, &position, FALSE);
3103 if (offset == -1) {
3104 GstEvent *e;
3105
3106 GST_WARNING_OBJECT (demux,
3107 "Failed to find offset for late essence track");
3108 earliest->eos = TRUE;
3109 e = gst_event_new_eos ();
3110 gst_event_set_seqnum (e, demux->seqnum);
3111 gst_pad_push_event (GST_PAD_CAST (earliest), e);
3112 continue;
3113 }
3114
3115 demux->offset = offset + demux->run_in;
3116 gst_mxf_demux_set_partition_for_offset (demux, demux->offset);
3117
3118 earliest->current_essence_track->position = position;
3119 break;
3120 }
3121 }
3122
3123 beach:
3124 if (buffer)
3125 gst_buffer_unref (buffer);
3126
3127 return ret;
3128 }
3129
3130 static void
gst_mxf_demux_loop(GstPad * pad)3131 gst_mxf_demux_loop (GstPad * pad)
3132 {
3133 GstMXFDemux *demux = NULL;
3134 GstFlowReturn flow = GST_FLOW_OK;
3135 GstMapInfo map;
3136 gboolean res;
3137
3138 demux = GST_MXF_DEMUX (gst_pad_get_parent (pad));
3139
3140 if (demux->run_in == -1) {
3141 /* Skip run-in, which is at most 64K and is finished
3142 * by a header partition pack */
3143 while (demux->offset < 64 * 1024) {
3144 GstBuffer *buffer = NULL;
3145
3146 if ((flow =
3147 gst_mxf_demux_pull_range (demux, demux->offset, 16,
3148 &buffer)) != GST_FLOW_OK)
3149 break;
3150
3151 gst_buffer_map (buffer, &map, GST_MAP_READ);
3152 res = mxf_is_header_partition_pack ((const MXFUL *) map.data);
3153 gst_buffer_unmap (buffer, &map);
3154
3155 if (res) {
3156 GST_DEBUG_OBJECT (demux,
3157 "Found header partition pack at offset %" G_GUINT64_FORMAT,
3158 demux->offset);
3159 demux->run_in = demux->offset;
3160 gst_buffer_unref (buffer);
3161 break;
3162 }
3163
3164 demux->offset++;
3165 gst_buffer_unref (buffer);
3166 }
3167
3168 if (G_UNLIKELY (flow != GST_FLOW_OK))
3169 goto pause;
3170
3171 if (G_UNLIKELY (demux->run_in == -1)) {
3172 GST_ERROR_OBJECT (demux, "No valid header partition pack found");
3173 flow = GST_FLOW_ERROR;
3174 goto pause;
3175 }
3176
3177 /* First of all pull&parse the random index pack at EOF */
3178 gst_mxf_demux_pull_random_index_pack (demux);
3179 }
3180
3181 /* Now actually do something */
3182 flow = gst_mxf_demux_pull_and_handle_klv_packet (demux);
3183
3184 /* pause if something went wrong */
3185 if (G_UNLIKELY (flow != GST_FLOW_OK))
3186 goto pause;
3187
3188 /* check EOS condition */
3189 if ((demux->segment.flags & GST_SEEK_FLAG_SEGMENT) &&
3190 (demux->segment.stop != -1) &&
3191 (demux->segment.position >= demux->segment.stop)) {
3192 guint i;
3193 gboolean eos = TRUE;
3194
3195 for (i = 0; i < demux->src->len; i++) {
3196 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
3197
3198 if (!p->eos && p->position < demux->segment.stop) {
3199 eos = FALSE;
3200 break;
3201 }
3202 }
3203
3204 if (eos) {
3205 flow = GST_FLOW_EOS;
3206 goto pause;
3207 }
3208 }
3209
3210 gst_object_unref (demux);
3211
3212 return;
3213
3214 pause:
3215 {
3216 const gchar *reason = gst_flow_get_name (flow);
3217
3218 GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
3219 gst_pad_pause_task (pad);
3220
3221 if (flow == GST_FLOW_EOS) {
3222 /* perform EOS logic */
3223 if (demux->src->len == 0) {
3224 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE,
3225 ("This stream contains no data."),
3226 ("got eos and didn't find any streams"));
3227 } else if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
3228 gint64 stop;
3229 GstMessage *m;
3230 GstEvent *e;
3231
3232 /* for segment playback we need to post when (in stream time)
3233 * we stopped, this is either stop (when set) or the duration. */
3234 if ((stop = demux->segment.stop) == -1)
3235 stop = demux->segment.duration;
3236
3237 GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
3238 m = gst_message_new_segment_done (GST_OBJECT_CAST (demux),
3239 GST_FORMAT_TIME, stop);
3240 gst_message_set_seqnum (m, demux->seqnum);
3241 gst_element_post_message (GST_ELEMENT_CAST (demux), m);
3242 e = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
3243 gst_event_set_seqnum (e, demux->seqnum);
3244 gst_mxf_demux_push_src_event (demux, e);
3245 } else {
3246 GstEvent *e;
3247
3248 /* normal playback, send EOS to all linked pads */
3249 GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
3250 e = gst_event_new_eos ();
3251 gst_event_set_seqnum (e, demux->seqnum);
3252 if (!gst_mxf_demux_push_src_event (demux, e)) {
3253 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
3254 }
3255 }
3256 } else if (flow == GST_FLOW_NOT_LINKED || flow < GST_FLOW_EOS) {
3257 GstEvent *e;
3258
3259 GST_ELEMENT_FLOW_ERROR (demux, flow);
3260 e = gst_event_new_eos ();
3261 gst_event_set_seqnum (e, demux->seqnum);
3262 gst_mxf_demux_push_src_event (demux, e);
3263 }
3264 gst_object_unref (demux);
3265 return;
3266 }
3267 }
3268
3269 static GstFlowReturn
gst_mxf_demux_chain(GstPad * pad,GstObject * parent,GstBuffer * inbuf)3270 gst_mxf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * inbuf)
3271 {
3272 GstFlowReturn ret = GST_FLOW_OK;
3273 GstMXFDemux *demux = NULL;
3274 MXFUL key;
3275 const guint8 *data = NULL;
3276 guint64 length = 0;
3277 guint64 offset = 0;
3278 GstBuffer *buffer = NULL;
3279 gboolean res;
3280 #ifndef GST_DISABLE_GST_DEBUG
3281 gchar str[48];
3282 #endif
3283
3284 demux = GST_MXF_DEMUX (parent);
3285
3286 GST_LOG_OBJECT (demux,
3287 "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
3288 G_GUINT64_FORMAT, gst_buffer_get_size (inbuf), GST_BUFFER_OFFSET (inbuf));
3289
3290 if (demux->src->len > 0) {
3291 if (!gst_mxf_demux_get_earliest_pad (demux)) {
3292 ret = GST_FLOW_EOS;
3293 GST_DEBUG_OBJECT (demux, "All tracks are EOS");
3294 return ret;
3295 }
3296 }
3297
3298 if (G_UNLIKELY (GST_BUFFER_OFFSET (inbuf) == 0)) {
3299 GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
3300 demux->run_in = -1;
3301 demux->offset = 0;
3302 }
3303
3304 if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (inbuf) != 0)) {
3305 GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's");
3306 if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
3307 demux->offset = GST_BUFFER_OFFSET (inbuf);
3308 gst_mxf_demux_set_partition_for_offset (demux, demux->offset);
3309 } else if (demux->current_partition == NULL) {
3310 gst_mxf_demux_set_partition_for_offset (demux, demux->offset);
3311 }
3312
3313 gst_adapter_push (demux->adapter, inbuf);
3314 inbuf = NULL;
3315
3316 while (ret == GST_FLOW_OK) {
3317 if (G_UNLIKELY (demux->flushing)) {
3318 GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
3319 ret = GST_FLOW_FLUSHING;
3320 break;
3321 }
3322
3323 if (gst_adapter_available (demux->adapter) < 16)
3324 break;
3325
3326 if (demux->run_in == -1) {
3327 /* Skip run-in, which is at most 64K and is finished
3328 * by a header partition pack */
3329
3330 while (demux->offset < 64 * 1024
3331 && gst_adapter_available (demux->adapter) >= 16) {
3332 data = gst_adapter_map (demux->adapter, 16);
3333 res = mxf_is_header_partition_pack ((const MXFUL *) data);
3334 gst_adapter_unmap (demux->adapter);
3335
3336 if (res) {
3337 GST_DEBUG_OBJECT (demux,
3338 "Found header partition pack at offset %" G_GUINT64_FORMAT,
3339 demux->offset);
3340 demux->run_in = demux->offset;
3341 break;
3342 }
3343 gst_adapter_flush (demux->adapter, 1);
3344 demux->offset++;
3345 }
3346 } else if (demux->offset < demux->run_in) {
3347 guint64 flush = MIN (gst_adapter_available (demux->adapter),
3348 demux->run_in - demux->offset);
3349 gst_adapter_flush (demux->adapter, flush);
3350 demux->offset += flush;
3351 continue;
3352 }
3353
3354 /* Need more data */
3355 if (demux->run_in == -1 && demux->offset < 64 * 1024)
3356 break;
3357
3358 if (G_UNLIKELY (demux->run_in == -1)) {
3359 GST_ERROR_OBJECT (demux, "No valid header partition pack found");
3360 ret = GST_FLOW_ERROR;
3361 break;
3362 }
3363
3364 if (gst_adapter_available (demux->adapter) < 17)
3365 break;
3366
3367 /* Now actually do something */
3368 memset (&key, 0, sizeof (MXFUL));
3369
3370 /* Pull 16 byte key and first byte of BER encoded length */
3371 data = gst_adapter_map (demux->adapter, 17);
3372
3373 memcpy (&key, data, 16);
3374
3375 GST_DEBUG_OBJECT (demux, "Got KLV packet with key %s",
3376 mxf_ul_to_string (&key, str));
3377
3378 /* Decode BER encoded packet length */
3379 if ((data[16] & 0x80) == 0) {
3380 length = data[16];
3381 offset = 17;
3382 } else {
3383 guint slen = data[16] & 0x7f;
3384
3385 offset = 16 + 1 + slen;
3386
3387 gst_adapter_unmap (demux->adapter);
3388
3389 /* Must be at most 8 according to SMPTE-379M 5.3.4 and
3390 * GStreamer buffers can only have a 4 bytes length */
3391 if (slen > 8) {
3392 GST_ERROR_OBJECT (demux, "Invalid KLV packet length: %u", slen);
3393 ret = GST_FLOW_ERROR;
3394 break;
3395 }
3396
3397 if (gst_adapter_available (demux->adapter) < 17 + slen)
3398 break;
3399
3400 data = gst_adapter_map (demux->adapter, 17 + slen);
3401 data += 17;
3402
3403 length = 0;
3404 while (slen) {
3405 length = (length << 8) | *data;
3406 data++;
3407 slen--;
3408 }
3409 }
3410
3411 gst_adapter_unmap (demux->adapter);
3412
3413 /* GStreamer's buffer sizes are stored in a guint so we
3414 * limit ourself to G_MAXUINT large buffers */
3415 if (length > G_MAXUINT) {
3416 GST_ERROR_OBJECT (demux,
3417 "Unsupported KLV packet length: %" G_GUINT64_FORMAT, length);
3418 ret = GST_FLOW_ERROR;
3419 break;
3420 }
3421
3422 GST_DEBUG_OBJECT (demux, "KLV packet with key %s has length "
3423 "%" G_GUINT64_FORMAT, mxf_ul_to_string (&key, str), length);
3424
3425 if (gst_adapter_available (demux->adapter) < offset + length)
3426 break;
3427
3428 gst_adapter_flush (demux->adapter, offset);
3429
3430 if (length > 0) {
3431 buffer = gst_adapter_take_buffer (demux->adapter, length);
3432
3433 ret = gst_mxf_demux_handle_klv_packet (demux, &key, buffer, FALSE);
3434 gst_buffer_unref (buffer);
3435 }
3436
3437 demux->offset += offset + length;
3438 }
3439
3440 return ret;
3441 }
3442
3443 static void
gst_mxf_demux_pad_set_position(GstMXFDemux * demux,GstMXFDemuxPad * p,GstClockTime start)3444 gst_mxf_demux_pad_set_position (GstMXFDemux * demux, GstMXFDemuxPad * p,
3445 GstClockTime start)
3446 {
3447 guint i;
3448 guint64 sum = 0;
3449 MXFMetadataSourceClip *clip = NULL;
3450
3451 if (!p->current_component) {
3452 p->current_essence_track_position =
3453 gst_util_uint64_scale (start, p->material_track->edit_rate.n,
3454 p->material_track->edit_rate.d * GST_SECOND);
3455
3456 if (p->current_essence_track_position >= p->current_essence_track->duration
3457 && p->current_essence_track->duration > 0) {
3458 p->current_essence_track_position = p->current_essence_track->duration;
3459 p->position =
3460 gst_util_uint64_scale (p->current_essence_track->duration,
3461 p->material_track->edit_rate.d * GST_SECOND,
3462 p->material_track->edit_rate.n);
3463 } else {
3464 p->position = start;
3465 }
3466 p->position_accumulated_error = 0.0;
3467 p->current_material_track_position = p->current_essence_track_position;
3468
3469 return;
3470 }
3471
3472 for (i = 0; i < p->material_track->parent.sequence->n_structural_components;
3473 i++) {
3474 clip =
3475 MXF_METADATA_SOURCE_CLIP (p->material_track->parent.sequence->
3476 structural_components[i]);
3477
3478 if (clip->parent.duration <= 0)
3479 break;
3480
3481 sum += clip->parent.duration;
3482
3483 if (gst_util_uint64_scale (sum, p->material_track->edit_rate.d * GST_SECOND,
3484 p->material_track->edit_rate.n) > start)
3485 break;
3486 }
3487
3488 if (i == p->material_track->parent.sequence->n_structural_components) {
3489 p->position =
3490 gst_util_uint64_scale (sum, p->material_track->edit_rate.d * GST_SECOND,
3491 p->material_track->edit_rate.n);
3492 p->position_accumulated_error = 0.0;
3493 p->current_material_track_position = sum;
3494
3495 gst_mxf_demux_pad_set_component (demux, p, i);
3496 return;
3497 }
3498
3499 if (clip->parent.duration > 0)
3500 sum -= clip->parent.duration;
3501
3502 start -=
3503 gst_util_uint64_scale (sum, p->material_track->edit_rate.d * GST_SECOND,
3504 p->material_track->edit_rate.n);
3505
3506 gst_mxf_demux_pad_set_component (demux, p, i);
3507
3508 {
3509 gint64 essence_offset = gst_util_uint64_scale (start,
3510 p->current_essence_track->source_track->edit_rate.n,
3511 p->current_essence_track->source_track->edit_rate.d * GST_SECOND);
3512
3513 p->current_essence_track_position += essence_offset;
3514
3515 p->position = gst_util_uint64_scale (sum,
3516 GST_SECOND * p->material_track->edit_rate.d,
3517 p->material_track->edit_rate.n) + gst_util_uint64_scale (essence_offset,
3518 GST_SECOND * p->current_essence_track->source_track->edit_rate.d,
3519 p->current_essence_track->source_track->edit_rate.n);
3520 p->position_accumulated_error = 0.0;
3521 p->current_material_track_position = sum + essence_offset;
3522 }
3523
3524 if (p->current_essence_track_position >= p->current_essence_track->duration
3525 && p->current_essence_track->duration > 0) {
3526 p->current_essence_track_position = p->current_essence_track->duration;
3527 p->position =
3528 gst_util_uint64_scale (sum + p->current_component->parent.duration,
3529 p->material_track->edit_rate.d * GST_SECOND,
3530 p->material_track->edit_rate.n);
3531 p->position_accumulated_error = 0.0;
3532 p->current_material_track_position =
3533 sum + p->current_component->parent.duration;
3534 }
3535 }
3536
3537 static gboolean
gst_mxf_demux_seek_push(GstMXFDemux * demux,GstEvent * event)3538 gst_mxf_demux_seek_push (GstMXFDemux * demux, GstEvent * event)
3539 {
3540 GstFormat format;
3541 GstSeekFlags flags;
3542 GstSeekType start_type, stop_type;
3543 gint64 start, stop;
3544 gdouble rate;
3545 gboolean update, flush, keyframe;
3546 GstSegment seeksegment;
3547 guint i;
3548 guint32 seqnum;
3549
3550 gst_event_parse_seek (event, &rate, &format, &flags,
3551 &start_type, &start, &stop_type, &stop);
3552 seqnum = gst_event_get_seqnum (event);
3553
3554 if (rate <= 0.0)
3555 goto wrong_rate;
3556
3557 if (format != GST_FORMAT_TIME)
3558 goto wrong_format;
3559
3560 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
3561 keyframe = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
3562
3563 /* Work on a copy until we are sure the seek succeeded. */
3564 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
3565
3566 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
3567 &demux->segment);
3568
3569 /* Apply the seek to our segment */
3570 gst_segment_do_seek (&seeksegment, rate, format, flags,
3571 start_type, start, stop_type, stop, &update);
3572
3573 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
3574 &seeksegment);
3575
3576 if (flush || seeksegment.position != demux->segment.position) {
3577 gboolean ret;
3578 guint64 new_offset = -1;
3579 GstEvent *e;
3580
3581 if (!demux->metadata_resolved || demux->update_metadata) {
3582 if (gst_mxf_demux_resolve_references (demux) != GST_FLOW_OK ||
3583 gst_mxf_demux_update_tracks (demux) != GST_FLOW_OK) {
3584 goto unresolved_metadata;
3585 }
3586 }
3587
3588 /* Do the actual seeking */
3589 for (i = 0; i < demux->src->len; i++) {
3590 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
3591 gint64 position;
3592 guint64 off;
3593
3594 /* Reset EOS flag on all pads */
3595 p->eos = FALSE;
3596 gst_mxf_demux_pad_set_position (demux, p, start);
3597
3598 position = p->current_essence_track_position;
3599 off = gst_mxf_demux_find_essence_element (demux, p->current_essence_track,
3600 &position, keyframe);
3601 new_offset = MIN (off, new_offset);
3602 p->discont = TRUE;
3603 }
3604
3605 if (new_offset == -1)
3606 goto no_new_offset;
3607
3608 new_offset += demux->run_in;
3609
3610 GST_DEBUG_OBJECT (demux, "generating an upstream seek at position %"
3611 G_GUINT64_FORMAT, new_offset);
3612 e = gst_event_new_seek (seeksegment.rate, GST_FORMAT_BYTES,
3613 seeksegment.flags | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
3614 new_offset, GST_SEEK_TYPE_NONE, 0);
3615 gst_event_set_seqnum (e, seqnum);
3616 ret = gst_pad_push_event (demux->sinkpad, e);
3617
3618 if (G_UNLIKELY (!ret)) {
3619 goto seek_failed;
3620 }
3621 }
3622
3623 /* Tell all the stream a new segment is needed */
3624 for (i = 0; i < demux->src->len; i++) {
3625 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
3626 p->need_segment = TRUE;
3627 }
3628
3629 for (i = 0; i < demux->essence_tracks->len; i++) {
3630 GstMXFDemuxEssenceTrack *t =
3631 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
3632 t->position = -1;
3633 }
3634
3635 /* Ok seek succeeded, take the newly configured segment */
3636 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
3637
3638 return TRUE;
3639
3640 /* ERRORS */
3641 wrong_format:
3642 {
3643 GST_WARNING_OBJECT (demux, "seeking only supported in TIME format");
3644 return gst_pad_push_event (demux->sinkpad, gst_event_ref (event));
3645 }
3646 wrong_rate:
3647 {
3648 GST_WARNING_OBJECT (demux, "only rates > 0.0 are allowed");
3649 return FALSE;
3650 }
3651 unresolved_metadata:
3652 {
3653 GST_WARNING_OBJECT (demux, "metadata can't be resolved");
3654 return gst_pad_push_event (demux->sinkpad, gst_event_ref (event));
3655 }
3656 seek_failed:
3657 {
3658 GST_WARNING_OBJECT (demux, "upstream seek failed");
3659 return gst_pad_push_event (demux->sinkpad, gst_event_ref (event));
3660 }
3661 no_new_offset:
3662 {
3663 GST_WARNING_OBJECT (demux, "can't find new offset");
3664 return gst_pad_push_event (demux->sinkpad, gst_event_ref (event));
3665 }
3666 }
3667
3668 static void
collect_index_table_segments(GstMXFDemux * demux)3669 collect_index_table_segments (GstMXFDemux * demux)
3670 {
3671 GList *l;
3672 guint i;
3673 guint64 old_offset = demux->offset;
3674 GstMXFDemuxPartition *old_partition = demux->current_partition;
3675
3676 if (!demux->random_index_pack)
3677 return;
3678
3679 for (i = 0; i < demux->random_index_pack->len; i++) {
3680 MXFRandomIndexPackEntry *e =
3681 &g_array_index (demux->random_index_pack, MXFRandomIndexPackEntry, i);
3682
3683 if (e->offset < demux->run_in) {
3684 GST_ERROR_OBJECT (demux, "Invalid random index pack entry");
3685 return;
3686 }
3687
3688 demux->offset = e->offset;
3689 read_partition_header (demux);
3690 }
3691
3692 demux->offset = old_offset;
3693 demux->current_partition = old_partition;
3694
3695 for (l = demux->pending_index_table_segments; l; l = l->next) {
3696 MXFIndexTableSegment *segment = l->data;
3697 GstMXFDemuxIndexTable *t = NULL;
3698 GList *k;
3699 guint64 start, end;
3700
3701 for (k = demux->index_tables; k; k = k->next) {
3702 GstMXFDemuxIndexTable *tmp = k->data;
3703
3704 if (tmp->body_sid == segment->body_sid
3705 && tmp->index_sid == segment->index_sid) {
3706 t = tmp;
3707 break;
3708 }
3709 }
3710
3711 if (!t) {
3712 t = g_new0 (GstMXFDemuxIndexTable, 1);
3713 t->body_sid = segment->body_sid;
3714 t->index_sid = segment->index_sid;
3715 t->offsets = g_array_new (FALSE, TRUE, sizeof (GstMXFDemuxIndex));
3716 demux->index_tables = g_list_prepend (demux->index_tables, t);
3717 }
3718
3719 start = segment->index_start_position;
3720 end = start + segment->index_duration;
3721 if (end > G_MAXINT / sizeof (GstMXFDemuxIndex)) {
3722 demux->index_tables = g_list_remove (demux->index_tables, t);
3723 g_array_free (t->offsets, TRUE);
3724 g_free (t);
3725 continue;
3726 }
3727
3728 if (t->offsets->len < end)
3729 g_array_set_size (t->offsets, end);
3730
3731 for (i = 0; i < segment->n_index_entries && start + i < t->offsets->len;
3732 i++) {
3733 guint64 offset = segment->index_entries[i].stream_offset;
3734 GList *m;
3735 GstMXFDemuxPartition *offset_partition = NULL, *next_partition = NULL;
3736
3737 for (m = demux->partitions; m; m = m->next) {
3738 GstMXFDemuxPartition *partition = m->data;
3739
3740 if (!next_partition && offset_partition)
3741 next_partition = partition;
3742
3743 if (partition->partition.body_sid != t->body_sid)
3744 continue;
3745 if (partition->partition.body_offset > offset)
3746 break;
3747
3748 offset_partition = partition;
3749 next_partition = NULL;
3750 }
3751
3752 if (offset_partition && offset >= offset_partition->partition.body_offset) {
3753 offset =
3754 offset_partition->partition.this_partition +
3755 offset_partition->essence_container_offset + (offset -
3756 offset_partition->partition.body_offset);
3757
3758 if (next_partition
3759 && offset >= next_partition->partition.this_partition) {
3760 GST_ERROR_OBJECT (demux,
3761 "Invalid index table segment going into next unrelated partition");
3762 } else {
3763 GstMXFDemuxIndex *index;
3764 gint8 temporal_offset = segment->index_entries[i].temporal_offset;
3765 guint64 pts_i = G_MAXUINT64;
3766
3767 if (temporal_offset > 0 ||
3768 (temporal_offset < 0 && start + i >= -(gint) temporal_offset)) {
3769 pts_i = start + i + temporal_offset;
3770
3771 if (t->offsets->len < pts_i)
3772 g_array_set_size (t->offsets, pts_i + 1);
3773
3774 index = &g_array_index (t->offsets, GstMXFDemuxIndex, pts_i);
3775 if (!index->initialized) {
3776 index->initialized = TRUE;
3777 index->offset = 0;
3778 index->pts = G_MAXUINT64;
3779 index->dts = G_MAXUINT64;
3780 index->keyframe = FALSE;
3781 }
3782
3783 index->pts = start + i;
3784 }
3785
3786 index = &g_array_index (t->offsets, GstMXFDemuxIndex, start + i);
3787 if (!index->initialized) {
3788 index->initialized = TRUE;
3789 index->offset = 0;
3790 index->pts = G_MAXUINT64;
3791 index->dts = G_MAXUINT64;
3792 index->keyframe = FALSE;
3793 }
3794
3795 index->offset = offset;
3796 index->keyframe = ! !(segment->index_entries[i].flags & 0x80)
3797 || (segment->index_entries[i].key_frame_offset == 0);
3798 index->dts = pts_i;
3799 }
3800 }
3801 }
3802 }
3803
3804 for (l = demux->pending_index_table_segments; l; l = l->next) {
3805 MXFIndexTableSegment *s = l->data;
3806 mxf_index_table_segment_reset (s);
3807 g_free (s);
3808 }
3809 g_list_free (demux->pending_index_table_segments);
3810 demux->pending_index_table_segments = NULL;
3811 }
3812
3813 static gboolean
gst_mxf_demux_seek_pull(GstMXFDemux * demux,GstEvent * event)3814 gst_mxf_demux_seek_pull (GstMXFDemux * demux, GstEvent * event)
3815 {
3816 GstClockTime keyunit_ts;
3817 GstFormat format;
3818 GstSeekFlags flags;
3819 GstSeekType start_type, stop_type;
3820 gint64 start, stop;
3821 gdouble rate;
3822 gboolean update, flush, keyframe;
3823 GstSegment seeksegment;
3824 guint i;
3825 gboolean ret = TRUE;
3826 guint32 seqnum;
3827
3828 gst_event_parse_seek (event, &rate, &format, &flags,
3829 &start_type, &start, &stop_type, &stop);
3830 seqnum = gst_event_get_seqnum (event);
3831
3832 if (format != GST_FORMAT_TIME)
3833 goto wrong_format;
3834
3835 if (rate <= 0.0)
3836 goto wrong_rate;
3837
3838 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
3839 keyframe = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
3840
3841 keyunit_ts = start;
3842
3843 if (!demux->index_table_segments_collected) {
3844 collect_index_table_segments (demux);
3845 demux->index_table_segments_collected = TRUE;
3846 }
3847
3848 if (flush) {
3849 GstEvent *e;
3850
3851 /* Flush start up and downstream to make sure data flow and loops are
3852 idle */
3853 e = gst_event_new_flush_start ();
3854 gst_event_set_seqnum (e, seqnum);
3855 gst_mxf_demux_push_src_event (demux, gst_event_ref (e));
3856 gst_pad_push_event (demux->sinkpad, e);
3857 } else {
3858 /* Pause the pulling task */
3859 gst_pad_pause_task (demux->sinkpad);
3860 }
3861
3862 /* Take the stream lock */
3863 GST_PAD_STREAM_LOCK (demux->sinkpad);
3864
3865 if (flush) {
3866 GstEvent *e;
3867
3868 /* Stop flushing upstream we need to pull */
3869 e = gst_event_new_flush_stop (TRUE);
3870 gst_event_set_seqnum (e, seqnum);
3871 gst_pad_push_event (demux->sinkpad, e);
3872 }
3873
3874 /* Work on a copy until we are sure the seek succeeded. */
3875 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
3876
3877 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
3878 &demux->segment);
3879
3880 /* Apply the seek to our segment */
3881 gst_segment_do_seek (&seeksegment, rate, format, flags,
3882 start_type, start, stop_type, stop, &update);
3883
3884 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
3885 &seeksegment);
3886
3887 if (flush || seeksegment.position != demux->segment.position) {
3888 guint64 new_offset = -1;
3889
3890 if (!demux->metadata_resolved || demux->update_metadata) {
3891 if (gst_mxf_demux_resolve_references (demux) != GST_FLOW_OK ||
3892 gst_mxf_demux_update_tracks (demux) != GST_FLOW_OK) {
3893 goto unresolved_metadata;
3894 }
3895 }
3896
3897 /* Do the actual seeking */
3898 for (i = 0; i < demux->src->len; i++) {
3899 MXFMetadataTrackType track_type = MXF_METADATA_TRACK_UNKNOWN;
3900 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
3901 gint64 position;
3902 guint64 off;
3903
3904 if (p->material_track != NULL)
3905 track_type = p->material_track->parent.type;
3906
3907 /* Reset EOS flag on all pads */
3908 p->eos = FALSE;
3909 gst_mxf_demux_pad_set_position (demux, p, start);
3910
3911 /* we always want to send data starting with a key unit */
3912 position = p->current_essence_track_position;
3913 off =
3914 gst_mxf_demux_find_essence_element (demux, p->current_essence_track,
3915 &position, TRUE);
3916 if (off == -1) {
3917 GST_DEBUG_OBJECT (demux, "Unable to find offset for pad %s",
3918 GST_PAD_NAME (p));
3919 p->current_essence_track_position = p->current_essence_track->duration;
3920 } else {
3921 new_offset = MIN (off, new_offset);
3922 if (position != p->current_essence_track_position) {
3923 p->position -=
3924 gst_util_uint64_scale (p->current_essence_track_position -
3925 position,
3926 GST_SECOND * p->current_essence_track->source_track->edit_rate.d,
3927 p->current_essence_track->source_track->edit_rate.n);
3928 p->position_accumulated_error = 0.0;
3929 p->current_material_track_position -=
3930 gst_util_uint64_scale (p->current_essence_track_position -
3931 position,
3932 p->material_track->edit_rate.n *
3933 p->current_essence_track->source_track->edit_rate.d,
3934 p->material_track->edit_rate.d *
3935 p->current_essence_track->source_track->edit_rate.n);
3936 }
3937 p->current_essence_track_position = position;
3938
3939 /* FIXME: what about DV + MPEG-TS container essence tracks? */
3940 if (track_type == MXF_METADATA_TRACK_PICTURE_ESSENCE) {
3941 keyunit_ts = MIN (p->position, keyunit_ts);
3942 }
3943 }
3944 p->discont = TRUE;
3945 }
3946 gst_flow_combiner_reset (demux->flowcombiner);
3947 if (new_offset == -1) {
3948 GST_WARNING_OBJECT (demux, "No new offset found");
3949 ret = FALSE;
3950 } else {
3951 demux->offset = new_offset + demux->run_in;
3952 }
3953 gst_mxf_demux_set_partition_for_offset (demux, demux->offset);
3954 }
3955
3956 if (G_UNLIKELY (demux->close_seg_event)) {
3957 gst_event_unref (demux->close_seg_event);
3958 demux->close_seg_event = NULL;
3959 }
3960
3961 if (flush) {
3962 GstEvent *e;
3963
3964 /* Stop flushing, the sinks are at time 0 now */
3965 e = gst_event_new_flush_stop (TRUE);
3966 gst_event_set_seqnum (e, seqnum);
3967 gst_mxf_demux_push_src_event (demux, e);
3968 } else {
3969 GST_DEBUG_OBJECT (demux, "closing running segment %" GST_SEGMENT_FORMAT,
3970 &demux->segment);
3971
3972 /* Close the current segment for a linear playback */
3973 demux->close_seg_event = gst_event_new_segment (&demux->segment);
3974 gst_event_set_seqnum (demux->close_seg_event, demux->seqnum);
3975 }
3976
3977 if (keyframe && keyunit_ts != start) {
3978 GST_INFO_OBJECT (demux, "key unit seek, adjusting segment start to "
3979 "%" GST_TIME_FORMAT, GST_TIME_ARGS (keyunit_ts));
3980 gst_segment_do_seek (&seeksegment, rate, format, flags,
3981 start_type, keyunit_ts, stop_type, stop, &update);
3982 }
3983
3984 /* Ok seek succeeded, take the newly configured segment */
3985 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
3986
3987 /* Notify about the start of a new segment */
3988 if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
3989 GstMessage *m;
3990
3991 m = gst_message_new_segment_start (GST_OBJECT (demux),
3992 demux->segment.format, demux->segment.position);
3993 gst_message_set_seqnum (m, seqnum);
3994 gst_element_post_message (GST_ELEMENT (demux), m);
3995 }
3996
3997 /* Tell all the stream a new segment is needed */
3998 for (i = 0; i < demux->src->len; i++) {
3999 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
4000 p->need_segment = TRUE;
4001 }
4002
4003 for (i = 0; i < demux->essence_tracks->len; i++) {
4004 GstMXFDemuxEssenceTrack *t =
4005 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
4006 t->position = -1;
4007 }
4008
4009 demux->seqnum = seqnum;
4010
4011 gst_pad_start_task (demux->sinkpad,
4012 (GstTaskFunction) gst_mxf_demux_loop, demux->sinkpad, NULL);
4013
4014 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
4015
4016 return ret;
4017
4018 /* ERRORS */
4019 wrong_format:
4020 {
4021 GST_WARNING_OBJECT (demux, "seeking only supported in TIME format");
4022 return FALSE;
4023 }
4024 wrong_rate:
4025 {
4026 GST_WARNING_OBJECT (demux, "only rates > 0.0 are allowed");
4027 return FALSE;
4028 }
4029 unresolved_metadata:
4030 {
4031 gst_pad_start_task (demux->sinkpad,
4032 (GstTaskFunction) gst_mxf_demux_loop, demux->sinkpad, NULL);
4033 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
4034 GST_WARNING_OBJECT (demux, "metadata can't be resolved");
4035 return FALSE;
4036 }
4037 }
4038
4039 static gboolean
gst_mxf_demux_src_event(GstPad * pad,GstObject * parent,GstEvent * event)4040 gst_mxf_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
4041 {
4042 GstMXFDemux *demux = GST_MXF_DEMUX (parent);
4043 gboolean ret;
4044
4045 GST_DEBUG_OBJECT (pad, "handling event %s", GST_EVENT_TYPE_NAME (event));
4046
4047 switch (GST_EVENT_TYPE (event)) {
4048 case GST_EVENT_SEEK:
4049 if (demux->random_access)
4050 ret = gst_mxf_demux_seek_pull (demux, event);
4051 else
4052 ret = gst_mxf_demux_seek_push (demux, event);
4053 gst_event_unref (event);
4054 break;
4055 default:
4056 ret = gst_pad_push_event (demux->sinkpad, event);
4057 break;
4058 }
4059
4060 return ret;
4061 }
4062
4063 static gboolean
gst_mxf_demux_src_query(GstPad * pad,GstObject * parent,GstQuery * query)4064 gst_mxf_demux_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
4065 {
4066 GstMXFDemux *demux = GST_MXF_DEMUX (parent);
4067 gboolean ret = FALSE;
4068 GstMXFDemuxPad *mxfpad = GST_MXF_DEMUX_PAD (pad);
4069
4070 GST_DEBUG_OBJECT (pad, "handling query %s",
4071 gst_query_type_get_name (GST_QUERY_TYPE (query)));
4072
4073 switch (GST_QUERY_TYPE (query)) {
4074 case GST_QUERY_POSITION:
4075 {
4076 GstFormat format;
4077 gint64 pos;
4078
4079 gst_query_parse_position (query, &format, NULL);
4080 if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT)
4081 goto error;
4082
4083 pos =
4084 format ==
4085 GST_FORMAT_DEFAULT ? mxfpad->current_material_track_position :
4086 mxfpad->position;
4087
4088 GST_DEBUG_OBJECT (pad,
4089 "Returning position %" G_GINT64_FORMAT " in format %s", pos,
4090 gst_format_get_name (format));
4091
4092 gst_query_set_position (query, format, pos);
4093 ret = TRUE;
4094
4095 break;
4096 }
4097 case GST_QUERY_DURATION:{
4098 gint64 duration;
4099 GstFormat format;
4100
4101 gst_query_parse_duration (query, &format, NULL);
4102 if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT)
4103 goto error;
4104
4105 g_rw_lock_reader_lock (&demux->metadata_lock);
4106 if (!mxfpad->material_track || !mxfpad->material_track->parent.sequence) {
4107 g_rw_lock_reader_unlock (&demux->metadata_lock);
4108 goto error;
4109 }
4110
4111 duration = mxfpad->material_track->parent.sequence->duration;
4112 if (duration <= -1)
4113 duration = -1;
4114
4115 if (duration != -1 && format == GST_FORMAT_TIME) {
4116 if (mxfpad->material_track->edit_rate.n == 0 ||
4117 mxfpad->material_track->edit_rate.d == 0) {
4118 g_rw_lock_reader_unlock (&demux->metadata_lock);
4119 goto error;
4120 }
4121
4122 duration =
4123 gst_util_uint64_scale (duration,
4124 GST_SECOND * mxfpad->material_track->edit_rate.d,
4125 mxfpad->material_track->edit_rate.n);
4126 }
4127 g_rw_lock_reader_unlock (&demux->metadata_lock);
4128
4129 GST_DEBUG_OBJECT (pad,
4130 "Returning duration %" G_GINT64_FORMAT " in format %s", duration,
4131 gst_format_get_name (format));
4132
4133 gst_query_set_duration (query, format, duration);
4134 ret = TRUE;
4135 break;
4136 }
4137 case GST_QUERY_SEEKING:{
4138 GstFormat fmt;
4139 gint64 duration;
4140
4141 ret = TRUE;
4142 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
4143 if (fmt != GST_FORMAT_TIME) {
4144 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
4145 goto done;
4146 }
4147
4148 if (!gst_pad_query_duration (pad, GST_FORMAT_TIME, &duration)) {
4149 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
4150 goto done;
4151 }
4152
4153 if (demux->random_access) {
4154 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, duration);
4155 } else {
4156 GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
4157 gboolean seekable;
4158
4159 seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
4160 if (seekable)
4161 gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
4162 if (seekable)
4163 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, duration);
4164 else
4165 gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
4166
4167 gst_query_unref (peerquery);
4168 }
4169
4170 break;
4171 }
4172 case GST_QUERY_SEGMENT:{
4173 GstFormat format;
4174 gint64 start, stop;
4175
4176 format = demux->segment.format;
4177
4178 start =
4179 gst_segment_to_stream_time (&demux->segment, format,
4180 demux->segment.start);
4181 if ((stop = demux->segment.stop) == -1)
4182 stop = demux->segment.duration;
4183 else
4184 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4185
4186 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4187 ret = TRUE;
4188 break;
4189 }
4190 default:
4191 ret = gst_pad_query_default (pad, parent, query);
4192 break;
4193 }
4194
4195 done:
4196 return ret;
4197
4198 /* ERRORS */
4199 error:
4200 {
4201 GST_DEBUG_OBJECT (pad, "query failed");
4202 goto done;
4203 }
4204 }
4205
4206 static gboolean
gst_mxf_demux_sink_activate(GstPad * sinkpad,GstObject * parent)4207 gst_mxf_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
4208 {
4209 GstQuery *query;
4210 GstPadMode mode = GST_PAD_MODE_PUSH;
4211
4212 query = gst_query_new_scheduling ();
4213
4214 if (gst_pad_peer_query (sinkpad, query)) {
4215 if (gst_query_has_scheduling_mode_with_flags (query,
4216 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE)) {
4217 GstSchedulingFlags flags;
4218 gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL);
4219 if (!(flags & GST_SCHEDULING_FLAG_SEQUENTIAL))
4220 mode = GST_PAD_MODE_PULL;
4221 }
4222 }
4223 gst_query_unref (query);
4224
4225 return gst_pad_activate_mode (sinkpad, mode, TRUE);
4226 }
4227
4228 static gboolean
gst_mxf_demux_sink_activate_mode(GstPad * sinkpad,GstObject * parent,GstPadMode mode,gboolean active)4229 gst_mxf_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
4230 GstPadMode mode, gboolean active)
4231 {
4232 GstMXFDemux *demux;
4233
4234 demux = GST_MXF_DEMUX (parent);
4235
4236 if (mode == GST_PAD_MODE_PUSH) {
4237 demux->random_access = FALSE;
4238 } else {
4239 if (active) {
4240 demux->random_access = TRUE;
4241 return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_mxf_demux_loop,
4242 sinkpad, NULL);
4243 } else {
4244 demux->random_access = FALSE;
4245 return gst_pad_stop_task (sinkpad);
4246 }
4247 }
4248
4249 return TRUE;
4250 }
4251
4252 static gboolean
gst_mxf_demux_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)4253 gst_mxf_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
4254 {
4255 GstMXFDemux *demux;
4256 gboolean ret = FALSE;
4257
4258 demux = GST_MXF_DEMUX (parent);
4259
4260 GST_DEBUG_OBJECT (pad, "handling event %s", GST_EVENT_TYPE_NAME (event));
4261
4262 switch (GST_EVENT_TYPE (event)) {
4263 case GST_EVENT_FLUSH_START:
4264 demux->flushing = TRUE;
4265 ret = gst_pad_event_default (pad, parent, event);
4266 break;
4267 case GST_EVENT_FLUSH_STOP:
4268 GST_DEBUG_OBJECT (demux, "flushing queued data in the MXF demuxer");
4269
4270 gst_adapter_clear (demux->adapter);
4271 demux->flushing = FALSE;
4272 demux->offset = 0;
4273 ret = gst_pad_event_default (pad, parent, event);
4274 break;
4275 case GST_EVENT_EOS:{
4276 GstMXFDemuxPad *p = NULL;
4277 guint i;
4278
4279 if (demux->src->len == 0) {
4280 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE,
4281 ("This stream contains no data."),
4282 ("got eos and didn't find any streams"));
4283 }
4284
4285 for (i = 0; i < demux->essence_tracks->len; i++) {
4286 GstMXFDemuxEssenceTrack *t =
4287 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i);
4288
4289 if (t->position > 0)
4290 t->duration = t->position;
4291 }
4292
4293 for (i = 0; i < demux->src->len; i++) {
4294 GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i);
4295
4296 if (!p->eos
4297 && p->current_essence_track_position >=
4298 p->current_essence_track->duration) {
4299 p->eos = TRUE;
4300 gst_pad_push_event (GST_PAD_CAST (p), gst_event_new_eos ());
4301 }
4302 }
4303
4304 while ((p = gst_mxf_demux_get_earliest_pad (demux))) {
4305 guint64 offset;
4306 gint64 position;
4307
4308 position = p->current_essence_track_position;
4309
4310 offset =
4311 gst_mxf_demux_find_essence_element (demux, p->current_essence_track,
4312 &position, FALSE);
4313 if (offset == -1) {
4314 GST_ERROR_OBJECT (demux, "Failed to find offset for essence track");
4315 p->eos = TRUE;
4316 gst_pad_push_event (GST_PAD_CAST (p), gst_event_new_eos ());
4317 continue;
4318 }
4319
4320 if (gst_pad_push_event (demux->sinkpad,
4321 gst_event_new_seek (demux->segment.rate, GST_FORMAT_BYTES,
4322 demux->segment.flags | GST_SEEK_FLAG_ACCURATE,
4323 GST_SEEK_TYPE_SET, offset + demux->run_in,
4324 GST_SEEK_TYPE_NONE, 0))) {
4325
4326 for (i = 0; i < demux->essence_tracks->len; i++) {
4327 GstMXFDemuxEssenceTrack *etrack =
4328 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack,
4329 i);
4330 etrack->position = -1;
4331 }
4332 ret = TRUE;
4333 goto out;
4334 } else {
4335 GST_WARNING_OBJECT (demux,
4336 "Seek to remaining part of the file failed");
4337 p->eos = TRUE;
4338 gst_pad_push_event (GST_PAD_CAST (p), gst_event_new_eos ());
4339 continue;
4340 }
4341 }
4342
4343 /* and one more time for good measure apparently? */
4344 gst_pad_event_default (pad, parent, event);
4345 ret = (demux->src->len > 0);
4346 break;
4347 }
4348 case GST_EVENT_SEGMENT:{
4349 guint i;
4350
4351 for (i = 0; i < demux->essence_tracks->len; i++) {
4352 GstMXFDemuxEssenceTrack *t =
4353 &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack,
4354 i);
4355 t->position = -1;
4356 }
4357 demux->current_partition = NULL;
4358 demux->seqnum = gst_event_get_seqnum (event);
4359 gst_event_unref (event);
4360 ret = TRUE;
4361 break;
4362 }
4363 default:
4364 ret = gst_pad_event_default (pad, parent, event);
4365 break;
4366 }
4367
4368 out:
4369
4370 return ret;
4371 }
4372
4373 static gboolean
gst_mxf_demux_query(GstElement * element,GstQuery * query)4374 gst_mxf_demux_query (GstElement * element, GstQuery * query)
4375 {
4376 GstMXFDemux *demux = GST_MXF_DEMUX (element);
4377 gboolean ret = FALSE;
4378
4379 GST_DEBUG_OBJECT (demux, "handling query %s",
4380 gst_query_type_get_name (GST_QUERY_TYPE (query)));
4381
4382 switch (GST_QUERY_TYPE (query)) {
4383 case GST_QUERY_POSITION:
4384 {
4385 GstFormat format;
4386 gint64 pos;
4387
4388 gst_query_parse_position (query, &format, NULL);
4389 if (format != GST_FORMAT_TIME)
4390 goto error;
4391
4392 pos = demux->segment.position;
4393
4394 GST_DEBUG_OBJECT (demux,
4395 "Returning position %" G_GINT64_FORMAT " in format %s", pos,
4396 gst_format_get_name (format));
4397
4398 gst_query_set_position (query, format, pos);
4399 ret = TRUE;
4400
4401 break;
4402 }
4403 case GST_QUERY_DURATION:{
4404 gint64 duration = -1;
4405 GstFormat format;
4406 guint i;
4407
4408 gst_query_parse_duration (query, &format, NULL);
4409 if (format != GST_FORMAT_TIME)
4410 goto error;
4411
4412 if (demux->src->len == 0)
4413 goto done;
4414
4415 g_rw_lock_reader_lock (&demux->metadata_lock);
4416 for (i = 0; i < demux->src->len; i++) {
4417 GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i);
4418 gint64 pdur = -1;
4419
4420 if (!pad->material_track || !pad->material_track->parent.sequence)
4421 continue;
4422
4423 pdur = pad->material_track->parent.sequence->duration;
4424 if (pad->material_track->edit_rate.n == 0 ||
4425 pad->material_track->edit_rate.d == 0 || pdur <= -1)
4426 continue;
4427
4428 pdur =
4429 gst_util_uint64_scale (pdur,
4430 GST_SECOND * pad->material_track->edit_rate.d,
4431 pad->material_track->edit_rate.n);
4432 duration = MAX (duration, pdur);
4433 }
4434 g_rw_lock_reader_unlock (&demux->metadata_lock);
4435
4436 if (duration == -1) {
4437 GST_DEBUG_OBJECT (demux, "No duration known (yet)");
4438 goto done;
4439 }
4440
4441 GST_DEBUG_OBJECT (demux,
4442 "Returning duration %" G_GINT64_FORMAT " in format %s", duration,
4443 gst_format_get_name (format));
4444
4445 gst_query_set_duration (query, format, duration);
4446 ret = TRUE;
4447 break;
4448 }
4449 case GST_QUERY_SEEKING:{
4450 GstFormat fmt;
4451
4452 ret = TRUE;
4453 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
4454 if (fmt != GST_FORMAT_TIME) {
4455 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
4456 goto done;
4457 }
4458
4459 if (demux->random_access) {
4460 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
4461 } else {
4462 GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
4463 gboolean seekable;
4464
4465 seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
4466 if (seekable)
4467 gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
4468 if (seekable)
4469 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
4470 else
4471 gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
4472 }
4473
4474 break;
4475 }
4476 case GST_QUERY_SEGMENT:{
4477 GstFormat format;
4478 gint64 start, stop;
4479
4480 format = demux->segment.format;
4481
4482 start =
4483 gst_segment_to_stream_time (&demux->segment, format,
4484 demux->segment.start);
4485 if ((stop = demux->segment.stop) == -1)
4486 stop = demux->segment.duration;
4487 else
4488 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4489
4490 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4491 ret = TRUE;
4492 break;
4493 }
4494 default:
4495 /* else forward upstream */
4496 ret = gst_pad_peer_query (demux->sinkpad, query);
4497 break;
4498 }
4499
4500 done:
4501 return ret;
4502
4503 /* ERRORS */
4504 error:
4505 {
4506 GST_DEBUG_OBJECT (demux, "query failed");
4507 goto done;
4508 }
4509 }
4510
4511 static GstStateChangeReturn
gst_mxf_demux_change_state(GstElement * element,GstStateChange transition)4512 gst_mxf_demux_change_state (GstElement * element, GstStateChange transition)
4513 {
4514 GstMXFDemux *demux = GST_MXF_DEMUX (element);
4515 GstStateChangeReturn ret;
4516
4517 switch (transition) {
4518 case GST_STATE_CHANGE_READY_TO_PAUSED:
4519 demux->seqnum = gst_util_seqnum_next ();
4520 break;
4521 default:
4522 break;
4523 }
4524
4525 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4526 if (ret == GST_STATE_CHANGE_FAILURE)
4527 return ret;
4528
4529 switch (transition) {
4530 case GST_STATE_CHANGE_PAUSED_TO_READY:
4531 gst_mxf_demux_reset (demux);
4532 break;
4533 default:
4534 break;
4535 }
4536
4537 return ret;
4538 }
4539
4540 static void
gst_mxf_demux_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)4541 gst_mxf_demux_set_property (GObject * object, guint prop_id,
4542 const GValue * value, GParamSpec * pspec)
4543 {
4544 GstMXFDemux *demux = GST_MXF_DEMUX (object);
4545
4546 switch (prop_id) {
4547 case PROP_PACKAGE:
4548 g_free (demux->requested_package_string);
4549 demux->requested_package_string = g_value_dup_string (value);
4550 break;
4551 case PROP_MAX_DRIFT:
4552 demux->max_drift = g_value_get_uint64 (value);
4553 break;
4554 default:
4555 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4556 break;
4557 }
4558 }
4559
4560 static void
gst_mxf_demux_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)4561 gst_mxf_demux_get_property (GObject * object, guint prop_id,
4562 GValue * value, GParamSpec * pspec)
4563 {
4564 GstMXFDemux *demux = GST_MXF_DEMUX (object);
4565
4566 switch (prop_id) {
4567 case PROP_PACKAGE:
4568 g_value_set_string (value, demux->current_package_string);
4569 break;
4570 case PROP_MAX_DRIFT:
4571 g_value_set_uint64 (value, demux->max_drift);
4572 break;
4573 case PROP_STRUCTURE:{
4574 GstStructure *s;
4575
4576 g_rw_lock_reader_lock (&demux->metadata_lock);
4577 if (demux->preface &&
4578 MXF_METADATA_BASE (demux->preface)->resolved ==
4579 MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS)
4580 s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (demux->preface));
4581 else
4582 s = NULL;
4583
4584 gst_value_set_structure (value, s);
4585
4586 if (s)
4587 gst_structure_free (s);
4588
4589 g_rw_lock_reader_unlock (&demux->metadata_lock);
4590 break;
4591 }
4592 default:
4593 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4594 break;
4595 }
4596 }
4597
4598 static void
gst_mxf_demux_finalize(GObject * object)4599 gst_mxf_demux_finalize (GObject * object)
4600 {
4601 GstMXFDemux *demux = GST_MXF_DEMUX (object);
4602
4603 gst_mxf_demux_reset (demux);
4604
4605 if (demux->adapter) {
4606 g_object_unref (demux->adapter);
4607 demux->adapter = NULL;
4608 }
4609
4610 if (demux->flowcombiner) {
4611 gst_flow_combiner_free (demux->flowcombiner);
4612 demux->flowcombiner = NULL;
4613 }
4614
4615 if (demux->close_seg_event) {
4616 gst_event_unref (demux->close_seg_event);
4617 demux->close_seg_event = NULL;
4618 }
4619
4620 g_free (demux->current_package_string);
4621 demux->current_package_string = NULL;
4622 g_free (demux->requested_package_string);
4623 demux->requested_package_string = NULL;
4624
4625 g_ptr_array_free (demux->src, TRUE);
4626 demux->src = NULL;
4627 g_array_free (demux->essence_tracks, TRUE);
4628 demux->essence_tracks = NULL;
4629
4630 g_hash_table_destroy (demux->metadata);
4631
4632 g_rw_lock_clear (&demux->metadata_lock);
4633
4634 G_OBJECT_CLASS (parent_class)->finalize (object);
4635 }
4636
4637 static void
gst_mxf_demux_class_init(GstMXFDemuxClass * klass)4638 gst_mxf_demux_class_init (GstMXFDemuxClass * klass)
4639 {
4640 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
4641 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
4642
4643 GST_DEBUG_CATEGORY_INIT (mxfdemux_debug, "mxfdemux", 0, "MXF demuxer");
4644
4645 parent_class = g_type_class_peek_parent (klass);
4646
4647 gobject_class->finalize = gst_mxf_demux_finalize;
4648 gobject_class->set_property = gst_mxf_demux_set_property;
4649 gobject_class->get_property = gst_mxf_demux_get_property;
4650
4651 g_object_class_install_property (gobject_class, PROP_PACKAGE,
4652 g_param_spec_string ("package", "Package",
4653 "Material or Source package to use for playback", NULL,
4654 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4655
4656 g_object_class_install_property (gobject_class, PROP_MAX_DRIFT,
4657 g_param_spec_uint64 ("max-drift", "Maximum drift",
4658 "Maximum number of nanoseconds by which tracks can differ",
4659 100 * GST_MSECOND, G_MAXUINT64, 500 * GST_MSECOND,
4660 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4661
4662 g_object_class_install_property (gobject_class, PROP_STRUCTURE,
4663 g_param_spec_boxed ("structure", "Structure",
4664 "Structural metadata of the MXF file",
4665 GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4666
4667 gstelement_class->change_state =
4668 GST_DEBUG_FUNCPTR (gst_mxf_demux_change_state);
4669 gstelement_class->query = GST_DEBUG_FUNCPTR (gst_mxf_demux_query);
4670
4671 gst_element_class_add_static_pad_template (gstelement_class,
4672 &mxf_sink_template);
4673 gst_element_class_add_static_pad_template (gstelement_class,
4674 &mxf_src_template);
4675 gst_element_class_set_static_metadata (gstelement_class, "MXF Demuxer",
4676 "Codec/Demuxer", "Demux MXF files",
4677 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
4678 }
4679
4680 static void
gst_mxf_demux_init(GstMXFDemux * demux)4681 gst_mxf_demux_init (GstMXFDemux * demux)
4682 {
4683 demux->sinkpad =
4684 gst_pad_new_from_static_template (&mxf_sink_template, "sink");
4685
4686 gst_pad_set_event_function (demux->sinkpad,
4687 GST_DEBUG_FUNCPTR (gst_mxf_demux_sink_event));
4688 gst_pad_set_chain_function (demux->sinkpad,
4689 GST_DEBUG_FUNCPTR (gst_mxf_demux_chain));
4690 gst_pad_set_activate_function (demux->sinkpad,
4691 GST_DEBUG_FUNCPTR (gst_mxf_demux_sink_activate));
4692 gst_pad_set_activatemode_function (demux->sinkpad,
4693 GST_DEBUG_FUNCPTR (gst_mxf_demux_sink_activate_mode));
4694
4695 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
4696
4697 demux->max_drift = 500 * GST_MSECOND;
4698
4699 demux->adapter = gst_adapter_new ();
4700 demux->flowcombiner = gst_flow_combiner_new ();
4701 g_rw_lock_init (&demux->metadata_lock);
4702
4703 demux->src = g_ptr_array_new ();
4704 demux->essence_tracks =
4705 g_array_new (FALSE, FALSE, sizeof (GstMXFDemuxEssenceTrack));
4706
4707 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4708
4709 gst_mxf_demux_reset (demux);
4710 }
4711