mxfdemux: don't error out if VANC track only contains packets we don't handle
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / gst / mxf / mxfmux.c
1 /* GStreamer
2  * Copyright (C) 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-mxfmux
22  * @title: mxfmux
23  *
24  * mxfmux muxes different streams into an MXF file.
25  *
26  * ## Example launch line
27  * |[
28  * gst-launch-1.0 -v filesrc location=/path/to/audio ! decodebin ! queue ! mxfmux name=m ! filesink location=file.mxf   filesrc location=/path/to/video ! decodebin ! queue ! m.
29  * ]| This pipeline muxes an audio and video file into a single MXF file.
30  *
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <math.h>
38 #include <string.h>
39
40 #include "gstmxfelements.h"
41 #include "mxfmux.h"
42
43 #ifdef HAVE_SYS_UTSNAME_H
44 #include <sys/utsname.h>
45 #endif
46
47 GST_DEBUG_CATEGORY_STATIC (mxfmux_debug);
48 #define GST_CAT_DEFAULT mxfmux_debug
49
50 #define GST_TYPE_MXF_MUX_PAD            (gst_mxf_mux_pad_get_type())
51 #define GST_MXF_MUX_PAD(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MXF_MUX_PAD, GstMXFMuxPad))
52 #define GST_MXF_MUX_PAD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MXF_MUX_PAD, GstMXFMuxPadClass))
53 #define GST_MXF_MUX_PAD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_MXF_MUX_PAD, GstMXFMuxPadClass))
54 #define GST_IS_MXF_MUX_PAD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MXF_MUX_PAD))
55 #define GST_IS_MXF_MUX_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MXF_MUX_PAD))
56
57 typedef struct
58 {
59   GstAggregatorPad parent;
60
61   guint64 pos;
62   GstClockTime last_timestamp;
63
64   MXFMetadataFileDescriptor *descriptor;
65
66   GstAdapter *adapter;
67   gboolean have_complete_edit_unit;
68
69   gpointer mapping_data;
70   const MXFEssenceElementWriter *writer;
71   MXFEssenceElementWriteFunc write_func;
72
73   MXFMetadataSourcePackage *source_package;
74   MXFMetadataTimelineTrack *source_track;
75 } GstMXFMuxPad;
76
77 typedef struct
78 {
79   GstAggregatorPadClass parent_class;
80 } GstMXFMuxPadClass;
81
82 GType gst_mxf_mux_pad_get_type (void);
83
84 G_DEFINE_TYPE (GstMXFMuxPad, gst_mxf_mux_pad, GST_TYPE_AGGREGATOR_PAD);
85
86 static void
87 gst_mxf_mux_pad_finalize (GObject * object)
88 {
89   GstMXFMuxPad *pad = GST_MXF_MUX_PAD (object);
90
91   g_object_unref (pad->adapter);
92   g_free (pad->mapping_data);
93
94   G_OBJECT_CLASS (gst_mxf_mux_pad_parent_class)->finalize (object);
95 }
96
97 static void
98 gst_mxf_mux_pad_class_init (GstMXFMuxPadClass * klass)
99 {
100   GObjectClass *object_class = (GObjectClass *) klass;
101
102   object_class->finalize = gst_mxf_mux_pad_finalize;
103 }
104
105 static void
106 gst_mxf_mux_pad_init (GstMXFMuxPad * pad)
107 {
108   pad->adapter = gst_adapter_new ();
109 }
110
111 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
112     GST_PAD_SRC,
113     GST_PAD_ALWAYS,
114     GST_STATIC_CAPS ("application/mxf")
115     );
116
117 enum
118 {
119   PROP_0
120 };
121
122 #define gst_mxf_mux_parent_class parent_class
123 G_DEFINE_TYPE (GstMXFMux, gst_mxf_mux, GST_TYPE_AGGREGATOR);
124 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (mxfmux, "mxfmux", GST_RANK_PRIMARY,
125     GST_TYPE_MXF_MUX, mxf_element_init (plugin));
126
127 static void gst_mxf_mux_finalize (GObject * object);
128
129 static GstFlowReturn gst_mxf_mux_aggregate (GstAggregator * aggregator,
130     gboolean timeout);
131 static gboolean gst_mxf_mux_stop (GstAggregator * aggregator);
132
133 static gboolean gst_mxf_mux_src_event (GstAggregator * aggregator,
134     GstEvent * event);
135 static gboolean gst_mxf_mux_sink_event (GstAggregator * aggregator,
136     GstAggregatorPad * aggpad, GstEvent * event);
137 static GstAggregatorPad *gst_mxf_mux_create_new_pad (GstAggregator * aggregator,
138     GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
139
140 static void gst_mxf_mux_reset (GstMXFMux * mux);
141
142 static GstFlowReturn
143 gst_mxf_mux_push (GstMXFMux * mux, GstBuffer * buf)
144 {
145   guint size = gst_buffer_get_size (buf);
146   GstFlowReturn ret;
147
148   ret = gst_aggregator_finish_buffer (GST_AGGREGATOR (mux), buf);
149   mux->offset += size;
150
151   return ret;
152 }
153
154 static void
155 gst_mxf_mux_class_init (GstMXFMuxClass * klass)
156 {
157   GObjectClass *gobject_class;
158   GstElementClass *gstelement_class;
159   GstAggregatorClass *gstaggregator_class;
160   const GstPadTemplate **p;
161
162   GST_DEBUG_CATEGORY_INIT (mxfmux_debug, "mxfmux", 0, "MXF muxer");
163
164   gobject_class = (GObjectClass *) klass;
165   gstelement_class = (GstElementClass *) klass;
166   gstaggregator_class = (GstAggregatorClass *) klass;
167
168   gobject_class->finalize = gst_mxf_mux_finalize;
169
170   gstaggregator_class->create_new_pad =
171       GST_DEBUG_FUNCPTR (gst_mxf_mux_create_new_pad);
172   gstaggregator_class->src_event = GST_DEBUG_FUNCPTR (gst_mxf_mux_src_event);
173   gstaggregator_class->sink_event = GST_DEBUG_FUNCPTR (gst_mxf_mux_sink_event);
174   gstaggregator_class->stop = GST_DEBUG_FUNCPTR (gst_mxf_mux_stop);
175   gstaggregator_class->aggregate = GST_DEBUG_FUNCPTR (gst_mxf_mux_aggregate);
176
177   gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
178       &src_templ, GST_TYPE_MXF_MUX_PAD);
179
180   p = mxf_essence_element_writer_get_pad_templates ();
181   while (p && *p) {
182     gst_element_class_add_pad_template (gstelement_class,
183         (GstPadTemplate *) gst_object_ref (GST_OBJECT (*p)));
184     p++;
185   }
186
187   gst_element_class_set_static_metadata (gstelement_class, "MXF muxer",
188       "Codec/Muxer",
189       "Muxes video/audio streams into a MXF stream",
190       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
191
192   gst_type_mark_as_plugin_api (GST_TYPE_MXF_MUX_PAD, 0);
193 }
194
195 static void
196 gst_mxf_mux_init (GstMXFMux * mux)
197 {
198   mux->index_table = g_array_new (FALSE, FALSE, sizeof (MXFIndexTableSegment));
199   gst_mxf_mux_reset (mux);
200 }
201
202 static void
203 gst_mxf_mux_finalize (GObject * object)
204 {
205   GstMXFMux *mux = GST_MXF_MUX (object);
206
207   gst_mxf_mux_reset (mux);
208
209   if (mux->metadata) {
210     g_hash_table_destroy (mux->metadata);
211     mux->metadata = NULL;
212     g_list_free (mux->metadata_list);
213     mux->metadata_list = NULL;
214   }
215
216   if (mux->index_table) {
217     gsize n;
218     for (n = 0; n < mux->index_table->len; ++n)
219       g_free (g_array_index (mux->index_table, MXFIndexTableSegment,
220               n).index_entries);
221     g_array_free (mux->index_table, TRUE);
222     mux->index_table = NULL;
223   }
224
225   G_OBJECT_CLASS (parent_class)->finalize (object);
226 }
227
228 static void
229 gst_mxf_mux_reset (GstMXFMux * mux)
230 {
231   GList *l;
232   gsize n;
233
234   GST_OBJECT_LOCK (mux);
235   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
236     GstMXFMuxPad *pad = l->data;
237
238     gst_adapter_clear (pad->adapter);
239     g_free (pad->mapping_data);
240     pad->mapping_data = NULL;
241
242     pad->pos = 0;
243     pad->last_timestamp = 0;
244     pad->descriptor = NULL;
245     pad->have_complete_edit_unit = FALSE;
246
247     pad->source_package = NULL;
248     pad->source_track = NULL;
249   }
250   GST_OBJECT_UNLOCK (mux);
251
252   mux->state = GST_MXF_MUX_STATE_HEADER;
253
254   if (mux->metadata) {
255     g_hash_table_destroy (mux->metadata);
256     mux->preface = NULL;
257     g_list_free (mux->metadata_list);
258     mux->metadata_list = NULL;
259   }
260   mux->metadata = mxf_metadata_hash_table_new ();
261
262   mxf_partition_pack_reset (&mux->partition);
263   mxf_primer_pack_reset (&mux->primer);
264   memset (&mux->min_edit_rate, 0, sizeof (MXFFraction));
265   mux->last_gc_timestamp = 0;
266   mux->last_gc_position = 0;
267   mux->offset = 0;
268
269   if (mux->index_table)
270     for (n = 0; n < mux->index_table->len; ++n)
271       g_free (g_array_index (mux->index_table, MXFIndexTableSegment,
272               n).index_entries);
273   g_array_set_size (mux->index_table, 0);
274   mux->current_index_pos = 0;
275   mux->last_keyframe_pos = 0;
276 }
277
278 static gboolean
279 gst_mxf_mux_src_event (GstAggregator * aggregator, GstEvent * event)
280 {
281   switch (GST_EVENT_TYPE (event)) {
282     case GST_EVENT_SEEK:
283       /* disable seeking for now */
284       gst_event_unref (event);
285       return FALSE;
286     default:
287       return GST_AGGREGATOR_CLASS (parent_class)->src_event (aggregator, event);
288       break;
289   }
290
291   g_assert_not_reached ();
292 }
293
294 static gboolean
295 gst_mxf_mux_set_caps (GstMXFMux * mux, GstMXFMuxPad * pad, GstCaps * caps)
296 {
297   gboolean ret = TRUE;
298   MXFUUID d_instance_uid = { {0,} };
299   MXFMetadataFileDescriptor *old_descriptor = pad->descriptor;
300   GList *l;
301
302   GST_DEBUG_OBJECT (pad, "Setting caps %" GST_PTR_FORMAT, caps);
303
304   if (old_descriptor) {
305     memcpy (&d_instance_uid, &MXF_METADATA_BASE (old_descriptor)->instance_uid,
306         16);
307     pad->descriptor = NULL;
308     g_free (pad->mapping_data);
309     pad->mapping_data = NULL;
310   }
311
312   pad->descriptor =
313       pad->writer->get_descriptor (GST_PAD_PAD_TEMPLATE (pad), caps,
314       &pad->write_func, &pad->mapping_data);
315
316   if (!pad->descriptor) {
317     GST_ERROR_OBJECT (mux,
318         "Couldn't get descriptor for pad '%s' with caps %" GST_PTR_FORMAT,
319         GST_PAD_NAME (pad), caps);
320     return FALSE;
321   }
322
323   if (mxf_uuid_is_zero (&d_instance_uid))
324     mxf_uuid_init (&d_instance_uid, mux->metadata);
325
326   memcpy (&MXF_METADATA_BASE (pad->descriptor)->instance_uid, &d_instance_uid,
327       16);
328
329   if (old_descriptor) {
330     for (l = mux->metadata_list; l; l = l->next) {
331       MXFMetadataBase *tmp = l->data;
332
333       if (mxf_uuid_is_equal (&d_instance_uid, &tmp->instance_uid)) {
334         l->data = pad->descriptor;
335         break;
336       }
337     }
338   } else {
339     mux->metadata_list = g_list_prepend (mux->metadata_list, pad->descriptor);
340   }
341
342   g_hash_table_replace (mux->metadata,
343       &MXF_METADATA_BASE (pad->descriptor)->instance_uid, pad->descriptor);
344
345   if (old_descriptor) {
346     if (mux->preface && mux->preface->content_storage &&
347         mux->preface->content_storage->packages) {
348       guint i, j;
349
350       for (i = 0; i < mux->preface->content_storage->n_packages; i++) {
351         MXFMetadataSourcePackage *package;
352
353         if (!MXF_IS_METADATA_SOURCE_PACKAGE (mux->preface->
354                 content_storage->packages[i]))
355           continue;
356
357         package =
358             MXF_METADATA_SOURCE_PACKAGE (mux->preface->
359             content_storage->packages[i]);
360
361         if (!package->descriptor)
362           continue;
363
364         if (MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (package->descriptor)) {
365           MXFMetadataMultipleDescriptor *tmp =
366               MXF_METADATA_MULTIPLE_DESCRIPTOR (package->descriptor);
367
368           for (j = 0; j < tmp->n_sub_descriptors; j++) {
369             if (tmp->sub_descriptors[j] ==
370                 MXF_METADATA_GENERIC_DESCRIPTOR (old_descriptor)) {
371               tmp->sub_descriptors[j] =
372                   MXF_METADATA_GENERIC_DESCRIPTOR (pad->descriptor);
373               memcpy (&tmp->sub_descriptors_uids[j], &d_instance_uid, 16);
374             }
375           }
376         } else if (package->descriptor ==
377             MXF_METADATA_GENERIC_DESCRIPTOR (old_descriptor)) {
378           package->descriptor =
379               MXF_METADATA_GENERIC_DESCRIPTOR (pad->descriptor);
380           memcpy (&package->descriptor_uid, &d_instance_uid, 16);
381         }
382       }
383     }
384   }
385
386   return ret;
387 }
388
389 static gboolean
390 gst_mxf_mux_sink_event (GstAggregator * aggregator,
391     GstAggregatorPad * aggpad, GstEvent * event)
392 {
393   GstMXFMux *mux = GST_MXF_MUX (aggregator);
394   gboolean ret = TRUE;
395
396   switch (GST_EVENT_TYPE (event)) {
397     case GST_EVENT_TAG:
398       /* TODO: do something with the tags */
399       break;
400     case GST_EVENT_CAPS:{
401       GstCaps *caps;
402
403       gst_event_parse_caps (event, &caps);
404
405       ret = gst_mxf_mux_set_caps (mux, GST_MXF_MUX_PAD (aggpad), caps);
406
407       break;
408     }
409     default:
410       break;
411   }
412
413   /* now GstAggregator can take care of the rest, e.g. EOS */
414   if (ret)
415     ret =
416         GST_AGGREGATOR_CLASS (parent_class)->sink_event (aggregator, aggpad,
417         event);
418
419   return ret;
420 }
421
422 static char *
423 gst_mxf_mux_create_pad_name (GstPadTemplate * templ, guint id)
424 {
425   GString *string;
426
427   string = g_string_new (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ));
428   g_string_truncate (string, string->len - 2);
429   g_string_append_printf (string, "%u", id);
430
431   return g_string_free (string, FALSE);
432 }
433
434 static GstAggregatorPad *
435 gst_mxf_mux_create_new_pad (GstAggregator * aggregator,
436     GstPadTemplate * templ, const gchar * pad_name, const GstCaps * caps)
437 {
438   GstMXFMux *mux = GST_MXF_MUX (aggregator);
439   GstMXFMuxPad *pad;
440   guint pad_number;
441   gchar *name = NULL;
442   const MXFEssenceElementWriter *writer;
443
444   if (mux->state != GST_MXF_MUX_STATE_HEADER) {
445     GST_WARNING_OBJECT (mux, "Can't request pads after writing header");
446     return NULL;
447   }
448
449   writer = mxf_essence_element_writer_find (templ);
450   if (!writer) {
451     GST_ERROR_OBJECT (mux, "Not our template");
452     return NULL;
453   }
454   pad_number = g_atomic_int_add ((gint *) & mux->n_pads, 1);
455   name = gst_mxf_mux_create_pad_name (templ, pad_number);
456
457   GST_DEBUG_OBJECT (mux, "Creating pad '%s'", name);
458   pad =
459       g_object_new (GST_TYPE_MXF_MUX_PAD, "name", name, "direction",
460       GST_PAD_SINK, "template", templ, NULL);
461   g_free (name);
462   pad->last_timestamp = 0;
463   pad->writer = writer;
464
465   gst_pad_use_fixed_caps (GST_PAD_CAST (pad));
466
467   return GST_AGGREGATOR_PAD (pad);
468 }
469
470 static GstFlowReturn
471 gst_mxf_mux_create_metadata (GstMXFMux * mux)
472 {
473   GstFlowReturn ret = GST_FLOW_OK;
474   GList *l;
475   GArray *tmp;
476
477   GST_DEBUG_OBJECT (mux, "Creating MXF metadata");
478
479   GST_OBJECT_LOCK (mux);
480
481   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
482     GstMXFMuxPad *pad = l->data;
483     GstCaps *caps;
484     GstBuffer *buffer;
485
486     if (!pad || !pad->descriptor) {
487       GST_OBJECT_UNLOCK (mux);
488       return GST_FLOW_ERROR;
489     }
490
491     caps = gst_pad_get_current_caps (GST_PAD_CAST (pad));
492     if (!caps) {
493       GST_OBJECT_UNLOCK (mux);
494       return GST_FLOW_ERROR;
495     }
496
497     buffer = gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
498     if (pad->writer->update_descriptor)
499       pad->writer->update_descriptor (pad->descriptor,
500           caps, pad->mapping_data, buffer);
501     if (buffer)
502       gst_buffer_unref (buffer);
503     gst_caps_unref (caps);
504   }
505
506   /* Preface */
507   mux->preface =
508       (MXFMetadataPreface *) g_object_new (MXF_TYPE_METADATA_PREFACE, NULL);
509   mxf_uuid_init (&MXF_METADATA_BASE (mux->preface)->instance_uid,
510       mux->metadata);
511   g_hash_table_insert (mux->metadata,
512       &MXF_METADATA_BASE (mux->preface)->instance_uid, mux->preface);
513   mux->metadata_list = g_list_prepend (mux->metadata_list, mux->preface);
514
515   mxf_timestamp_set_now (&mux->preface->last_modified_date);
516   mux->preface->version = 258;
517   mux->preface->object_model_version = 1;
518
519   mxf_op_set_generalized (&mux->preface->operational_pattern, MXF_OP_1a, TRUE,
520       TRUE, FALSE);
521
522   tmp = g_array_new (FALSE, FALSE, sizeof (MXFUL));
523   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
524     GstMXFMuxPad *pad = l->data;
525     guint i;
526     gboolean found = FALSE;
527
528     if (!pad || !pad->descriptor ||
529         mxf_ul_is_zero (&pad->descriptor->essence_container)) {
530       GST_OBJECT_UNLOCK (mux);
531       return GST_FLOW_ERROR;
532     }
533
534     for (i = 0; i < tmp->len; i++) {
535       if (mxf_ul_is_equal (&pad->descriptor->essence_container,
536               &g_array_index (tmp, MXFUL, i))) {
537         found = TRUE;
538         break;
539       }
540     }
541
542     if (found)
543       continue;
544
545     g_array_append_val (tmp, pad->descriptor->essence_container);
546   }
547   mux->preface->n_essence_containers = tmp->len;
548   mux->preface->essence_containers = (MXFUL *) g_array_free (tmp, FALSE);
549
550   /* This will later be used as UID for the material package */
551   mxf_uuid_init (&mux->preface->primary_package_uid, mux->metadata);
552
553   /* Identifications */
554   {
555     MXFMetadataIdentification *identification;
556     static const guint8 gst_uid[] = {
557       0xe5, 0xde, 0xcd, 0x04, 0x24, 0x90, 0x69, 0x18,
558       0x8a, 0xc9, 0xb5, 0xd7, 0x02, 0x58, 0x46, 0x78
559     };
560     guint major, minor, micro, nano;
561
562     mux->preface->n_identifications = 1;
563     mux->preface->identifications = g_new0 (MXFMetadataIdentification *, 1);
564     identification = mux->preface->identifications[0] =
565         (MXFMetadataIdentification *)
566         g_object_new (MXF_TYPE_METADATA_IDENTIFICATION, NULL);
567
568     mxf_uuid_init (&MXF_METADATA_BASE (identification)->instance_uid,
569         mux->metadata);
570     g_hash_table_insert (mux->metadata,
571         &MXF_METADATA_BASE (identification)->instance_uid, identification);
572     mux->metadata_list = g_list_prepend (mux->metadata_list, identification);
573
574     mxf_uuid_init (&identification->this_generation_uid, NULL);
575
576     identification->company_name = g_strdup ("GStreamer");
577     identification->product_name = g_strdup ("GStreamer Multimedia Framework");
578
579     gst_version (&major, &minor, &micro, &nano);
580     identification->product_version.major = major;
581     identification->product_version.minor = minor;
582     identification->product_version.patch = micro;
583     identification->product_version.build = nano;
584     identification->product_version.release =
585         (nano == 0) ? 1 : (nano == 1) ? 2 : 4;
586
587     identification->version_string =
588         g_strdup_printf ("%u.%u.%u.%u", major, minor, micro, nano);
589     memcpy (&identification->product_uid, &gst_uid, 16);
590
591     memcpy (&identification->modification_date,
592         &mux->preface->last_modified_date, sizeof (MXFTimestamp));
593     memcpy (&identification->toolkit_version, &identification->product_version,
594         sizeof (MXFProductVersion));
595
596 #ifdef HAVE_SYS_UTSNAME_H
597     {
598       struct utsname sys_details;
599
600       if (uname (&sys_details) == 0) {
601         identification->platform = g_strdup_printf ("%s %s %s",
602             sys_details.sysname, sys_details.release, sys_details.machine);
603       }
604     }
605 #endif
606
607 #if defined(G_OS_WIN32)
608     if (identification->platform == NULL)
609       identification->platform = g_strdup ("Microsoft Windows");
610 #elif defined(G_OS_BEOS)
611     if (identification->platform == NULL)
612       identification->platform = g_strdup ("BEOS");
613 #elif defined(G_OS_UNIX)
614     if (identification->platform == NULL)
615       identification->platform = g_strdup ("Unix");
616 #endif
617   }
618
619   /* Content storage */
620   {
621     MXFMetadataContentStorage *cstorage;
622     guint i;
623
624     cstorage = mux->preface->content_storage = (MXFMetadataContentStorage *)
625         g_object_new (MXF_TYPE_METADATA_CONTENT_STORAGE, NULL);
626     mxf_uuid_init (&MXF_METADATA_BASE (cstorage)->instance_uid, mux->metadata);
627     g_hash_table_insert (mux->metadata,
628         &MXF_METADATA_BASE (cstorage)->instance_uid, cstorage);
629     mux->metadata_list = g_list_prepend (mux->metadata_list, cstorage);
630
631     cstorage->n_packages = 2;
632     cstorage->packages = g_new0 (MXFMetadataGenericPackage *, 2);
633
634     /* Source package */
635     {
636       MXFMetadataSourcePackage *p;
637
638       cstorage->packages[1] = (MXFMetadataGenericPackage *)
639           g_object_new (MXF_TYPE_METADATA_SOURCE_PACKAGE, NULL);
640       mxf_uuid_init (&MXF_METADATA_BASE (cstorage->packages[1])->instance_uid,
641           mux->metadata);
642       g_hash_table_insert (mux->metadata,
643           &MXF_METADATA_BASE (cstorage->packages[1])->instance_uid,
644           cstorage->packages[1]);
645       mux->metadata_list =
646           g_list_prepend (mux->metadata_list, cstorage->packages[1]);
647       p = (MXFMetadataSourcePackage *) cstorage->packages[1];
648
649       mxf_umid_init (&p->parent.package_uid);
650       p->parent.name = g_strdup ("Source package");
651       memcpy (&p->parent.package_creation_date,
652           &mux->preface->last_modified_date, sizeof (MXFTimestamp));
653       memcpy (&p->parent.package_modified_date,
654           &mux->preface->last_modified_date, sizeof (MXFTimestamp));
655
656       p->parent.n_tracks = GST_ELEMENT_CAST (mux)->numsinkpads + 1;
657       p->parent.tracks = g_new0 (MXFMetadataTrack *, p->parent.n_tracks);
658
659       if (p->parent.n_tracks > 2) {
660         MXFMetadataMultipleDescriptor *d;
661
662         p->descriptor = (MXFMetadataGenericDescriptor *)
663             g_object_new (MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR, NULL);
664         d = (MXFMetadataMultipleDescriptor *) p->descriptor;
665         d->n_sub_descriptors = p->parent.n_tracks - 1;
666         d->sub_descriptors =
667             g_new0 (MXFMetadataGenericDescriptor *, p->parent.n_tracks - 1);
668
669         mxf_uuid_init (&MXF_METADATA_BASE (d)->instance_uid, mux->metadata);
670         g_hash_table_insert (mux->metadata,
671             &MXF_METADATA_BASE (d)->instance_uid, d);
672         mux->metadata_list = g_list_prepend (mux->metadata_list, d);
673       }
674
675       /* Tracks */
676       {
677         guint n;
678
679         n = 1;
680
681         /* Essence tracks */
682         for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
683           GstMXFMuxPad *pad = l->data;
684           MXFMetadataTimelineTrack *track;
685           MXFMetadataSequence *sequence;
686           MXFMetadataSourceClip *clip;
687           GstCaps *caps;
688           GstBuffer *buffer;
689
690           p->parent.tracks[n] = (MXFMetadataTrack *)
691               g_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK, NULL);
692           track = (MXFMetadataTimelineTrack *) p->parent.tracks[n];
693           mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid,
694               mux->metadata);
695           g_hash_table_insert (mux->metadata,
696               &MXF_METADATA_BASE (track)->instance_uid, track);
697           mux->metadata_list = g_list_prepend (mux->metadata_list, track);
698
699           caps = gst_pad_get_current_caps (GST_PAD_CAST (pad));
700           buffer = gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
701           track->parent.track_id = n + 1;
702           track->parent.track_number =
703               pad->writer->get_track_number_template (pad->descriptor,
704               caps, pad->mapping_data);
705
706           /* FIXME: All tracks in a source package must have the same edit
707            * rate! This means that if we have different edit rates, we need to
708            * make them different source packages and essence containers with
709            * a different BodySID */
710           pad->writer->get_edit_rate (pad->descriptor,
711               caps, pad->mapping_data, buffer, p, track, &track->edit_rate);
712           if (buffer)
713             gst_buffer_unref (buffer);
714           gst_caps_unref (caps);
715
716           sequence = track->parent.sequence = (MXFMetadataSequence *)
717               g_object_new (MXF_TYPE_METADATA_SEQUENCE, NULL);
718           mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid,
719               mux->metadata);
720           g_hash_table_insert (mux->metadata,
721               &MXF_METADATA_BASE (sequence)->instance_uid, sequence);
722           mux->metadata_list = g_list_prepend (mux->metadata_list, sequence);
723
724           memcpy (&sequence->data_definition, &pad->writer->data_definition,
725               16);
726
727           sequence->n_structural_components = 1;
728           sequence->structural_components =
729               g_new0 (MXFMetadataStructuralComponent *, 1);
730
731           clip = (MXFMetadataSourceClip *)
732               g_object_new (MXF_TYPE_METADATA_SOURCE_CLIP, NULL);
733           sequence->structural_components[0] =
734               (MXFMetadataStructuralComponent *) clip;
735           mxf_uuid_init (&MXF_METADATA_BASE (clip)->instance_uid,
736               mux->metadata);
737           g_hash_table_insert (mux->metadata,
738               &MXF_METADATA_BASE (clip)->instance_uid, clip);
739           mux->metadata_list = g_list_prepend (mux->metadata_list, clip);
740
741           memcpy (&clip->parent.data_definition, &sequence->data_definition,
742               16);
743           clip->start_position = 0;
744
745           pad->source_package = p;
746           pad->source_track = track;
747           pad->descriptor->linked_track_id = n + 1;
748           if (p->parent.n_tracks == 2) {
749             p->descriptor = (MXFMetadataGenericDescriptor *) pad->descriptor;
750           } else {
751             MXF_METADATA_MULTIPLE_DESCRIPTOR (p->
752                 descriptor)->sub_descriptors[n - 1] =
753                 (MXFMetadataGenericDescriptor *) pad->descriptor;
754           }
755
756           n++;
757         }
758       }
759     }
760
761     /* Material package */
762     {
763       MXFMetadataMaterialPackage *p;
764       MXFFraction min_edit_rate = { 0, 0 };
765       gdouble min_edit_rate_d = G_MAXDOUBLE;
766
767       cstorage->packages[0] = (MXFMetadataGenericPackage *)
768           g_object_new (MXF_TYPE_METADATA_MATERIAL_PACKAGE, NULL);
769       memcpy (&MXF_METADATA_BASE (cstorage->packages[0])->instance_uid,
770           &mux->preface->primary_package_uid, 16);
771       g_hash_table_insert (mux->metadata,
772           &MXF_METADATA_BASE (cstorage->packages[0])->instance_uid,
773           cstorage->packages[0]);
774       mux->metadata_list =
775           g_list_prepend (mux->metadata_list, cstorage->packages[0]);
776       p = (MXFMetadataMaterialPackage *) cstorage->packages[0];
777
778       mxf_umid_init (&p->package_uid);
779       p->name = g_strdup ("Material package");
780       memcpy (&p->package_creation_date, &mux->preface->last_modified_date,
781           sizeof (MXFTimestamp));
782       memcpy (&p->package_modified_date, &mux->preface->last_modified_date,
783           sizeof (MXFTimestamp));
784
785       p->n_tracks = GST_ELEMENT_CAST (mux)->numsinkpads + 1;
786       p->tracks = g_new0 (MXFMetadataTrack *, p->n_tracks);
787
788       /* Tracks */
789       {
790         guint n;
791
792         n = 1;
793         /* Essence tracks */
794         for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
795           GstMXFMuxPad *pad = l->data;
796           GstCaps *caps;
797           GstBuffer *buffer;
798           MXFMetadataSourcePackage *source_package;
799           MXFMetadataTimelineTrack *track, *source_track;
800           MXFMetadataSequence *sequence;
801           MXFMetadataSourceClip *clip;
802
803           source_package = MXF_METADATA_SOURCE_PACKAGE (cstorage->packages[1]);
804           source_track =
805               MXF_METADATA_TIMELINE_TRACK (source_package->parent.tracks[n]);
806
807           p->tracks[n] = (MXFMetadataTrack *)
808               g_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK, NULL);
809           track = (MXFMetadataTimelineTrack *) p->tracks[n];
810           mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid,
811               mux->metadata);
812           g_hash_table_insert (mux->metadata,
813               &MXF_METADATA_BASE (track)->instance_uid, track);
814           mux->metadata_list = g_list_prepend (mux->metadata_list, track);
815
816           track->parent.track_id = n + 1;
817           track->parent.track_number = 0;
818
819           caps = gst_pad_get_current_caps (GST_PAD_CAST (pad));
820           buffer = gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
821           pad->writer->get_edit_rate (pad->descriptor,
822               caps, pad->mapping_data,
823               buffer, source_package, source_track, &track->edit_rate);
824           if (buffer)
825             gst_buffer_unref (buffer);
826           gst_caps_unref (caps);
827
828           if (track->edit_rate.n != source_track->edit_rate.n ||
829               track->edit_rate.d != source_track->edit_rate.d) {
830             memcpy (&source_track->edit_rate, &track->edit_rate,
831                 sizeof (MXFFraction));
832           }
833
834           if (track->edit_rate.d <= 0 || track->edit_rate.n <= 0) {
835             GST_ERROR_OBJECT (mux, "Invalid edit rate");
836             GST_OBJECT_UNLOCK (mux);
837             return GST_FLOW_ERROR;
838           }
839
840           if (min_edit_rate_d >
841               ((gdouble) track->edit_rate.n) / ((gdouble) track->edit_rate.d)) {
842             min_edit_rate_d =
843                 ((gdouble) track->edit_rate.n) / ((gdouble) track->edit_rate.d);
844             memcpy (&min_edit_rate, &track->edit_rate, sizeof (MXFFraction));
845           }
846
847           sequence = track->parent.sequence = (MXFMetadataSequence *)
848               g_object_new (MXF_TYPE_METADATA_SEQUENCE, NULL);
849           mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid,
850               mux->metadata);
851           g_hash_table_insert (mux->metadata,
852               &MXF_METADATA_BASE (sequence)->instance_uid, sequence);
853           mux->metadata_list = g_list_prepend (mux->metadata_list, sequence);
854
855           memcpy (&sequence->data_definition, &pad->writer->data_definition,
856               16);
857           sequence->n_structural_components = 1;
858           sequence->structural_components =
859               g_new0 (MXFMetadataStructuralComponent *, 1);
860
861           clip = (MXFMetadataSourceClip *)
862               g_object_new (MXF_TYPE_METADATA_SOURCE_CLIP, NULL);
863           sequence->structural_components[0] =
864               (MXFMetadataStructuralComponent *) clip;
865           mxf_uuid_init (&MXF_METADATA_BASE (clip)->instance_uid,
866               mux->metadata);
867           g_hash_table_insert (mux->metadata,
868               &MXF_METADATA_BASE (clip)->instance_uid, clip);
869           mux->metadata_list = g_list_prepend (mux->metadata_list, clip);
870
871           memcpy (&clip->parent.data_definition, &sequence->data_definition,
872               16);
873           clip->start_position = 0;
874
875           memcpy (&clip->source_package_id, &cstorage->packages[1]->package_uid,
876               32);
877           clip->source_track_id = n + 1;
878
879           n++;
880         }
881
882         n = 0;
883         /* Timecode track */
884         {
885           MXFMetadataTimelineTrack *track;
886           MXFMetadataSequence *sequence;
887           MXFMetadataTimecodeComponent *component;
888
889           p->tracks[n] = (MXFMetadataTrack *)
890               g_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK, NULL);
891           track = (MXFMetadataTimelineTrack *) p->tracks[n];
892           mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid,
893               mux->metadata);
894           g_hash_table_insert (mux->metadata,
895               &MXF_METADATA_BASE (track)->instance_uid, track);
896           mux->metadata_list = g_list_prepend (mux->metadata_list, track);
897
898           track->parent.track_id = n + 1;
899           track->parent.track_number = 0;
900           track->parent.track_name = g_strdup ("Timecode track");
901           /* FIXME: Is this correct? */
902           memcpy (&track->edit_rate, &min_edit_rate, sizeof (MXFFraction));
903
904           sequence = track->parent.sequence = (MXFMetadataSequence *)
905               g_object_new (MXF_TYPE_METADATA_SEQUENCE, NULL);
906           mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid,
907               mux->metadata);
908           g_hash_table_insert (mux->metadata,
909               &MXF_METADATA_BASE (sequence)->instance_uid, sequence);
910           mux->metadata_list = g_list_prepend (mux->metadata_list, sequence);
911
912           memcpy (&sequence->data_definition,
913               mxf_metadata_track_identifier_get
914               (MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE), 16);
915
916           sequence->n_structural_components = 1;
917           sequence->structural_components =
918               g_new0 (MXFMetadataStructuralComponent *, 1);
919
920           component = (MXFMetadataTimecodeComponent *)
921               g_object_new (MXF_TYPE_METADATA_TIMECODE_COMPONENT, NULL);
922           sequence->structural_components[0] =
923               (MXFMetadataStructuralComponent *) component;
924           mxf_uuid_init (&MXF_METADATA_BASE (component)->instance_uid,
925               mux->metadata);
926           g_hash_table_insert (mux->metadata,
927               &MXF_METADATA_BASE (component)->instance_uid, component);
928           mux->metadata_list = g_list_prepend (mux->metadata_list, component);
929
930           memcpy (&component->parent.data_definition,
931               &sequence->data_definition, 16);
932
933           component->start_timecode = 0;
934           if (track->edit_rate.d == 0)
935             component->rounded_timecode_base = 1;
936           else
937             component->rounded_timecode_base =
938                 (((gdouble) track->edit_rate.n) /
939                 ((gdouble) track->edit_rate.d) + 0.5);
940           /* TODO: drop frame */
941         }
942
943         memcpy (&mux->min_edit_rate, &min_edit_rate, sizeof (MXFFraction));
944       }
945     }
946
947     /* Timecode track */
948     {
949       MXFMetadataSourcePackage *p;
950       MXFMetadataTimelineTrack *track;
951       MXFMetadataSequence *sequence;
952       MXFMetadataTimecodeComponent *component;
953       guint n = 0;
954
955       p = (MXFMetadataSourcePackage *) cstorage->packages[1];
956
957       p->parent.tracks[n] = (MXFMetadataTrack *)
958           g_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK, NULL);
959       track = (MXFMetadataTimelineTrack *) p->parent.tracks[n];
960       mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid, mux->metadata);
961       g_hash_table_insert (mux->metadata,
962           &MXF_METADATA_BASE (track)->instance_uid, track);
963       mux->metadata_list = g_list_prepend (mux->metadata_list, track);
964
965       track->parent.track_id = n + 1;
966       track->parent.track_number = 0;
967       track->parent.track_name = g_strdup ("Timecode track");
968       /* FIXME: Is this correct? */
969       memcpy (&track->edit_rate, &mux->min_edit_rate, sizeof (MXFFraction));
970
971       sequence = track->parent.sequence = (MXFMetadataSequence *)
972           g_object_new (MXF_TYPE_METADATA_SEQUENCE, NULL);
973       mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid,
974           mux->metadata);
975       g_hash_table_insert (mux->metadata,
976           &MXF_METADATA_BASE (sequence)->instance_uid, sequence);
977       mux->metadata_list = g_list_prepend (mux->metadata_list, sequence);
978
979       memcpy (&sequence->data_definition,
980           mxf_metadata_track_identifier_get
981           (MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE), 16);
982
983       sequence->n_structural_components = 1;
984       sequence->structural_components =
985           g_new0 (MXFMetadataStructuralComponent *, 1);
986
987       component = (MXFMetadataTimecodeComponent *)
988           g_object_new (MXF_TYPE_METADATA_TIMECODE_COMPONENT, NULL);
989       sequence->structural_components[0] =
990           (MXFMetadataStructuralComponent *) component;
991       mxf_uuid_init (&MXF_METADATA_BASE (component)->instance_uid,
992           mux->metadata);
993       g_hash_table_insert (mux->metadata,
994           &MXF_METADATA_BASE (component)->instance_uid, component);
995       mux->metadata_list = g_list_prepend (mux->metadata_list, component);
996
997       memcpy (&component->parent.data_definition,
998           &sequence->data_definition, 16);
999
1000       component->start_timecode = 0;
1001       if (track->edit_rate.d == 0)
1002         component->rounded_timecode_base = 1;
1003       else
1004         component->rounded_timecode_base =
1005             (((gdouble) track->edit_rate.n) /
1006             ((gdouble) track->edit_rate.d) + 0.5);
1007       /* TODO: drop frame */
1008     }
1009
1010
1011     for (i = 1; i < cstorage->packages[1]->n_tracks; i++) {
1012       MXFMetadataTrack *track = cstorage->packages[1]->tracks[i];
1013       guint j;
1014       guint32 templ;
1015       guint8 n_type, n;
1016
1017       if ((track->track_number & 0x00ff00ff) != 0)
1018         continue;
1019
1020       templ = track->track_number;
1021       n_type = 0;
1022
1023       for (j = 1; j < cstorage->packages[1]->n_tracks; j++) {
1024         MXFMetadataTrack *tmp = cstorage->packages[1]->tracks[j];
1025
1026         if (tmp->track_number == templ) {
1027           n_type++;
1028         }
1029       }
1030
1031       n = 0;
1032       for (j = 1; j < cstorage->packages[1]->n_tracks; j++) {
1033         MXFMetadataTrack *tmp = cstorage->packages[1]->tracks[j];
1034
1035         if (tmp->track_number == templ) {
1036           n++;
1037           tmp->track_number |= (n_type << 16) | (n);
1038         }
1039       }
1040     }
1041
1042     cstorage->n_essence_container_data = 1;
1043     cstorage->essence_container_data =
1044         g_new0 (MXFMetadataEssenceContainerData *, 1);
1045     cstorage->essence_container_data[0] = (MXFMetadataEssenceContainerData *)
1046         g_object_new (MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA, NULL);
1047     mxf_uuid_init (&MXF_METADATA_BASE (cstorage->essence_container_data[0])->
1048         instance_uid, mux->metadata);
1049     g_hash_table_insert (mux->metadata,
1050         &MXF_METADATA_BASE (cstorage->essence_container_data[0])->instance_uid,
1051         cstorage->essence_container_data[0]);
1052     mux->metadata_list =
1053         g_list_prepend (mux->metadata_list,
1054         cstorage->essence_container_data[0]);
1055
1056     cstorage->essence_container_data[0]->linked_package =
1057         MXF_METADATA_SOURCE_PACKAGE (cstorage->packages[1]);
1058     cstorage->essence_container_data[0]->index_sid = 2;
1059     cstorage->essence_container_data[0]->body_sid = 1;
1060   }
1061
1062   /* Sort descriptors at the correct places */
1063   {
1064     GList *l;
1065     GList *descriptors = NULL;
1066
1067     for (l = mux->metadata_list; l; l = l->next) {
1068       MXFMetadataBase *m = l->data;
1069
1070       if (MXF_IS_METADATA_GENERIC_DESCRIPTOR (m)
1071           && !MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (m)) {
1072         descriptors = l;
1073         l->prev->next = NULL;
1074         l->prev = NULL;
1075         break;
1076       }
1077     }
1078
1079     g_assert (descriptors != NULL);
1080
1081     for (l = mux->metadata_list; l; l = l->next) {
1082       MXFMetadataBase *m = l->data;
1083       GList *s;
1084
1085       if (MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (m) ||
1086           MXF_IS_METADATA_SOURCE_PACKAGE (m)) {
1087         s = l->prev;
1088         l->prev = g_list_last (descriptors);
1089         s->next = descriptors;
1090         descriptors->prev = s;
1091         l->prev->next = l;
1092         break;
1093       }
1094     }
1095   }
1096
1097   GST_OBJECT_UNLOCK (mux);
1098
1099   mux->metadata_list = g_list_reverse (mux->metadata_list);
1100
1101   return ret;
1102 }
1103
1104 static GstFlowReturn
1105 gst_mxf_mux_init_partition_pack (GstMXFMux * mux)
1106 {
1107   GList *l;
1108   guint i = 0;
1109
1110   mxf_partition_pack_reset (&mux->partition);
1111   mux->partition.type = MXF_PARTITION_PACK_HEADER;
1112   mux->partition.closed = mux->partition.complete = FALSE;
1113   mux->partition.major_version = 0x0001;
1114   mux->partition.minor_version = 0x0002;
1115   mux->partition.kag_size = 1;
1116   mux->partition.this_partition = 0;
1117   mux->partition.prev_partition = 0;
1118   mux->partition.footer_partition = 0;
1119   mux->partition.header_byte_count = 0;
1120   mux->partition.index_byte_count = 0;
1121   mux->partition.index_sid = 0;
1122   mux->partition.body_offset = 0;
1123   mux->partition.body_sid = 0;
1124
1125   memcpy (&mux->partition.operational_pattern,
1126       &mux->preface->operational_pattern, 16);
1127
1128   GST_OBJECT_LOCK (mux);
1129   mux->partition.n_essence_containers = GST_ELEMENT_CAST (mux)->numsinkpads;
1130   mux->partition.essence_containers =
1131       g_new0 (MXFUL, mux->partition.n_essence_containers);
1132
1133   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
1134     GstMXFMuxPad *pad = l->data;
1135     guint j;
1136     gboolean found = FALSE;
1137
1138     for (j = 0; j <= i; j++) {
1139       if (mxf_ul_is_equal (&pad->descriptor->essence_container,
1140               &mux->partition.essence_containers[j])) {
1141         found = TRUE;
1142         break;
1143       }
1144     }
1145
1146     if (found)
1147       continue;
1148
1149     memcpy (&mux->partition.essence_containers[i],
1150         &pad->descriptor->essence_container, 16);
1151     i++;
1152   }
1153   mux->partition.n_essence_containers = i;
1154   GST_OBJECT_UNLOCK (mux);
1155
1156   return GST_FLOW_OK;
1157 }
1158
1159 static GstFlowReturn
1160 gst_mxf_mux_write_header_metadata (GstMXFMux * mux)
1161 {
1162   GstFlowReturn ret = GST_FLOW_OK;
1163   GstBuffer *buf;
1164   GList *buffers = NULL;
1165   GList *l;
1166   MXFMetadataBase *m;
1167   guint64 header_byte_count = 0;
1168
1169   for (l = mux->metadata_list; l; l = l->next) {
1170     m = l->data;
1171     buf = mxf_metadata_base_to_buffer (m, &mux->primer);
1172     header_byte_count += gst_buffer_get_size (buf);
1173     buffers = g_list_prepend (buffers, buf);
1174   }
1175
1176   buffers = g_list_reverse (buffers);
1177   buf = mxf_primer_pack_to_buffer (&mux->primer);
1178   header_byte_count += gst_buffer_get_size (buf);
1179   buffers = g_list_prepend (buffers, buf);
1180
1181   mux->partition.header_byte_count = header_byte_count;
1182   buf = mxf_partition_pack_to_buffer (&mux->partition);
1183   if ((ret = gst_mxf_mux_push (mux, buf)) != GST_FLOW_OK) {
1184     GST_ERROR_OBJECT (mux, "Failed pushing partition: %s",
1185         gst_flow_get_name (ret));
1186     g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
1187     g_list_free (buffers);
1188     return ret;
1189   }
1190
1191   for (l = buffers; l; l = l->next) {
1192     buf = l->data;
1193     l->data = NULL;
1194     if ((ret = gst_mxf_mux_push (mux, buf)) != GST_FLOW_OK) {
1195       GST_ERROR_OBJECT (mux, "Failed pushing buffer: %s",
1196           gst_flow_get_name (ret));
1197       g_list_foreach (l, (GFunc) gst_mini_object_unref, NULL);
1198       g_list_free (buffers);
1199       return ret;
1200     }
1201   }
1202
1203   g_list_free (buffers);
1204
1205   return ret;
1206 }
1207
1208 static const guint8 _gc_essence_element_ul[] = {
1209   0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x01,
1210   0x0d, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00
1211 };
1212
1213 static GstFlowReturn
1214 gst_mxf_mux_handle_buffer (GstMXFMux * mux, GstMXFMuxPad * pad)
1215 {
1216   GstBuffer *buf = gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
1217   GstBuffer *outbuf = NULL;
1218   GstMapInfo map;
1219   gsize buf_size;
1220   GstFlowReturn ret = GST_FLOW_OK;
1221   guint8 slen, ber[9];
1222   gboolean flush = gst_aggregator_pad_is_eos (GST_AGGREGATOR_PAD (pad))
1223       && !pad->have_complete_edit_unit && buf == NULL;
1224   gboolean is_keyframe = buf ?
1225       !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) : TRUE;
1226   GstClockTime pts = buf ? GST_BUFFER_PTS (buf) : GST_CLOCK_TIME_NONE;
1227   GstClockTime dts = buf ? GST_BUFFER_DTS (buf) : GST_CLOCK_TIME_NONE;
1228
1229   if (pad->have_complete_edit_unit) {
1230     GST_DEBUG_OBJECT (pad,
1231         "Handling remaining buffer for track %u at position %" G_GINT64_FORMAT,
1232         pad->source_track->parent.track_id, pad->pos);
1233     if (buf)
1234       gst_buffer_unref (buf);
1235     buf = NULL;
1236   } else if (!flush) {
1237     if (buf)
1238       gst_buffer_unref (buf);
1239     buf = gst_aggregator_pad_pop_buffer (GST_AGGREGATOR_PAD (pad));
1240   }
1241
1242   if (buf) {
1243     GST_DEBUG_OBJECT (pad,
1244         "Handling buffer of size %" G_GSIZE_FORMAT " for track %u at position %"
1245         G_GINT64_FORMAT, gst_buffer_get_size (buf),
1246         pad->source_track->parent.track_id, pad->pos);
1247   } else {
1248     flush = TRUE;
1249     GST_DEBUG_OBJECT (pad,
1250         "Flushing for track %u at position %" G_GINT64_FORMAT,
1251         pad->source_track->parent.track_id, pad->pos);
1252   }
1253
1254   ret = pad->write_func (buf, pad->mapping_data, pad->adapter, &outbuf, flush);
1255   if (ret != GST_FLOW_OK && ret != GST_FLOW_CUSTOM_SUCCESS) {
1256     GST_ERROR_OBJECT (pad,
1257         "Failed handling buffer for track %u, reason %s",
1258         pad->source_track->parent.track_id, gst_flow_get_name (ret));
1259     return ret;
1260   }
1261
1262   if (ret == GST_FLOW_CUSTOM_SUCCESS) {
1263     pad->have_complete_edit_unit = TRUE;
1264     ret = GST_FLOW_OK;
1265   } else {
1266     pad->have_complete_edit_unit = FALSE;
1267   }
1268
1269   buf = outbuf;
1270   if (buf == NULL)
1271     return ret;
1272
1273   /* We currently only index the first essence stream */
1274   if (pad == (GstMXFMuxPad *) GST_ELEMENT_CAST (mux)->sinkpads->data) {
1275     MXFIndexTableSegment *segment;
1276     const gint max_segment_size = G_MAXUINT16 / 11;
1277
1278     if (mux->index_table->len == 0 ||
1279         g_array_index (mux->index_table, MXFIndexTableSegment,
1280             mux->current_index_pos).index_duration >= max_segment_size) {
1281
1282       if (mux->index_table->len > 0)
1283         mux->current_index_pos++;
1284
1285       if (mux->index_table->len <= mux->current_index_pos) {
1286         MXFIndexTableSegment s;
1287
1288         memset (&segment, 0, sizeof (segment));
1289
1290         mxf_uuid_init (&s.instance_id, mux->metadata);
1291         memcpy (&s.index_edit_rate, &pad->source_track->edit_rate,
1292             sizeof (s.index_edit_rate));
1293         if (mux->index_table->len > 0)
1294           s.index_start_position =
1295               g_array_index (mux->index_table, MXFIndexTableSegment,
1296               mux->index_table->len - 1).index_start_position;
1297         else
1298           s.index_start_position = 0;
1299         s.index_duration = 0;
1300         s.edit_unit_byte_count = 0;
1301         s.index_sid =
1302             mux->preface->content_storage->essence_container_data[0]->index_sid;
1303         s.body_sid =
1304             mux->preface->content_storage->essence_container_data[0]->body_sid;
1305         s.slice_count = 0;
1306         s.pos_table_count = 0;
1307         s.n_delta_entries = 0;
1308         s.delta_entries = NULL;
1309         s.n_index_entries = 0;
1310         s.index_entries = g_new0 (MXFIndexEntry, max_segment_size);
1311         g_array_append_val (mux->index_table, s);
1312       }
1313     }
1314     segment =
1315         &g_array_index (mux->index_table, MXFIndexTableSegment,
1316         mux->current_index_pos);
1317
1318     if (dts != GST_CLOCK_TIME_NONE && pts != GST_CLOCK_TIME_NONE) {
1319       guint64 pts_pos;
1320       guint64 pts_index_pos, pts_segment_pos;
1321       gint64 index_pos_diff;
1322       MXFIndexTableSegment *pts_segment;
1323
1324       pts =
1325           gst_segment_to_running_time (&pad->parent.segment, GST_FORMAT_TIME,
1326           pts);
1327       pts_pos =
1328           gst_util_uint64_scale_round (pts, pad->source_track->edit_rate.n,
1329           pad->source_track->edit_rate.d * GST_SECOND);
1330
1331       index_pos_diff = pts_pos - pad->pos;
1332       pts_index_pos = mux->current_index_pos;
1333       pts_segment_pos = segment->n_index_entries;
1334       if (index_pos_diff >= 0) {
1335         while (pts_segment_pos + index_pos_diff >= max_segment_size) {
1336           index_pos_diff -= max_segment_size - pts_segment_pos;
1337           pts_segment_pos = 0;
1338           pts_index_pos++;
1339
1340           if (pts_index_pos >= mux->index_table->len) {
1341             MXFIndexTableSegment s;
1342
1343             memset (&segment, 0, sizeof (segment));
1344
1345             mxf_uuid_init (&s.instance_id, mux->metadata);
1346             memcpy (&s.index_edit_rate, &pad->source_track->edit_rate,
1347                 sizeof (s.index_edit_rate));
1348             if (mux->index_table->len > 0)
1349               s.index_start_position =
1350                   g_array_index (mux->index_table, MXFIndexTableSegment,
1351                   mux->index_table->len - 1).index_start_position;
1352             else
1353               s.index_start_position = 0;
1354             s.index_duration = 0;
1355             s.edit_unit_byte_count = 0;
1356             s.index_sid =
1357                 mux->preface->content_storage->
1358                 essence_container_data[0]->index_sid;
1359             s.body_sid =
1360                 mux->preface->content_storage->
1361                 essence_container_data[0]->body_sid;
1362             s.slice_count = 0;
1363             s.pos_table_count = 0;
1364             s.n_delta_entries = 0;
1365             s.delta_entries = NULL;
1366             s.n_index_entries = 0;
1367             s.index_entries = g_new0 (MXFIndexEntry, max_segment_size);
1368             g_array_append_val (mux->index_table, s);
1369           }
1370         }
1371       } else {
1372         while (pts_segment_pos + index_pos_diff <= 0) {
1373           if (pts_index_pos == 0) {
1374             pts_index_pos = G_MAXUINT64;
1375             break;
1376           }
1377           index_pos_diff += pts_segment_pos;
1378           pts_segment_pos = max_segment_size;
1379           pts_index_pos--;
1380         }
1381       }
1382       if (pts_index_pos != G_MAXUINT64) {
1383         g_assert (index_pos_diff < 127 && index_pos_diff >= -127);
1384         pts_segment =
1385             &g_array_index (mux->index_table, MXFIndexTableSegment,
1386             pts_index_pos);
1387         pts_segment->index_entries[pts_segment_pos +
1388             index_pos_diff].temporal_offset = -index_pos_diff;
1389       }
1390     }
1391
1392     /* Leave temporal offset initialized at 0, above code will set it as necessary */
1393     ;
1394     if (is_keyframe)
1395       mux->last_keyframe_pos = pad->pos;
1396     segment->index_entries[segment->n_index_entries].key_frame_offset =
1397         MIN (pad->pos - mux->last_keyframe_pos, 127);
1398     segment->index_entries[segment->n_index_entries].flags = is_keyframe ? 0x80 : 0x20; /* FIXME: Need to distinguish all the cases */
1399     segment->index_entries[segment->n_index_entries].stream_offset =
1400         mux->partition.body_offset;
1401
1402     segment->n_index_entries++;
1403     segment->index_duration++;
1404   }
1405
1406   buf_size = gst_buffer_get_size (buf);
1407   slen = mxf_ber_encode_size (buf_size, ber);
1408   outbuf = gst_buffer_new_and_alloc (16 + slen);
1409   gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
1410   memcpy (map.data, _gc_essence_element_ul, 16);
1411   GST_WRITE_UINT32_BE (map.data + 12, pad->source_track->parent.track_number);
1412   memcpy (map.data + 16, ber, slen);
1413   gst_buffer_unmap (outbuf, &map);
1414   outbuf = gst_buffer_append (outbuf, buf);
1415
1416   GST_DEBUG_OBJECT (pad,
1417       "Pushing buffer of size %" G_GSIZE_FORMAT " for track %u",
1418       gst_buffer_get_size (outbuf), pad->source_track->parent.track_id);
1419
1420   mux->partition.body_offset += gst_buffer_get_size (outbuf);
1421   if ((ret = gst_mxf_mux_push (mux, outbuf)) != GST_FLOW_OK) {
1422     GST_ERROR_OBJECT (pad,
1423         "Failed pushing buffer for track %u, reason %s",
1424         pad->source_track->parent.track_id, gst_flow_get_name (ret));
1425     return ret;
1426   }
1427
1428   pad->pos++;
1429   pad->last_timestamp =
1430       gst_util_uint64_scale (GST_SECOND * pad->pos,
1431       pad->source_track->edit_rate.d, pad->source_track->edit_rate.n);
1432
1433   return ret;
1434 }
1435
1436 static GstFlowReturn
1437 gst_mxf_mux_write_body_partition (GstMXFMux * mux)
1438 {
1439   GstBuffer *buf;
1440
1441   mux->partition.type = MXF_PARTITION_PACK_BODY;
1442   mux->partition.closed = TRUE;
1443   mux->partition.complete = TRUE;
1444   mux->partition.this_partition = mux->offset;
1445   mux->partition.prev_partition = 0;
1446   mux->partition.footer_partition = 0;
1447   mux->partition.header_byte_count = 0;
1448   mux->partition.index_byte_count = 0;
1449   mux->partition.index_sid = 0;
1450   mux->partition.body_offset = 0;
1451   mux->partition.body_sid =
1452       mux->preface->content_storage->essence_container_data[0]->body_sid;
1453
1454   buf = mxf_partition_pack_to_buffer (&mux->partition);
1455   return gst_mxf_mux_push (mux, buf);
1456 }
1457
1458 static GstFlowReturn
1459 gst_mxf_mux_handle_eos (GstMXFMux * mux)
1460 {
1461   GList *l;
1462   gboolean have_data = FALSE;
1463   GstBuffer *packet;
1464
1465   do {
1466     GstMXFMuxPad *best = NULL;
1467
1468     have_data = FALSE;
1469
1470     GST_OBJECT_LOCK (mux);
1471     for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
1472       GstMXFMuxPad *pad = l->data;
1473       GstBuffer *buffer =
1474           gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
1475
1476       GstClockTime next_gc_timestamp =
1477           gst_util_uint64_scale ((mux->last_gc_position + 1) * GST_SECOND,
1478           mux->min_edit_rate.d, mux->min_edit_rate.n);
1479
1480       if (pad->have_complete_edit_unit ||
1481           gst_adapter_available (pad->adapter) > 0 || buffer) {
1482         have_data = TRUE;
1483         if (pad->last_timestamp < next_gc_timestamp) {
1484           best = gst_object_ref (pad);
1485           if (buffer)
1486             gst_buffer_unref (buffer);
1487           break;
1488         }
1489       }
1490       if (buffer)
1491         gst_buffer_unref (buffer);
1492
1493       if (have_data && !l->next) {
1494         mux->last_gc_position++;
1495         mux->last_gc_timestamp = next_gc_timestamp;
1496         break;
1497       }
1498     }
1499     GST_OBJECT_UNLOCK (mux);
1500
1501     if (best) {
1502       gst_mxf_mux_handle_buffer (mux, best);
1503       gst_object_unref (best);
1504       have_data = TRUE;
1505     }
1506   } while (have_data);
1507
1508   mux->last_gc_position++;
1509   mux->last_gc_timestamp =
1510       gst_util_uint64_scale (mux->last_gc_position * GST_SECOND,
1511       mux->min_edit_rate.d, mux->min_edit_rate.n);
1512
1513   /* Update essence track durations */
1514   GST_OBJECT_LOCK (mux);
1515   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
1516     GstMXFMuxPad *pad = l->data;
1517     guint i;
1518
1519     /* Update durations */
1520     pad->source_track->parent.sequence->duration = pad->pos;
1521     MXF_METADATA_SOURCE_CLIP (pad->source_track->parent.
1522         sequence->structural_components[0])->parent.duration = pad->pos;
1523     for (i = 0; i < mux->preface->content_storage->packages[0]->n_tracks; i++) {
1524       MXFMetadataTimelineTrack *track;
1525
1526       if (!MXF_IS_METADATA_TIMELINE_TRACK (mux->preface->
1527               content_storage->packages[0]->tracks[i])
1528           || !MXF_IS_METADATA_SOURCE_CLIP (mux->preface->
1529               content_storage->packages[0]->tracks[i]->sequence->
1530               structural_components[0]))
1531         continue;
1532
1533       track =
1534           MXF_METADATA_TIMELINE_TRACK (mux->preface->
1535           content_storage->packages[0]->tracks[i]);
1536       if (MXF_METADATA_SOURCE_CLIP (track->parent.
1537               sequence->structural_components[0])->source_track_id ==
1538           pad->source_track->parent.track_id) {
1539         track->parent.sequence->structural_components[0]->duration = pad->pos;
1540         track->parent.sequence->duration = pad->pos;
1541       }
1542     }
1543   }
1544   GST_OBJECT_UNLOCK (mux);
1545
1546   /* Update timecode track duration */
1547   {
1548     MXFMetadataTimelineTrack *track =
1549         MXF_METADATA_TIMELINE_TRACK (mux->preface->
1550         content_storage->packages[0]->tracks[0]);
1551     MXFMetadataSequence *sequence = track->parent.sequence;
1552     MXFMetadataTimecodeComponent *component =
1553         MXF_METADATA_TIMECODE_COMPONENT (sequence->structural_components[0]);
1554
1555     sequence->duration = mux->last_gc_position;
1556     component->parent.duration = mux->last_gc_position;
1557   }
1558
1559   {
1560     MXFMetadataTimelineTrack *track =
1561         MXF_METADATA_TIMELINE_TRACK (mux->preface->
1562         content_storage->packages[1]->tracks[0]);
1563     MXFMetadataSequence *sequence = track->parent.sequence;
1564     MXFMetadataTimecodeComponent *component =
1565         MXF_METADATA_TIMECODE_COMPONENT (sequence->structural_components[0]);
1566
1567     sequence->duration = mux->last_gc_position;
1568     component->parent.duration = mux->last_gc_position;
1569   }
1570
1571   {
1572     guint64 body_partition = mux->partition.this_partition;
1573     guint32 body_sid = mux->partition.body_sid;
1574     guint64 footer_partition = mux->offset;
1575     GArray *rip;
1576     GstFlowReturn ret;
1577     GstSegment segment;
1578     MXFRandomIndexPackEntry entry;
1579     GList *index_entries = NULL, *l;
1580     guint index_byte_count = 0;
1581     guint i;
1582     GstBuffer *buf;
1583
1584     for (i = 0; i < mux->index_table->len; i++) {
1585       MXFIndexTableSegment *segment =
1586           &g_array_index (mux->index_table, MXFIndexTableSegment, i);
1587       GstBuffer *segment_buffer = mxf_index_table_segment_to_buffer (segment);
1588
1589       index_byte_count += gst_buffer_get_size (segment_buffer);
1590       index_entries = g_list_prepend (index_entries, segment_buffer);
1591     }
1592
1593     mux->partition.type = MXF_PARTITION_PACK_FOOTER;
1594     mux->partition.closed = TRUE;
1595     mux->partition.complete = TRUE;
1596     mux->partition.this_partition = mux->offset;
1597     mux->partition.prev_partition = body_partition;
1598     mux->partition.footer_partition = mux->offset;
1599     mux->partition.header_byte_count = 0;
1600     mux->partition.index_byte_count = index_byte_count;
1601     mux->partition.index_sid =
1602         mux->preface->content_storage->essence_container_data[0]->index_sid;
1603     mux->partition.body_offset = 0;
1604     mux->partition.body_sid = 0;
1605
1606     gst_mxf_mux_write_header_metadata (mux);
1607
1608     index_entries = g_list_reverse (index_entries);
1609     for (l = index_entries; l; l = l->next) {
1610       if ((ret = gst_mxf_mux_push (mux, l->data)) != GST_FLOW_OK) {
1611         GST_ERROR_OBJECT (mux, "Failed pushing index table segment");
1612       }
1613     }
1614     g_list_free (index_entries);
1615
1616     rip = g_array_sized_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry), 3);
1617     entry.offset = 0;
1618     entry.body_sid = 0;
1619     g_array_append_val (rip, entry);
1620     entry.offset = body_partition;
1621     entry.body_sid = body_sid;
1622     g_array_append_val (rip, entry);
1623     entry.offset = footer_partition;
1624     entry.body_sid = 0;
1625     g_array_append_val (rip, entry);
1626
1627     packet = mxf_random_index_pack_to_buffer (rip);
1628     if ((ret = gst_mxf_mux_push (mux, packet)) != GST_FLOW_OK) {
1629       GST_ERROR_OBJECT (mux, "Failed pushing random index pack");
1630     }
1631     g_array_free (rip, TRUE);
1632
1633     /* Rewrite header partition with updated values */
1634     gst_segment_init (&segment, GST_FORMAT_BYTES);
1635     if (gst_pad_push_event (GST_AGGREGATOR_SRC_PAD (mux),
1636             gst_event_new_segment (&segment))) {
1637       mux->offset = 0;
1638       mux->partition.type = MXF_PARTITION_PACK_HEADER;
1639       mux->partition.closed = TRUE;
1640       mux->partition.complete = TRUE;
1641       mux->partition.this_partition = 0;
1642       mux->partition.prev_partition = 0;
1643       mux->partition.footer_partition = footer_partition;
1644       mux->partition.header_byte_count = 0;
1645       mux->partition.index_byte_count = 0;
1646       mux->partition.index_sid = 0;
1647       mux->partition.body_offset = 0;
1648       mux->partition.body_sid = 0;
1649
1650       ret = gst_mxf_mux_write_header_metadata (mux);
1651       if (ret != GST_FLOW_OK) {
1652         GST_ERROR_OBJECT (mux, "Rewriting header partition failed");
1653         return ret;
1654       }
1655
1656       g_assert (mux->offset == body_partition);
1657
1658       mux->partition.type = MXF_PARTITION_PACK_BODY;
1659       mux->partition.closed = TRUE;
1660       mux->partition.complete = TRUE;
1661       mux->partition.this_partition = mux->offset;
1662       mux->partition.prev_partition = 0;
1663       mux->partition.footer_partition = footer_partition;
1664       mux->partition.header_byte_count = 0;
1665       mux->partition.index_byte_count = 0;
1666       mux->partition.index_sid = 0;
1667       mux->partition.body_offset = 0;
1668       mux->partition.body_sid =
1669           mux->preface->content_storage->essence_container_data[0]->body_sid;
1670
1671       buf = mxf_partition_pack_to_buffer (&mux->partition);
1672       ret = gst_mxf_mux_push (mux, buf);
1673       if (ret != GST_FLOW_OK) {
1674         GST_ERROR_OBJECT (mux, "Rewriting body partition failed");
1675         return ret;
1676       }
1677     } else {
1678       GST_WARNING_OBJECT (mux, "Can't rewrite header partition");
1679     }
1680   }
1681
1682   return GST_FLOW_OK;
1683 }
1684
1685 static gint
1686 _sort_mux_pads (gconstpointer a, gconstpointer b)
1687 {
1688   const GstMXFMuxPad *pa = a, *pb = b;
1689   MXFMetadataTrackType ta =
1690       mxf_metadata_track_identifier_parse (&pa->writer->data_definition);
1691   MXFMetadataTrackType tb =
1692       mxf_metadata_track_identifier_parse (&pb->writer->data_definition);
1693
1694   if (ta != tb)
1695     return ta - tb;
1696
1697   return pa->source_track->parent.track_number -
1698       pa->source_track->parent.track_number;
1699 }
1700
1701
1702 static gboolean
1703 gst_mxf_mux_stop (GstAggregator * aggregator)
1704 {
1705   GstMXFMux *mux = GST_MXF_MUX (aggregator);
1706
1707   gst_mxf_mux_reset (mux);
1708
1709   return TRUE;
1710 }
1711
1712 static GstFlowReturn
1713 gst_mxf_mux_aggregate (GstAggregator * aggregator, gboolean timeout)
1714 {
1715   GstMXFMux *mux = GST_MXF_MUX (aggregator);
1716   GstMXFMuxPad *best = NULL;
1717   GstFlowReturn ret;
1718   GList *l;
1719   gboolean eos = TRUE;
1720
1721   if (timeout) {
1722     GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1723         ("Live mixing and got a timeout. This is not supported yet"));
1724     ret = GST_FLOW_ERROR;
1725     goto error;
1726   }
1727
1728   if (mux->state == GST_MXF_MUX_STATE_ERROR) {
1729     GST_ERROR_OBJECT (mux, "Had an error before -- returning");
1730     return GST_FLOW_ERROR;
1731   } else if (mux->state == GST_MXF_MUX_STATE_EOS) {
1732     GST_WARNING_OBJECT (mux, "EOS");
1733     return GST_FLOW_EOS;
1734   }
1735
1736   if (mux->state == GST_MXF_MUX_STATE_HEADER) {
1737     GstCaps *caps;
1738
1739     if (GST_ELEMENT_CAST (mux)->sinkpads == NULL) {
1740       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1741           ("No input streams configured"));
1742       ret = GST_FLOW_ERROR;
1743       goto error;
1744     }
1745
1746     caps = gst_caps_new_empty_simple ("application/mxf");
1747     gst_aggregator_set_src_caps (GST_AGGREGATOR (mux), caps);
1748     gst_caps_unref (caps);
1749
1750     if ((ret = gst_mxf_mux_create_metadata (mux)) != GST_FLOW_OK)
1751       goto error;
1752
1753     if ((ret = gst_mxf_mux_init_partition_pack (mux)) != GST_FLOW_OK)
1754       goto error;
1755
1756     if ((ret = gst_mxf_mux_write_header_metadata (mux)) != GST_FLOW_OK)
1757       goto error;
1758
1759     /* Sort pads, we will always write in that order */
1760     GST_OBJECT_LOCK (mux);
1761     GST_ELEMENT_CAST (mux)->sinkpads =
1762         g_list_sort (GST_ELEMENT_CAST (mux)->sinkpads, _sort_mux_pads);
1763     GST_OBJECT_UNLOCK (mux);
1764
1765     /* Write body partition */
1766     ret = gst_mxf_mux_write_body_partition (mux);
1767     if (ret != GST_FLOW_OK)
1768       goto error;
1769     mux->state = GST_MXF_MUX_STATE_DATA;
1770   }
1771
1772   g_return_val_if_fail (g_hash_table_size (mux->metadata) > 0, GST_FLOW_ERROR);
1773
1774   do {
1775     GST_OBJECT_LOCK (mux);
1776     for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
1777       gboolean pad_eos;
1778       GstMXFMuxPad *pad = l->data;
1779       GstBuffer *buffer;
1780       GstClockTime next_gc_timestamp =
1781           gst_util_uint64_scale ((mux->last_gc_position + 1) * GST_SECOND,
1782           mux->min_edit_rate.d, mux->min_edit_rate.n);
1783
1784       pad_eos = gst_aggregator_pad_is_eos (GST_AGGREGATOR_PAD (pad));
1785       if (!pad_eos)
1786         eos = FALSE;
1787
1788       buffer = gst_aggregator_pad_peek_buffer (GST_AGGREGATOR_PAD (pad));
1789
1790       if ((!pad_eos || pad->have_complete_edit_unit ||
1791               gst_adapter_available (pad->adapter) > 0 || buffer)
1792           && pad->last_timestamp < next_gc_timestamp) {
1793         if (buffer)
1794           gst_buffer_unref (buffer);
1795         best = gst_object_ref (pad);
1796         break;
1797       } else if (!eos && !l->next) {
1798         mux->last_gc_position++;
1799         mux->last_gc_timestamp = next_gc_timestamp;
1800         eos = FALSE;
1801         if (buffer)
1802           gst_buffer_unref (buffer);
1803         best = NULL;
1804         break;
1805       }
1806       if (buffer)
1807         gst_buffer_unref (buffer);
1808     }
1809     GST_OBJECT_UNLOCK (mux);
1810   } while (!eos && best == NULL);
1811
1812   if (!eos && best) {
1813     ret = gst_mxf_mux_handle_buffer (mux, best);
1814     gst_object_unref (best);
1815     if (ret != GST_FLOW_OK)
1816       goto error;
1817   } else if (eos) {
1818     GST_DEBUG_OBJECT (mux, "Handling EOS");
1819
1820     if (best)
1821       gst_object_unref (best);
1822
1823     gst_mxf_mux_handle_eos (mux);
1824     mux->state = GST_MXF_MUX_STATE_EOS;
1825     return GST_FLOW_EOS;
1826   } else {
1827     g_assert_not_reached ();
1828   }
1829
1830   return GST_FLOW_OK;
1831
1832 error:
1833   {
1834     mux->state = GST_MXF_MUX_STATE_ERROR;
1835     return ret;
1836   }
1837 }