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