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