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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <gst/gst.h>
25 #include <string.h>
26 
27 #include "mxftypes.h"
28 #include "mxfmetadata.h"
29 #include "mxfquark.h"
30 
31 GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
32 #define GST_CAT_DEFAULT mxf_debug
33 
34 G_DEFINE_ABSTRACT_TYPE (MXFMetadataBase, mxf_metadata_base, G_TYPE_OBJECT);
35 
36 static void
mxf_metadata_base_finalize(GObject * object)37 mxf_metadata_base_finalize (GObject * object)
38 {
39   MXFMetadataBase *self = MXF_METADATA_BASE (object);
40 
41   if (self->other_tags) {
42     g_hash_table_destroy (self->other_tags);
43     self->other_tags = NULL;
44   }
45 
46   G_OBJECT_CLASS (mxf_metadata_base_parent_class)->finalize (object);
47 }
48 
49 static gboolean
mxf_metadata_base_handle_tag(MXFMetadataBase * self,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)50 mxf_metadata_base_handle_tag (MXFMetadataBase * self, MXFPrimerPack * primer,
51     guint16 tag, const guint8 * tag_data, guint tag_size)
52 {
53   return (mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size,
54           &self->other_tags));
55 }
56 
57 static gboolean
mxf_metadata_base_resolve_default(MXFMetadataBase * self,GHashTable * metadata)58 mxf_metadata_base_resolve_default (MXFMetadataBase * self,
59     GHashTable * metadata)
60 {
61   return TRUE;
62 }
63 
64 static GstStructure *
mxf_metadata_base_to_structure_default(MXFMetadataBase * self)65 mxf_metadata_base_to_structure_default (MXFMetadataBase * self)
66 {
67   MXFMetadataBaseClass *klass = MXF_METADATA_BASE_GET_CLASS (self);
68   GstStructure *ret;
69   gchar str[48];
70 
71   g_return_val_if_fail (klass->name_quark != 0, NULL);
72 
73   ret = gst_structure_new_id_empty (klass->name_quark);
74 
75   if (!mxf_uuid_is_zero (&self->instance_uid)) {
76     mxf_uuid_to_string (&self->instance_uid, str);
77     gst_structure_id_set (ret, MXF_QUARK (INSTANCE_UID), G_TYPE_STRING, str,
78         NULL);
79   }
80 
81   if (!mxf_uuid_is_zero (&self->generation_uid)) {
82     mxf_uuid_to_string (&self->generation_uid, str);
83     gst_structure_id_set (ret, MXF_QUARK (GENERATION_UID), G_TYPE_STRING, str,
84         NULL);
85   }
86 
87   if (self->other_tags) {
88     MXFLocalTag *tag;
89     GValue va = { 0, };
90     GValue v = { 0, };
91     GstStructure *s;
92     GstBuffer *buf;
93     GstMapInfo map;
94     GHashTableIter iter;
95 
96     g_hash_table_iter_init (&iter, self->other_tags);
97     g_value_init (&va, GST_TYPE_ARRAY);
98 
99     while (g_hash_table_iter_next (&iter, NULL, (gpointer) & tag)) {
100       g_value_init (&v, GST_TYPE_STRUCTURE);
101       s = gst_structure_new_id_empty (MXF_QUARK (TAG));
102 
103       mxf_ul_to_string (&tag->ul, str);
104 
105       buf = gst_buffer_new_and_alloc (tag->size);
106       gst_buffer_map (buf, &map, GST_MAP_WRITE);
107       memcpy (map.data, tag->data, tag->size);
108       gst_buffer_unmap (buf, &map);
109 
110       gst_structure_id_set (s, MXF_QUARK (NAME), G_TYPE_STRING, str,
111           MXF_QUARK (DATA), GST_TYPE_BUFFER, buf, NULL);
112 
113       gst_value_set_structure (&v, s);
114       gst_structure_free (s);
115       gst_buffer_unref (buf);
116       gst_value_array_append_value (&va, &v);
117       g_value_unset (&v);
118     }
119 
120     gst_structure_id_set_value (ret, MXF_QUARK (OTHER_TAGS), &va);
121     g_value_unset (&va);
122   }
123 
124   return ret;
125 }
126 
127 static void
mxf_metadata_base_init(MXFMetadataBase * self)128 mxf_metadata_base_init (MXFMetadataBase * self)
129 {
130 
131 }
132 
133 static void
mxf_metadata_base_class_init(MXFMetadataBaseClass * klass)134 mxf_metadata_base_class_init (MXFMetadataBaseClass * klass)
135 {
136   GObjectClass *object_class = (GObjectClass *) klass;
137 
138   object_class->finalize = mxf_metadata_base_finalize;
139   klass->handle_tag = mxf_metadata_base_handle_tag;
140   klass->resolve = mxf_metadata_base_resolve_default;
141   klass->to_structure = mxf_metadata_base_to_structure_default;
142 }
143 
144 gboolean
mxf_metadata_base_parse(MXFMetadataBase * self,MXFPrimerPack * primer,const guint8 * data,guint size)145 mxf_metadata_base_parse (MXFMetadataBase * self, MXFPrimerPack * primer,
146     const guint8 * data, guint size)
147 {
148   guint16 tag, tag_size;
149   const guint8 *tag_data;
150 
151   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), FALSE);
152   g_return_val_if_fail (primer != NULL, FALSE);
153 
154   if (size == 0)
155     return FALSE;
156 
157   g_return_val_if_fail (data != NULL, FALSE);
158 
159   while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
160     if (tag_size == 0 || tag == 0x0000)
161       goto next;
162 
163     if (!MXF_METADATA_BASE_GET_CLASS (self)->handle_tag (self, primer, tag,
164             tag_data, tag_size))
165       return FALSE;
166   next:
167     data += 4 + tag_size;
168     size -= 4 + tag_size;
169   }
170 
171   return TRUE;
172 }
173 
174 gboolean
mxf_metadata_base_resolve(MXFMetadataBase * self,GHashTable * metadata)175 mxf_metadata_base_resolve (MXFMetadataBase * self, GHashTable * metadata)
176 {
177   MXFMetadataBaseClass *klass;
178   gboolean ret = TRUE;
179 
180   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), FALSE);
181   g_return_val_if_fail (metadata != NULL, FALSE);
182 
183   if (self->resolved == MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS)
184     return TRUE;
185   else if (self->resolved != MXF_METADATA_BASE_RESOLVE_STATE_NONE)
186     return FALSE;
187 
188   self->resolved = MXF_METADATA_BASE_RESOLVE_STATE_RUNNING;
189 
190   klass = MXF_METADATA_BASE_GET_CLASS (self);
191 
192   if (klass->resolve)
193     ret = klass->resolve (self, metadata);
194 
195   self->resolved =
196       (ret) ? MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS :
197       MXF_METADATA_BASE_RESOLVE_STATE_FAILURE;
198 
199   return ret;
200 }
201 
202 GstStructure *
mxf_metadata_base_to_structure(MXFMetadataBase * self)203 mxf_metadata_base_to_structure (MXFMetadataBase * self)
204 {
205   MXFMetadataBaseClass *klass;
206 
207   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), NULL);
208 
209   g_return_val_if_fail (self->resolved ==
210       MXF_METADATA_BASE_RESOLVE_STATE_SUCCESS, NULL);
211 
212   klass = MXF_METADATA_BASE_GET_CLASS (self);
213 
214   if (klass->to_structure)
215     return klass->to_structure (self);
216 
217   return NULL;
218 }
219 
220 GstBuffer *
mxf_metadata_base_to_buffer(MXFMetadataBase * self,MXFPrimerPack * primer)221 mxf_metadata_base_to_buffer (MXFMetadataBase * self, MXFPrimerPack * primer)
222 {
223   MXFMetadataBaseClass *klass;
224   GstBuffer *ret;
225   GstMapInfo map;
226   GList *tags, *l;
227   guint size = 0, slen;
228   guint8 ber[9];
229   MXFLocalTag *t, *last;
230   guint8 *data;
231 
232   g_return_val_if_fail (MXF_IS_METADATA_BASE (self), NULL);
233   g_return_val_if_fail (primer != NULL, NULL);
234 
235   klass = MXF_METADATA_BASE_GET_CLASS (self);
236   g_return_val_if_fail (klass->write_tags, NULL);
237 
238   tags = klass->write_tags (self, primer);
239   g_return_val_if_fail (tags != NULL, NULL);
240 
241   /* Add unknown tags */
242   if (self->other_tags) {
243     MXFLocalTag *tmp;
244     GHashTableIter iter;
245 
246     g_hash_table_iter_init (&iter, self->other_tags);
247 
248     while (g_hash_table_iter_next (&iter, NULL, (gpointer) & t)) {
249       tmp = g_slice_dup (MXFLocalTag, t);
250       if (t->g_slice) {
251         tmp->data = g_slice_alloc (t->size);
252         mxf_primer_pack_add_mapping (primer, 0x0000, &t->ul);
253         memcpy (tmp->data, t->data, t->size);
254       } else {
255         tmp->data = g_memdup (t->data, t->size);
256       }
257       tags = g_list_prepend (tags, tmp);
258     }
259   }
260 
261   l = g_list_last (tags);
262   last = l->data;
263   tags = g_list_delete_link (tags, l);
264   /* Last element contains the metadata UL */
265   g_return_val_if_fail (last->size == 0, NULL);
266 
267   for (l = tags; l; l = l->next) {
268     t = l->data;
269     g_assert (G_MAXUINT - t->size >= size);
270     size += 4 + t->size;
271   }
272 
273   slen = mxf_ber_encode_size (size, ber);
274   size += 16 + slen;
275 
276   ret = gst_buffer_new_and_alloc (size);
277   gst_buffer_map (ret, &map, GST_MAP_WRITE);
278 
279   memcpy (map.data, &last->ul, 16);
280   mxf_local_tag_free (last);
281   last = NULL;
282   memcpy (map.data + 16, ber, slen);
283 
284   data = map.data + 16 + slen;
285   size -= 16 + slen;
286 
287   for (l = tags; l; l = l->next) {
288     guint16 local_tag;
289 
290     g_assert (size >= 4);
291     t = l->data;
292 
293     local_tag =
294         GPOINTER_TO_UINT (g_hash_table_lookup (primer->reverse_mappings,
295             &t->ul));
296     g_assert (local_tag != 0);
297 
298     GST_WRITE_UINT16_BE (data, local_tag);
299     GST_WRITE_UINT16_BE (data + 2, t->size);
300     data += 4;
301     size -= 4;
302     g_assert (size >= t->size);
303 
304     memcpy (data, t->data, t->size);
305     data += t->size;
306     size -= t->size;
307 
308     mxf_local_tag_free (t);
309   }
310 
311   g_list_free (tags);
312 
313   gst_buffer_unmap (ret, &map);
314 
315   return ret;
316 }
317 
318 G_DEFINE_ABSTRACT_TYPE (MXFMetadata, mxf_metadata, MXF_TYPE_METADATA_BASE);
319 
320 static gboolean
mxf_metadata_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)321 mxf_metadata_handle_tag (MXFMetadataBase * metadata, MXFPrimerPack * primer,
322     guint16 tag, const guint8 * tag_data, guint tag_size)
323 {
324 #ifndef GST_DISABLE_GST_DEBUG
325   gchar str[48];
326 #endif
327   MXFMetadata *self = MXF_METADATA (metadata);
328   gboolean ret = TRUE;
329 
330   switch (tag) {
331     case 0x3c0a:
332       if (tag_size != 16)
333         goto error;
334       memcpy (&self->parent.instance_uid, tag_data, 16);
335       GST_DEBUG ("  instance uid = %s",
336           mxf_uuid_to_string (&self->parent.instance_uid, str));
337       break;
338     case 0x0102:
339       if (tag_size != 16)
340         goto error;
341       memcpy (&self->parent.generation_uid, tag_data, 16);
342       GST_DEBUG ("  generation uid = %s",
343           mxf_uuid_to_string (&self->parent.generation_uid, str));
344       break;
345     default:
346       ret =
347           MXF_METADATA_BASE_CLASS (mxf_metadata_parent_class)->handle_tag
348           (metadata, primer, tag, tag_data, tag_size);
349       break;
350   }
351 
352   return ret;
353 
354 error:
355 
356   GST_ERROR ("Invalid metadata local tag 0x%04x of size %u", tag, tag_size);
357 
358   return FALSE;
359 }
360 
361 static GList *
mxf_metadata_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)362 mxf_metadata_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
363 {
364   MXFMetadata *self = MXF_METADATA (m);
365   GList *ret = NULL;
366   MXFLocalTag *t;
367   MXFMetadataClass *klass;
368 
369   g_return_val_if_fail (MXF_IS_METADATA (self), NULL);
370   klass = MXF_METADATA_GET_CLASS (self);
371 
372   /* Last element contains the metadata key */
373   t = g_slice_new0 (MXFLocalTag);
374   memcpy (&t->ul, MXF_UL (METADATA), 16);
375   GST_WRITE_UINT16_BE (&t->ul.u[13], klass->type);
376   ret = g_list_prepend (ret, t);
377 
378   t = g_slice_new0 (MXFLocalTag);
379   memcpy (&t->ul, MXF_UL (INSTANCE_UID), 16);
380   t->size = 16;
381   t->data = g_slice_alloc (16);
382   t->g_slice = TRUE;
383   memcpy (t->data, &self->parent.instance_uid, 16);
384   mxf_primer_pack_add_mapping (primer, 0x3c0a, &t->ul);
385   ret = g_list_prepend (ret, t);
386 
387   if (!mxf_uuid_is_zero (&self->parent.generation_uid)) {
388     t = g_slice_new0 (MXFLocalTag);
389     memcpy (&t->ul, MXF_UL (GENERATION_UID), 16);
390     t->size = 16;
391     t->data = g_slice_alloc (16);
392     t->g_slice = TRUE;
393     memcpy (t->data, &self->parent.generation_uid, 16);
394     mxf_primer_pack_add_mapping (primer, 0x0102, &t->ul);
395     ret = g_list_prepend (ret, t);
396   }
397 
398   return ret;
399 }
400 
401 static void
mxf_metadata_class_init(MXFMetadataClass * klass)402 mxf_metadata_class_init (MXFMetadataClass * klass)
403 {
404   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
405 
406   metadata_base_class->handle_tag = mxf_metadata_handle_tag;
407   metadata_base_class->write_tags = mxf_metadata_write_tags;
408 }
409 
410 static void
mxf_metadata_init(MXFMetadata * self)411 mxf_metadata_init (MXFMetadata * self)
412 {
413 }
414 
415 static GArray *_mxf_metadata_registry = NULL;
416 
417 #define _add_metadata_type(type) G_STMT_START { \
418   GType t = type; \
419   \
420   g_array_append_val (_mxf_metadata_registry, t); \
421 } G_STMT_END
422 
423 void
mxf_metadata_init_types(void)424 mxf_metadata_init_types (void)
425 {
426   g_return_if_fail (_mxf_metadata_registry == NULL);
427 
428   _mxf_metadata_registry = g_array_new (FALSE, TRUE, sizeof (GType));
429 
430   _add_metadata_type (MXF_TYPE_METADATA_PREFACE);
431   _add_metadata_type (MXF_TYPE_METADATA_IDENTIFICATION);
432   _add_metadata_type (MXF_TYPE_METADATA_CONTENT_STORAGE);
433   _add_metadata_type (MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA);
434   _add_metadata_type (MXF_TYPE_METADATA_MATERIAL_PACKAGE);
435   _add_metadata_type (MXF_TYPE_METADATA_SOURCE_PACKAGE);
436   _add_metadata_type (MXF_TYPE_METADATA_TIMELINE_TRACK);
437   _add_metadata_type (MXF_TYPE_METADATA_EVENT_TRACK);
438   _add_metadata_type (MXF_TYPE_METADATA_STATIC_TRACK);
439   _add_metadata_type (MXF_TYPE_METADATA_SEQUENCE);
440   _add_metadata_type (MXF_TYPE_METADATA_SOURCE_CLIP);
441   _add_metadata_type (MXF_TYPE_METADATA_FILLER);
442   _add_metadata_type (MXF_TYPE_METADATA_TIMECODE_COMPONENT);
443   _add_metadata_type (MXF_TYPE_METADATA_DM_SEGMENT);
444   _add_metadata_type (MXF_TYPE_METADATA_DM_SOURCE_CLIP);
445   _add_metadata_type (MXF_TYPE_METADATA_FILE_DESCRIPTOR);
446   _add_metadata_type (MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
447   _add_metadata_type (MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR);
448   _add_metadata_type (MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR);
449   _add_metadata_type (MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR);
450   _add_metadata_type (MXF_TYPE_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR);
451   _add_metadata_type (MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR);
452   _add_metadata_type (MXF_TYPE_METADATA_NETWORK_LOCATOR);
453   _add_metadata_type (MXF_TYPE_METADATA_TEXT_LOCATOR);
454 }
455 
456 #undef _add_metadata_type
457 
458 void
mxf_metadata_register(GType type)459 mxf_metadata_register (GType type)
460 {
461   g_return_if_fail (g_type_is_a (type, MXF_TYPE_METADATA));
462 
463   g_array_append_val (_mxf_metadata_registry, type);
464 }
465 
466 MXFMetadata *
mxf_metadata_new(guint16 type,MXFPrimerPack * primer,guint64 offset,const guint8 * data,guint size)467 mxf_metadata_new (guint16 type, MXFPrimerPack * primer, guint64 offset,
468     const guint8 * data, guint size)
469 {
470   guint i;
471   GType t = G_TYPE_INVALID;
472   MXFMetadata *ret = NULL;
473 
474   g_return_val_if_fail (type != 0, NULL);
475   g_return_val_if_fail (primer != NULL, NULL);
476   g_return_val_if_fail (_mxf_metadata_registry != NULL, NULL);
477 
478   for (i = 0; i < _mxf_metadata_registry->len; i++) {
479     GType tmp = g_array_index (_mxf_metadata_registry, GType, i);
480     MXFMetadataClass *klass = MXF_METADATA_CLASS (g_type_class_ref (tmp));
481 
482     if (klass->type == type) {
483       g_type_class_unref (klass);
484       t = tmp;
485       break;
486     }
487     g_type_class_unref (klass);
488   }
489 
490   if (t == G_TYPE_INVALID) {
491     GST_WARNING
492         ("No handler for type 0x%04x found -- using generic metadata parser",
493         type);
494     return NULL;
495   }
496 
497 
498   GST_DEBUG ("Metadata type 0x%04x is handled by type %s", type,
499       g_type_name (t));
500 
501   ret = (MXFMetadata *) g_type_create_instance (t);
502   if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
503     GST_ERROR ("Parsing metadata failed");
504     g_object_unref (ret);
505     return NULL;
506   }
507 
508   ret->parent.offset = offset;
509   return ret;
510 }
511 
512 G_DEFINE_TYPE (MXFMetadataPreface, mxf_metadata_preface, MXF_TYPE_METADATA);
513 
514 static void
mxf_metadata_preface_finalize(GObject * object)515 mxf_metadata_preface_finalize (GObject * object)
516 {
517   MXFMetadataPreface *self = MXF_METADATA_PREFACE (object);
518 
519   g_free (self->identifications_uids);
520   self->identifications_uids = NULL;
521 
522   g_free (self->identifications);
523   self->identifications = NULL;
524 
525   g_free (self->essence_containers);
526   self->essence_containers = NULL;
527 
528   g_free (self->dm_schemes);
529   self->dm_schemes = NULL;
530 
531   G_OBJECT_CLASS (mxf_metadata_preface_parent_class)->finalize (object);
532 }
533 
534 static gboolean
mxf_metadata_preface_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)535 mxf_metadata_preface_handle_tag (MXFMetadataBase * metadata,
536     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
537     guint tag_size)
538 {
539   MXFMetadataPreface *self = MXF_METADATA_PREFACE (metadata);
540 #ifndef GST_DISABLE_GST_DEBUG
541   gchar str[48];
542 #endif
543   gboolean ret = TRUE;
544 
545   switch (tag) {
546     case 0x3b02:
547       if (!mxf_timestamp_parse (&self->last_modified_date, tag_data, tag_size))
548         goto error;
549       GST_DEBUG ("  last modified date = %s",
550           mxf_timestamp_to_string (&self->last_modified_date, str));
551       break;
552     case 0x3b05:
553       if (tag_size != 2)
554         goto error;
555       self->version = GST_READ_UINT16_BE (tag_data);
556       GST_DEBUG ("  version = %u.%u", (self->version >> 8),
557           (self->version & 0x0f));
558       break;
559     case 0x3b07:
560       if (tag_size != 4)
561         goto error;
562       self->object_model_version = GST_READ_UINT32_BE (tag_data);
563       GST_DEBUG ("  object model version = %u", self->object_model_version);
564       break;
565     case 0x3b08:
566       if (tag_size != 16)
567         goto error;
568       memcpy (&self->primary_package_uid, tag_data, 16);
569       GST_DEBUG ("  primary package = %s",
570           mxf_uuid_to_string (&self->primary_package_uid, str));
571       break;
572     case 0x3b06:
573       if (!mxf_uuid_array_parse (&self->identifications_uids,
574               &self->n_identifications, tag_data, tag_size))
575         goto error;
576 
577       GST_DEBUG ("  number of identifications = %u", self->n_identifications);
578 #ifndef GST_DISABLE_GST_DEBUG
579       {
580         guint i;
581         for (i = 0; i < self->n_identifications; i++) {
582           GST_DEBUG ("  identification %u = %s", i,
583               mxf_uuid_to_string (&self->identifications_uids[i], str));
584         }
585       }
586 #endif
587       break;
588     case 0x3b03:
589       if (tag_size != 16)
590         goto error;
591       memcpy (&self->content_storage_uid, tag_data, 16);
592       GST_DEBUG ("  content storage = %s",
593           mxf_uuid_to_string (&self->content_storage_uid, str));
594       break;
595     case 0x3b09:
596       if (tag_size != 16)
597         goto error;
598       memcpy (&self->operational_pattern, tag_data, 16);
599       GST_DEBUG ("  operational pattern = %s",
600           mxf_ul_to_string (&self->operational_pattern, str));
601       break;
602     case 0x3b0a:
603       if (!mxf_ul_array_parse (&self->essence_containers,
604               &self->n_essence_containers, tag_data, tag_size))
605         goto error;
606 
607       GST_DEBUG ("  number of essence containers = %u",
608           self->n_essence_containers);
609 #ifndef GST_DISABLE_GST_DEBUG
610       {
611         guint i;
612         for (i = 0; i < self->n_essence_containers; i++) {
613           GST_DEBUG ("  essence container %u = %s", i,
614               mxf_ul_to_string (&self->essence_containers[i], str));
615         }
616       }
617 #endif
618       break;
619     case 0x3b0b:
620       if (!mxf_ul_array_parse (&self->dm_schemes, &self->n_dm_schemes, tag_data,
621               tag_size))
622         goto error;
623       GST_DEBUG ("  number of DM schemes = %u", self->n_dm_schemes);
624 
625 #ifndef GST_DISABLE_GST_DEBUG
626       {
627         guint i;
628         for (i = 0; i < self->n_dm_schemes; i++) {
629           GST_DEBUG ("  DM schemes %u = %s", i,
630               mxf_ul_to_string (&self->dm_schemes[i], str));
631         }
632       }
633 #endif
634       break;
635     default:
636       ret =
637           MXF_METADATA_BASE_CLASS
638           (mxf_metadata_preface_parent_class)->handle_tag (metadata, primer,
639           tag, tag_data, tag_size);
640       break;
641   }
642 
643   return ret;
644 
645 error:
646 
647   GST_ERROR ("Invalid preface local tag 0x%04x of size %u", tag, tag_size);
648 
649   return FALSE;
650 }
651 
652 static gboolean
mxf_metadata_preface_resolve(MXFMetadataBase * m,GHashTable * metadata)653 mxf_metadata_preface_resolve (MXFMetadataBase * m, GHashTable * metadata)
654 {
655   MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
656   MXFMetadataBase *current = NULL;
657   guint i;
658 #ifndef GST_DISABLE_GST_DEBUG
659   gchar str[48];
660 #endif
661 
662   if (!mxf_uuid_is_zero (&self->primary_package_uid)) {
663     current = g_hash_table_lookup (metadata, &self->primary_package_uid);
664     if (!current || !MXF_IS_METADATA_GENERIC_PACKAGE (current)) {
665       GST_ERROR ("Primary package %s not found",
666           mxf_uuid_to_string (&self->primary_package_uid, str));
667     } else {
668       if (mxf_metadata_base_resolve (current, metadata)) {
669         self->primary_package = MXF_METADATA_GENERIC_PACKAGE (current);
670       }
671     }
672   }
673   current = NULL;
674 
675   current = g_hash_table_lookup (metadata, &self->content_storage_uid);
676   if (!current || !MXF_IS_METADATA_CONTENT_STORAGE (current)) {
677     GST_ERROR ("Content storage %s not found",
678         mxf_uuid_to_string (&self->content_storage_uid, str));
679     return FALSE;
680   } else {
681     if (mxf_metadata_base_resolve (current, metadata)) {
682       self->content_storage = MXF_METADATA_CONTENT_STORAGE (current);
683     } else {
684       GST_ERROR ("Couldn't resolve content storage %s",
685           mxf_uuid_to_string (&self->content_storage_uid, str));
686       return FALSE;
687     }
688   }
689   current = NULL;
690 
691   if (self->identifications)
692     memset (self->identifications, 0,
693         sizeof (gpointer) * self->n_identifications);
694   else
695     self->identifications =
696         g_new0 (MXFMetadataIdentification *, self->n_identifications);
697   for (i = 0; i < self->n_identifications; i++) {
698     current = g_hash_table_lookup (metadata, &self->identifications_uids[i]);
699     if (current && MXF_IS_METADATA_IDENTIFICATION (current)) {
700       if (mxf_metadata_base_resolve (current, metadata))
701         self->identifications[i] = MXF_METADATA_IDENTIFICATION (current);
702     }
703     current = NULL;
704   }
705 
706   return
707       MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->resolve (m,
708       metadata);
709 }
710 
711 static GstStructure *
mxf_metadata_preface_to_structure(MXFMetadataBase * m)712 mxf_metadata_preface_to_structure (MXFMetadataBase * m)
713 {
714   GstStructure *ret =
715       MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->to_structure
716       (m);
717   MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
718   gchar str[48];
719   guint i;
720 
721   if (!mxf_timestamp_is_unknown (&self->last_modified_date)) {
722     mxf_timestamp_to_string (&self->last_modified_date, str);
723     gst_structure_id_set (ret, MXF_QUARK (LAST_MODIFIED_DATE), G_TYPE_STRING,
724         str, NULL);
725   }
726 
727   if (self->version != 0)
728     gst_structure_id_set (ret, MXF_QUARK (VERSION), G_TYPE_UINT, self->version,
729         NULL);
730 
731   if (self->object_model_version != 0)
732     gst_structure_id_set (ret, MXF_QUARK (OBJECT_MODEL_VERSION), G_TYPE_UINT,
733         self->object_model_version, NULL);
734 
735   if (!mxf_uuid_is_zero (&self->primary_package_uid)) {
736     mxf_uuid_to_string (&self->primary_package_uid, str);
737     gst_structure_id_set (ret, MXF_QUARK (PRIMARY_PACKAGE), G_TYPE_STRING, str,
738         NULL);
739   }
740 
741   if (self->n_identifications > 0) {
742     GValue arr = { 0, }
743     , val = {
744     0,};
745 
746     g_value_init (&arr, GST_TYPE_ARRAY);
747 
748     for (i = 0; i < self->n_identifications; i++) {
749       GstStructure *s;
750 
751       if (self->identifications[i] == NULL)
752         continue;
753 
754       g_value_init (&val, GST_TYPE_STRUCTURE);
755 
756       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
757           (self->identifications[i]));
758       gst_value_set_structure (&val, s);
759       gst_structure_free (s);
760       gst_value_array_append_value (&arr, &val);
761       g_value_unset (&val);
762     }
763 
764     if (gst_value_array_get_size (&arr) > 0)
765       gst_structure_id_set_value (ret, MXF_QUARK (IDENTIFICATIONS), &arr);
766 
767     g_value_unset (&arr);
768   }
769 
770   if (self->content_storage) {
771     GstStructure *s =
772         mxf_metadata_base_to_structure (MXF_METADATA_BASE
773         (self->content_storage));
774     gst_structure_id_set (ret, MXF_QUARK (CONTENT_STORAGE), GST_TYPE_STRUCTURE,
775         s, NULL);
776     gst_structure_free (s);
777   }
778 
779   if (!mxf_ul_is_zero (&self->operational_pattern)) {
780     mxf_ul_to_string (&self->operational_pattern, str);
781     gst_structure_id_set (ret, MXF_QUARK (OPERATIONAL_PATTERN), G_TYPE_STRING,
782         str, NULL);
783   }
784 
785   if (self->n_essence_containers > 0) {
786     GValue arr = { 0, }
787     , val = {
788     0,};
789 
790     g_value_init (&arr, GST_TYPE_ARRAY);
791 
792     for (i = 0; i < self->n_essence_containers; i++) {
793       if (mxf_ul_is_zero (&self->essence_containers[i]))
794         continue;
795 
796       g_value_init (&val, G_TYPE_STRING);
797 
798       mxf_ul_to_string (&self->essence_containers[i], str);
799       g_value_set_string (&val, str);
800 
801       gst_value_array_append_value (&arr, &val);
802       g_value_unset (&val);
803     }
804 
805     if (gst_value_array_get_size (&arr) > 0)
806       gst_structure_id_set_value (ret, MXF_QUARK (ESSENCE_CONTAINERS), &arr);
807 
808     g_value_unset (&arr);
809   }
810 
811   if (self->n_dm_schemes > 0) {
812     GValue arr = { 0, }
813     , val = {
814     0,};
815 
816     g_value_init (&arr, GST_TYPE_ARRAY);
817 
818     for (i = 0; i < self->n_dm_schemes; i++) {
819       if (mxf_ul_is_zero (&self->dm_schemes[i]))
820         continue;
821 
822       g_value_init (&val, G_TYPE_STRING);
823 
824       mxf_ul_to_string (&self->dm_schemes[i], str);
825       g_value_set_string (&val, str);
826 
827       gst_value_array_append_value (&arr, &val);
828       g_value_unset (&val);
829     }
830 
831     if (gst_value_array_get_size (&arr) > 0)
832       gst_structure_id_set_value (ret, MXF_QUARK (DM_SCHEMES), &arr);
833 
834     g_value_unset (&arr);
835   }
836 
837   return ret;
838 }
839 
840 static GList *
mxf_metadata_preface_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)841 mxf_metadata_preface_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
842 {
843   MXFMetadataPreface *self = MXF_METADATA_PREFACE (m);
844   GList *ret =
845       MXF_METADATA_BASE_CLASS (mxf_metadata_preface_parent_class)->write_tags
846       (m, primer);
847   MXFLocalTag *t;
848   guint i;
849 
850   t = g_slice_new0 (MXFLocalTag);
851   memcpy (&t->ul, MXF_UL (LAST_MODIFIED_DATE), 16);
852   t->size = 8;
853   t->data = g_slice_alloc (8);
854   t->g_slice = TRUE;
855   mxf_timestamp_write (&self->last_modified_date, t->data);
856   mxf_primer_pack_add_mapping (primer, 0x3b02, &t->ul);
857   ret = g_list_prepend (ret, t);
858 
859   t = g_slice_new0 (MXFLocalTag);
860   memcpy (&t->ul, MXF_UL (VERSION), 16);
861   t->size = 2;
862   t->data = g_slice_alloc (2);
863   t->g_slice = TRUE;
864   GST_WRITE_UINT16_BE (t->data, self->version);
865   mxf_primer_pack_add_mapping (primer, 0x3b05, &t->ul);
866   ret = g_list_prepend (ret, t);
867 
868   if (self->object_model_version) {
869     t = g_slice_new0 (MXFLocalTag);
870     memcpy (&t->ul, MXF_UL (OBJECT_MODEL_VERSION), 16);
871     t->size = 4;
872     t->data = g_slice_alloc (4);
873     t->g_slice = TRUE;
874     GST_WRITE_UINT32_BE (t->data, self->object_model_version);
875     mxf_primer_pack_add_mapping (primer, 0x3b07, &t->ul);
876     ret = g_list_prepend (ret, t);
877   }
878 
879   if (!mxf_uuid_is_zero (&self->primary_package_uid)) {
880     t = g_slice_new0 (MXFLocalTag);
881     memcpy (&t->ul, MXF_UL (PRIMARY_PACKAGE), 16);
882     t->size = 16;
883     t->data = g_slice_alloc (16);
884     t->g_slice = TRUE;
885     memcpy (t->data, &self->primary_package_uid, 16);
886     mxf_primer_pack_add_mapping (primer, 0x3b08, &t->ul);
887     ret = g_list_prepend (ret, t);
888   }
889 
890   t = g_slice_new0 (MXFLocalTag);
891   memcpy (&t->ul, MXF_UL (IDENTIFICATIONS), 16);
892   t->size = 8 + 16 * self->n_identifications;
893   t->data = g_slice_alloc0 (t->size);
894   t->g_slice = TRUE;
895   mxf_primer_pack_add_mapping (primer, 0x3b06, &t->ul);
896   GST_WRITE_UINT32_BE (t->data, self->n_identifications);
897   GST_WRITE_UINT32_BE (t->data + 4, 16);
898   for (i = 0; i < self->n_identifications; i++) {
899     if (!self->identifications[i])
900       continue;
901 
902     memcpy (t->data + 8 + 16 * i,
903         &MXF_METADATA_BASE (self->identifications[i])->instance_uid, 16);
904   }
905   ret = g_list_prepend (ret, t);
906 
907   t = g_slice_new0 (MXFLocalTag);
908   memcpy (&t->ul, MXF_UL (CONTENT_STORAGE), 16);
909   t->size = 16;
910   t->data = g_slice_alloc (t->size);
911   t->g_slice = TRUE;
912   mxf_primer_pack_add_mapping (primer, 0x3b03, &t->ul);
913   memcpy (t->data, &MXF_METADATA_BASE (self->content_storage)->instance_uid,
914       16);
915   ret = g_list_prepend (ret, t);
916 
917   t = g_slice_new0 (MXFLocalTag);
918   memcpy (&t->ul, MXF_UL (OPERATIONAL_PATTERN), 16);
919   t->size = 16;
920   t->data = g_slice_alloc (t->size);
921   t->g_slice = TRUE;
922   mxf_primer_pack_add_mapping (primer, 0x3b09, &t->ul);
923   memcpy (t->data, &self->operational_pattern, 16);
924   ret = g_list_prepend (ret, t);
925 
926   t = g_slice_new0 (MXFLocalTag);
927   memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINERS), 16);
928   t->size = 8 + 16 * self->n_essence_containers;
929   t->data = g_slice_alloc0 (t->size);
930   t->g_slice = TRUE;
931   mxf_primer_pack_add_mapping (primer, 0x3b0a, &t->ul);
932   GST_WRITE_UINT32_BE (t->data, self->n_essence_containers);
933   GST_WRITE_UINT32_BE (t->data + 4, 16);
934   for (i = 0; i < self->n_essence_containers; i++) {
935     memcpy (t->data + 8 + 16 * i, &self->essence_containers[i], 16);
936   }
937   ret = g_list_prepend (ret, t);
938 
939   t = g_slice_new0 (MXFLocalTag);
940   memcpy (&t->ul, MXF_UL (DM_SCHEMES), 16);
941   t->size = 8 + 16 * self->n_dm_schemes;
942   t->data = g_slice_alloc0 (t->size);
943   t->g_slice = TRUE;
944   mxf_primer_pack_add_mapping (primer, 0x3b0b, &t->ul);
945   GST_WRITE_UINT32_BE (t->data, self->n_dm_schemes);
946   GST_WRITE_UINT32_BE (t->data + 4, 16);
947   for (i = 0; i < self->n_dm_schemes; i++) {
948     memcpy (t->data + 8 + 16 * i, &self->dm_schemes[i], 16);
949   }
950   ret = g_list_prepend (ret, t);
951 
952   return ret;
953 }
954 
955 static void
mxf_metadata_preface_init(MXFMetadataPreface * self)956 mxf_metadata_preface_init (MXFMetadataPreface * self)
957 {
958 
959 }
960 
961 static void
mxf_metadata_preface_class_init(MXFMetadataPrefaceClass * klass)962 mxf_metadata_preface_class_init (MXFMetadataPrefaceClass * klass)
963 {
964   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
965   GObjectClass *object_class = (GObjectClass *) klass;
966   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
967 
968   object_class->finalize = mxf_metadata_preface_finalize;
969   metadata_base_class->handle_tag = mxf_metadata_preface_handle_tag;
970   metadata_base_class->resolve = mxf_metadata_preface_resolve;
971   metadata_base_class->to_structure = mxf_metadata_preface_to_structure;
972   metadata_base_class->write_tags = mxf_metadata_preface_write_tags;
973   metadata_base_class->name_quark = MXF_QUARK (PREFACE);
974   metadata_class->type = 0x012f;
975 }
976 
977 G_DEFINE_TYPE (MXFMetadataIdentification, mxf_metadata_identification,
978     MXF_TYPE_METADATA);
979 
980 static void
mxf_metadata_identification_finalize(GObject * object)981 mxf_metadata_identification_finalize (GObject * object)
982 {
983   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (object);
984 
985   g_free (self->company_name);
986   self->company_name = NULL;
987 
988   g_free (self->product_name);
989   self->product_name = NULL;
990 
991   g_free (self->version_string);
992   self->version_string = NULL;
993 
994   g_free (self->platform);
995   self->platform = NULL;
996 
997   G_OBJECT_CLASS (mxf_metadata_identification_parent_class)->finalize (object);
998 }
999 
1000 static gboolean
mxf_metadata_identification_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)1001 mxf_metadata_identification_handle_tag (MXFMetadataBase * metadata,
1002     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1003     guint tag_size)
1004 {
1005   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (metadata);
1006   gboolean ret = TRUE;
1007 #ifndef GST_DISABLE_GST_DEBUG
1008   gchar str[48];
1009 #endif
1010 
1011   switch (tag) {
1012     case 0x3c09:
1013       if (tag_size != 16)
1014         goto error;
1015       memcpy (&self->this_generation_uid, tag_data, 16);
1016       GST_DEBUG ("  this generation uid = %s",
1017           mxf_uuid_to_string (&self->this_generation_uid, str));
1018       break;
1019     case 0x3c01:
1020       self->company_name = mxf_utf16_to_utf8 (tag_data, tag_size);
1021       GST_DEBUG ("  company name = %s", GST_STR_NULL (self->company_name));
1022       break;
1023     case 0x3c02:
1024       self->product_name = mxf_utf16_to_utf8 (tag_data, tag_size);
1025       GST_DEBUG ("  product name = %s", GST_STR_NULL (self->product_name));
1026       break;
1027     case 0x3c03:
1028       if (!mxf_product_version_parse (&self->product_version,
1029               tag_data, tag_size))
1030         goto error;
1031       GST_DEBUG ("  product version = %u.%u.%u.%u.%u",
1032           self->product_version.major,
1033           self->product_version.minor,
1034           self->product_version.patch,
1035           self->product_version.build, self->product_version.release);
1036       break;
1037     case 0x3c04:
1038       self->version_string = mxf_utf16_to_utf8 (tag_data, tag_size);
1039       GST_DEBUG ("  version string = %s", GST_STR_NULL (self->version_string));
1040       break;
1041     case 0x3c05:
1042       if (tag_size != 16)
1043         goto error;
1044       memcpy (&self->product_uid, tag_data, 16);
1045       GST_DEBUG ("  product uid = %s",
1046           mxf_uuid_to_string (&self->product_uid, str));
1047       break;
1048     case 0x3c06:
1049       if (!mxf_timestamp_parse (&self->modification_date, tag_data, tag_size))
1050         goto error;
1051       GST_DEBUG ("  modification date = %s",
1052           mxf_timestamp_to_string (&self->modification_date, str));
1053       break;
1054     case 0x3c07:
1055       if (!mxf_product_version_parse (&self->toolkit_version,
1056               tag_data, tag_size))
1057         goto error;
1058       GST_DEBUG ("  toolkit version = %u.%u.%u.%u.%u",
1059           self->toolkit_version.major,
1060           self->toolkit_version.minor,
1061           self->toolkit_version.patch,
1062           self->toolkit_version.build, self->toolkit_version.release);
1063       break;
1064     case 0x3c08:
1065       self->platform = mxf_utf16_to_utf8 (tag_data, tag_size);
1066       GST_DEBUG ("  platform = %s", GST_STR_NULL (self->platform));
1067       break;
1068     default:
1069       ret =
1070           MXF_METADATA_BASE_CLASS
1071           (mxf_metadata_identification_parent_class)->handle_tag (metadata,
1072           primer, tag, tag_data, tag_size);
1073       break;
1074   }
1075 
1076   return ret;
1077 
1078 error:
1079   GST_ERROR ("Invalid identification local tag 0x%04x of size %u", tag,
1080       tag_size);
1081 
1082   return FALSE;
1083 }
1084 
1085 static GstStructure *
mxf_metadata_identification_to_structure(MXFMetadataBase * m)1086 mxf_metadata_identification_to_structure (MXFMetadataBase * m)
1087 {
1088   GstStructure *ret =
1089       MXF_METADATA_BASE_CLASS
1090       (mxf_metadata_identification_parent_class)->to_structure (m);
1091   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (m);
1092   gchar str[48];
1093 
1094   if (!mxf_uuid_is_zero (&self->this_generation_uid)) {
1095     mxf_uuid_to_string (&self->this_generation_uid, str);
1096     gst_structure_id_set (ret, MXF_QUARK (THIS_GENERATION_UID), G_TYPE_STRING,
1097         str, NULL);
1098   }
1099 
1100   if (self->company_name)
1101     gst_structure_id_set (ret, MXF_QUARK (COMPANY_NAME), G_TYPE_STRING,
1102         self->company_name, NULL);
1103 
1104   if (self->product_name)
1105     gst_structure_id_set (ret, MXF_QUARK (PRODUCT_NAME), G_TYPE_STRING,
1106         self->product_name, NULL);
1107 
1108   if (self->product_version.major ||
1109       self->product_version.minor ||
1110       self->product_version.patch ||
1111       self->product_version.build || self->product_version.release) {
1112     g_snprintf (str, 48, "%u.%u.%u.%u.%u", self->product_version.major,
1113         self->product_version.minor,
1114         self->product_version.patch,
1115         self->product_version.build, self->product_version.release);
1116     gst_structure_id_set (ret, MXF_QUARK (PRODUCT_VERSION), G_TYPE_STRING, str,
1117         NULL);
1118   }
1119 
1120   if (self->version_string)
1121     gst_structure_id_set (ret, MXF_QUARK (VERSION_STRING), G_TYPE_STRING,
1122         self->version_string, NULL);
1123 
1124   if (!mxf_uuid_is_zero (&self->product_uid)) {
1125     mxf_uuid_to_string (&self->product_uid, str);
1126     gst_structure_id_set (ret, MXF_QUARK (PRODUCT_UID), G_TYPE_STRING, str,
1127         NULL);
1128   }
1129 
1130   if (!mxf_timestamp_is_unknown (&self->modification_date)) {
1131     mxf_timestamp_to_string (&self->modification_date, str);
1132     gst_structure_id_set (ret, MXF_QUARK (MODIFICATION_DATE), G_TYPE_STRING,
1133         str, NULL);
1134   }
1135 
1136   if (self->toolkit_version.major ||
1137       self->toolkit_version.minor ||
1138       self->toolkit_version.patch ||
1139       self->toolkit_version.build || self->toolkit_version.release) {
1140     g_snprintf (str, 48, "%u.%u.%u.%u.%u", self->toolkit_version.major,
1141         self->toolkit_version.minor,
1142         self->toolkit_version.patch,
1143         self->toolkit_version.build, self->toolkit_version.release);
1144     gst_structure_id_set (ret, MXF_QUARK (TOOLKIT_VERSION), G_TYPE_STRING, str,
1145         NULL);
1146   }
1147 
1148   if (self->platform)
1149     gst_structure_id_set (ret, MXF_QUARK (PLATFORM), G_TYPE_STRING,
1150         self->platform, NULL);
1151 
1152   return ret;
1153 }
1154 
1155 static GList *
mxf_metadata_identification_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)1156 mxf_metadata_identification_write_tags (MXFMetadataBase * m,
1157     MXFPrimerPack * primer)
1158 {
1159   MXFMetadataIdentification *self = MXF_METADATA_IDENTIFICATION (m);
1160   GList *ret =
1161       MXF_METADATA_BASE_CLASS
1162       (mxf_metadata_identification_parent_class)->write_tags (m, primer);
1163   MXFLocalTag *t;
1164 
1165   if (self->company_name) {
1166     t = g_slice_new0 (MXFLocalTag);
1167     memcpy (&t->ul, MXF_UL (COMPANY_NAME), 16);
1168     t->data = mxf_utf8_to_utf16 (self->company_name, &t->size);
1169     mxf_primer_pack_add_mapping (primer, 0x3c01, &t->ul);
1170     ret = g_list_prepend (ret, t);
1171   }
1172 
1173   if (self->product_name) {
1174     t = g_slice_new0 (MXFLocalTag);
1175     memcpy (&t->ul, MXF_UL (PRODUCT_NAME), 16);
1176     t->data = mxf_utf8_to_utf16 (self->product_name, &t->size);
1177     mxf_primer_pack_add_mapping (primer, 0x3c02, &t->ul);
1178     ret = g_list_prepend (ret, t);
1179   }
1180 
1181   if (!mxf_product_version_is_valid (&self->product_version)) {
1182     t = g_slice_new0 (MXFLocalTag);
1183     memcpy (&t->ul, MXF_UL (PRODUCT_VERSION), 16);
1184     t->size = 10;
1185     t->data = g_slice_alloc (t->size);
1186     t->g_slice = TRUE;
1187     mxf_product_version_write (&self->product_version, t->data);
1188     mxf_primer_pack_add_mapping (primer, 0x3c03, &t->ul);
1189     ret = g_list_prepend (ret, t);
1190   }
1191 
1192   if (self->version_string) {
1193     t = g_slice_new0 (MXFLocalTag);
1194     memcpy (&t->ul, MXF_UL (VERSION_STRING), 16);
1195     t->data = mxf_utf8_to_utf16 (self->version_string, &t->size);
1196     mxf_primer_pack_add_mapping (primer, 0x3c04, &t->ul);
1197     ret = g_list_prepend (ret, t);
1198   }
1199 
1200   if (!mxf_uuid_is_zero (&self->product_uid)) {
1201     t = g_slice_new0 (MXFLocalTag);
1202     memcpy (&t->ul, MXF_UL (PRODUCT_UID), 16);
1203     t->size = 16;
1204     t->data = g_slice_alloc (t->size);
1205     t->g_slice = TRUE;
1206     memcpy (t->data, &self->product_uid, 16);
1207     mxf_primer_pack_add_mapping (primer, 0x3c05, &t->ul);
1208     ret = g_list_prepend (ret, t);
1209   }
1210 
1211   if (!mxf_timestamp_is_unknown (&self->modification_date)) {
1212     t = g_slice_new0 (MXFLocalTag);
1213     memcpy (&t->ul, MXF_UL (MODIFICATION_DATE), 16);
1214     t->size = 8;
1215     t->data = g_slice_alloc (t->size);
1216     t->g_slice = TRUE;
1217     mxf_timestamp_write (&self->modification_date, t->data);
1218     mxf_primer_pack_add_mapping (primer, 0x3c06, &t->ul);
1219     ret = g_list_prepend (ret, t);
1220   }
1221 
1222   if (!mxf_product_version_is_valid (&self->toolkit_version)) {
1223     t = g_slice_new0 (MXFLocalTag);
1224     memcpy (&t->ul, MXF_UL (TOOLKIT_VERSION), 16);
1225     t->size = 10;
1226     t->data = g_slice_alloc (t->size);
1227     t->g_slice = TRUE;
1228     mxf_product_version_write (&self->toolkit_version, t->data);
1229     mxf_primer_pack_add_mapping (primer, 0x3c07, &t->ul);
1230     ret = g_list_prepend (ret, t);
1231   }
1232 
1233   if (self->platform) {
1234     t = g_slice_new0 (MXFLocalTag);
1235     memcpy (&t->ul, MXF_UL (PLATFORM), 16);
1236     t->data = mxf_utf8_to_utf16 (self->platform, &t->size);
1237     mxf_primer_pack_add_mapping (primer, 0x3c08, &t->ul);
1238     ret = g_list_prepend (ret, t);
1239   }
1240 
1241   if (!mxf_uuid_is_zero (&self->this_generation_uid)) {
1242     t = g_slice_new0 (MXFLocalTag);
1243     memcpy (&t->ul, MXF_UL (THIS_GENERATION_UID), 16);
1244     t->size = 16;
1245     t->data = g_slice_alloc (t->size);
1246     t->g_slice = TRUE;
1247     memcpy (t->data, &self->this_generation_uid, 16);
1248     mxf_primer_pack_add_mapping (primer, 0x3c09, &t->ul);
1249     ret = g_list_prepend (ret, t);
1250   }
1251 
1252   return ret;
1253 }
1254 
1255 static void
mxf_metadata_identification_init(MXFMetadataIdentification * self)1256 mxf_metadata_identification_init (MXFMetadataIdentification * self)
1257 {
1258 
1259 }
1260 
1261 static void
mxf_metadata_identification_class_init(MXFMetadataIdentificationClass * klass)1262 mxf_metadata_identification_class_init (MXFMetadataIdentificationClass * klass)
1263 {
1264   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
1265   GObjectClass *object_class = (GObjectClass *) klass;
1266   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
1267 
1268   object_class->finalize = mxf_metadata_identification_finalize;
1269   metadata_base_class->handle_tag = mxf_metadata_identification_handle_tag;
1270   metadata_base_class->name_quark = MXF_QUARK (IDENTIFICATION);
1271   metadata_base_class->to_structure = mxf_metadata_identification_to_structure;
1272   metadata_base_class->write_tags = mxf_metadata_identification_write_tags;
1273   metadata_class->type = 0x0130;
1274 }
1275 
1276 G_DEFINE_TYPE (MXFMetadataContentStorage, mxf_metadata_content_storage,
1277     MXF_TYPE_METADATA);
1278 
1279 static void
mxf_metadata_content_storage_finalize(GObject * object)1280 mxf_metadata_content_storage_finalize (GObject * object)
1281 {
1282   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (object);
1283 
1284   g_free (self->packages);
1285   self->packages = NULL;
1286   g_free (self->packages_uids);
1287   self->packages_uids = NULL;
1288   g_free (self->essence_container_data);
1289   self->essence_container_data = NULL;
1290   g_free (self->essence_container_data_uids);
1291   self->essence_container_data_uids = NULL;
1292 
1293   G_OBJECT_CLASS (mxf_metadata_content_storage_parent_class)->finalize (object);
1294 }
1295 
1296 static gboolean
mxf_metadata_content_storage_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)1297 mxf_metadata_content_storage_handle_tag (MXFMetadataBase * metadata,
1298     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1299     guint tag_size)
1300 {
1301   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (metadata);
1302   gboolean ret = TRUE;
1303 #ifndef GST_DISABLE_GST_DEBUG
1304   gchar str[48];
1305 #endif
1306 
1307   switch (tag) {
1308     case 0x1901:
1309       if (!mxf_uuid_array_parse (&self->packages_uids, &self->n_packages,
1310               tag_data, tag_size))
1311         goto error;
1312       GST_DEBUG ("  number of packages = %u", self->n_packages);
1313 #ifndef GST_DISABLE_GST_DEBUG
1314       {
1315         guint i;
1316         for (i = 0; i < self->n_packages; i++) {
1317           GST_DEBUG ("  package %u = %s", i,
1318               mxf_uuid_to_string (&self->packages_uids[i], str));
1319         }
1320       }
1321 #endif
1322       break;
1323     case 0x1902:
1324       if (!mxf_uuid_array_parse (&self->essence_container_data_uids,
1325               &self->n_essence_container_data, tag_data, tag_size))
1326         goto error;
1327 
1328       GST_DEBUG ("  number of essence container data = %u",
1329           self->n_essence_container_data);
1330 #ifndef GST_DISABLE_GST_DEBUG
1331       {
1332         guint i;
1333         for (i = 0; i < self->n_essence_container_data; i++) {
1334           GST_DEBUG ("  essence container data %u = %s", i,
1335               mxf_uuid_to_string (&self->essence_container_data_uids[i], str));
1336         }
1337       }
1338 #endif
1339       break;
1340     default:
1341       ret =
1342           MXF_METADATA_BASE_CLASS
1343           (mxf_metadata_content_storage_parent_class)->handle_tag (metadata,
1344           primer, tag, tag_data, tag_size);
1345       break;
1346   }
1347 
1348   return ret;
1349 
1350 error:
1351 
1352   GST_ERROR ("Invalid content storage local tag 0x%04x of size %u", tag,
1353       tag_size);
1354 
1355   return FALSE;
1356 }
1357 
1358 static gboolean
mxf_metadata_content_storage_resolve(MXFMetadataBase * m,GHashTable * metadata)1359 mxf_metadata_content_storage_resolve (MXFMetadataBase * m,
1360     GHashTable * metadata)
1361 {
1362   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
1363   MXFMetadataBase *current = NULL;
1364   guint i;
1365   gboolean have_package = FALSE;
1366   gboolean have_ecd = FALSE;
1367 #ifndef GST_DISABLE_GST_DEBUG
1368   gchar str[48];
1369 #endif
1370 
1371   if (self->packages)
1372     memset (self->packages, 0, sizeof (gpointer) * self->n_packages);
1373   else
1374     self->packages = g_new0 (MXFMetadataGenericPackage *, self->n_packages);
1375 
1376   for (i = 0; i < self->n_packages; i++) {
1377     current = g_hash_table_lookup (metadata, &self->packages_uids[i]);
1378     if (current && MXF_IS_METADATA_GENERIC_PACKAGE (current)) {
1379       if (mxf_metadata_base_resolve (current, metadata)) {
1380         self->packages[i] = MXF_METADATA_GENERIC_PACKAGE (current);
1381         have_package = TRUE;
1382       } else {
1383         GST_ERROR ("Couldn't resolve package %s",
1384             mxf_uuid_to_string (&self->packages_uids[i], str));
1385       }
1386     } else {
1387       GST_ERROR ("Package %s not found",
1388           mxf_uuid_to_string (&self->packages_uids[i], str));
1389     }
1390   }
1391 
1392   if (self->essence_container_data)
1393     memset (self->essence_container_data, 0,
1394         sizeof (gpointer) * self->n_essence_container_data);
1395   else
1396     self->essence_container_data =
1397         g_new0 (MXFMetadataEssenceContainerData *,
1398         self->n_essence_container_data);
1399   for (i = 0; i < self->n_essence_container_data; i++) {
1400     current =
1401         g_hash_table_lookup (metadata, &self->essence_container_data_uids[i]);
1402     if (current && MXF_IS_METADATA_ESSENCE_CONTAINER_DATA (current)) {
1403       if (mxf_metadata_base_resolve (current, metadata)) {
1404         self->essence_container_data[i] =
1405             MXF_METADATA_ESSENCE_CONTAINER_DATA (current);
1406         have_ecd = TRUE;
1407       } else {
1408         GST_ERROR ("Couldn't resolve essence container data %s",
1409             mxf_uuid_to_string (&self->essence_container_data_uids[i], str));
1410       }
1411     } else {
1412       GST_ERROR ("Essence container data %s not found",
1413           mxf_uuid_to_string (&self->essence_container_data_uids[i], str));
1414     }
1415   }
1416 
1417   if (!have_package) {
1418     GST_ERROR ("Couldn't resolve any package");
1419     return FALSE;
1420   } else if (!have_ecd) {
1421     GST_ERROR ("Couldn't resolve any essence container data");
1422     return FALSE;
1423   }
1424 
1425   return
1426       MXF_METADATA_BASE_CLASS
1427       (mxf_metadata_content_storage_parent_class)->resolve (m, metadata);
1428 }
1429 
1430 static GstStructure *
mxf_metadata_content_storage_to_structure(MXFMetadataBase * m)1431 mxf_metadata_content_storage_to_structure (MXFMetadataBase * m)
1432 {
1433   GstStructure *ret =
1434       MXF_METADATA_BASE_CLASS
1435       (mxf_metadata_content_storage_parent_class)->to_structure (m);
1436   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
1437   guint i;
1438 
1439   if (self->n_packages > 0) {
1440     GValue arr = { 0, }
1441     , val = {
1442     0,};
1443 
1444     g_value_init (&arr, GST_TYPE_ARRAY);
1445 
1446     for (i = 0; i < self->n_packages; i++) {
1447       GstStructure *s;
1448 
1449       if (self->packages[i] == NULL)
1450         continue;
1451 
1452       g_value_init (&val, GST_TYPE_STRUCTURE);
1453 
1454       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->packages
1455               [i]));
1456       gst_value_set_structure (&val, s);
1457       gst_structure_free (s);
1458       gst_value_array_append_value (&arr, &val);
1459       g_value_unset (&val);
1460     }
1461 
1462     if (gst_value_array_get_size (&arr) > 0)
1463       gst_structure_id_set_value (ret, MXF_QUARK (PACKAGES), &arr);
1464 
1465     g_value_unset (&arr);
1466   }
1467 
1468   if (self->n_essence_container_data > 0) {
1469     GValue arr = { 0, }
1470     , val = {
1471     0,};
1472 
1473     g_value_init (&arr, GST_TYPE_ARRAY);
1474 
1475     for (i = 0; i < self->n_essence_container_data; i++) {
1476       GstStructure *s;
1477 
1478       if (self->essence_container_data[i] == NULL)
1479         continue;
1480 
1481       g_value_init (&val, GST_TYPE_STRUCTURE);
1482 
1483       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
1484           (self->essence_container_data[i]));
1485       gst_value_set_structure (&val, s);
1486       gst_structure_free (s);
1487       gst_value_array_append_value (&arr, &val);
1488       g_value_unset (&val);
1489     }
1490 
1491     if (gst_value_array_get_size (&arr) > 0)
1492       gst_structure_id_set_value (ret, MXF_QUARK (ESSENCE_CONTAINER_DATA),
1493           &arr);
1494 
1495     g_value_unset (&arr);
1496   }
1497 
1498   return ret;
1499 }
1500 
1501 static GList *
mxf_metadata_content_storage_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)1502 mxf_metadata_content_storage_write_tags (MXFMetadataBase * m,
1503     MXFPrimerPack * primer)
1504 {
1505   MXFMetadataContentStorage *self = MXF_METADATA_CONTENT_STORAGE (m);
1506   GList *ret =
1507       MXF_METADATA_BASE_CLASS
1508       (mxf_metadata_content_storage_parent_class)->write_tags (m, primer);
1509   MXFLocalTag *t;
1510   guint i;
1511 
1512   if (self->packages) {
1513     t = g_slice_new0 (MXFLocalTag);
1514     memcpy (&t->ul, MXF_UL (PACKAGES), 16);
1515     t->size = 8 + 16 * self->n_packages;
1516     t->data = g_slice_alloc0 (t->size);
1517     t->g_slice = TRUE;
1518     GST_WRITE_UINT32_BE (t->data, self->n_packages);
1519     GST_WRITE_UINT32_BE (t->data + 4, 16);
1520     for (i = 0; i < self->n_packages; i++) {
1521       if (!self->packages[i])
1522         continue;
1523 
1524       memcpy (t->data + 8 + i * 16,
1525           &MXF_METADATA_BASE (self->packages[i])->instance_uid, 16);
1526     }
1527 
1528     mxf_primer_pack_add_mapping (primer, 0x1901, &t->ul);
1529     ret = g_list_prepend (ret, t);
1530   }
1531 
1532   if (self->essence_container_data) {
1533     t = g_slice_new0 (MXFLocalTag);
1534     memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINER_DATA), 16);
1535     t->size = 8 + 16 * self->n_essence_container_data;
1536     t->data = g_slice_alloc0 (t->size);
1537     t->g_slice = TRUE;
1538     GST_WRITE_UINT32_BE (t->data, self->n_essence_container_data);
1539     GST_WRITE_UINT32_BE (t->data + 4, 16);
1540     for (i = 0; i < self->n_essence_container_data; i++) {
1541       if (!self->essence_container_data[i])
1542         continue;
1543 
1544       memcpy (t->data + 8 + i * 16,
1545           &MXF_METADATA_BASE (self->essence_container_data[i])->instance_uid,
1546           16);
1547     }
1548 
1549     mxf_primer_pack_add_mapping (primer, 0x1902, &t->ul);
1550     ret = g_list_prepend (ret, t);
1551   }
1552 
1553   return ret;
1554 }
1555 
1556 static void
mxf_metadata_content_storage_init(MXFMetadataContentStorage * self)1557 mxf_metadata_content_storage_init (MXFMetadataContentStorage * self)
1558 {
1559 
1560 }
1561 
1562 static void
mxf_metadata_content_storage_class_init(MXFMetadataContentStorageClass * klass)1563 mxf_metadata_content_storage_class_init (MXFMetadataContentStorageClass * klass)
1564 {
1565   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
1566   GObjectClass *object_class = (GObjectClass *) klass;
1567   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
1568 
1569   object_class->finalize = mxf_metadata_content_storage_finalize;
1570   metadata_base_class->handle_tag = mxf_metadata_content_storage_handle_tag;
1571   metadata_base_class->resolve = mxf_metadata_content_storage_resolve;
1572   metadata_base_class->name_quark = MXF_QUARK (CONTENT_STORAGE);
1573   metadata_base_class->to_structure = mxf_metadata_content_storage_to_structure;
1574   metadata_base_class->write_tags = mxf_metadata_content_storage_write_tags;
1575   metadata_class->type = 0x0118;
1576 }
1577 
1578 G_DEFINE_TYPE (MXFMetadataEssenceContainerData,
1579     mxf_metadata_essence_container_data, MXF_TYPE_METADATA);
1580 
1581 static gboolean
mxf_metadata_essence_container_data_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)1582 mxf_metadata_essence_container_data_handle_tag (MXFMetadataBase * metadata,
1583     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1584     guint tag_size)
1585 {
1586   MXFMetadataEssenceContainerData *self =
1587       MXF_METADATA_ESSENCE_CONTAINER_DATA (metadata);
1588   gboolean ret = TRUE;
1589 #ifndef GST_DISABLE_GST_DEBUG
1590   gchar str[96];
1591 #endif
1592 
1593   switch (tag) {
1594     case 0x2701:
1595       if (tag_size != 32)
1596         goto error;
1597       memcpy (&self->linked_package_uid, tag_data, 32);
1598       GST_DEBUG ("  linked package = %s",
1599           mxf_umid_to_string (&self->linked_package_uid, str));
1600       break;
1601     case 0x3f06:
1602       if (tag_size != 4)
1603         goto error;
1604       self->index_sid = GST_READ_UINT32_BE (tag_data);
1605       GST_DEBUG ("  index sid = %u", self->index_sid);
1606       break;
1607     case 0x3f07:
1608       if (tag_size != 4)
1609         goto error;
1610       self->body_sid = GST_READ_UINT32_BE (tag_data);
1611       GST_DEBUG ("  body sid = %u", self->body_sid);
1612       break;
1613     default:
1614       ret =
1615           MXF_METADATA_BASE_CLASS
1616           (mxf_metadata_essence_container_data_parent_class)->handle_tag
1617           (metadata, primer, tag, tag_data, tag_size);
1618       break;
1619   }
1620 
1621   return ret;
1622 
1623 error:
1624 
1625   GST_ERROR ("Invalid essence container data local tag 0x%04x of size %u", tag,
1626       tag_size);
1627 
1628   return FALSE;
1629 }
1630 
1631 static gboolean
mxf_metadata_essence_container_data_resolve(MXFMetadataBase * m,GHashTable * metadata)1632 mxf_metadata_essence_container_data_resolve (MXFMetadataBase * m,
1633     GHashTable * metadata)
1634 {
1635   MXFMetadataEssenceContainerData *self =
1636       MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
1637   MXFMetadataBase *current = NULL;
1638   GHashTableIter iter;
1639 #ifndef GST_DISABLE_GST_DEBUG
1640   gchar str[96];
1641 #endif
1642 
1643   g_hash_table_iter_init (&iter, metadata);
1644 
1645   while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
1646     if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
1647       MXFMetadataSourcePackage *package = MXF_METADATA_SOURCE_PACKAGE (current);
1648 
1649       if (mxf_umid_is_equal (&package->parent.package_uid,
1650               &self->linked_package_uid)) {
1651         if (mxf_metadata_base_resolve (current, metadata)) {
1652           self->linked_package = package;
1653         } else {
1654           GST_ERROR ("Couldn't resolve linked package %s",
1655               mxf_umid_to_string (&self->linked_package_uid, str));
1656         }
1657         break;
1658       }
1659     }
1660   }
1661 
1662   if (!self->linked_package) {
1663     GST_ERROR ("Couldn't resolve or find linked package %s",
1664         mxf_umid_to_string (&self->linked_package_uid, str));
1665     return FALSE;
1666   }
1667 
1668   return
1669       MXF_METADATA_BASE_CLASS
1670       (mxf_metadata_essence_container_data_parent_class)->resolve (m, metadata);
1671 }
1672 
1673 static GstStructure *
mxf_metadata_essence_container_data_to_structure(MXFMetadataBase * m)1674 mxf_metadata_essence_container_data_to_structure (MXFMetadataBase * m)
1675 {
1676   GstStructure *ret =
1677       MXF_METADATA_BASE_CLASS
1678       (mxf_metadata_essence_container_data_parent_class)->to_structure (m);
1679   MXFMetadataEssenceContainerData *self =
1680       MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
1681   gchar str[96];
1682 
1683   if (!mxf_umid_is_zero (&self->linked_package_uid)) {
1684     mxf_umid_to_string (&self->linked_package_uid, str);
1685     gst_structure_id_set (ret, MXF_QUARK (LINKED_PACKAGE), G_TYPE_STRING, str,
1686         NULL);
1687   }
1688 
1689   gst_structure_id_set (ret, MXF_QUARK (INDEX_SID), G_TYPE_UINT,
1690       self->index_sid, MXF_QUARK (BODY_SID), G_TYPE_UINT, self->body_sid, NULL);
1691 
1692 
1693   return ret;
1694 }
1695 
1696 static GList *
mxf_metadata_essence_container_data_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)1697 mxf_metadata_essence_container_data_write_tags (MXFMetadataBase * m,
1698     MXFPrimerPack * primer)
1699 {
1700   MXFMetadataEssenceContainerData *self =
1701       MXF_METADATA_ESSENCE_CONTAINER_DATA (m);
1702   GList *ret =
1703       MXF_METADATA_BASE_CLASS
1704       (mxf_metadata_essence_container_data_parent_class)->write_tags (m,
1705       primer);
1706   MXFLocalTag *t;
1707 
1708   t = g_slice_new0 (MXFLocalTag);
1709   memcpy (&t->ul, MXF_UL (LINKED_PACKAGE_UID), 16);
1710   t->size = 32;
1711   t->data = g_slice_alloc0 (32);
1712   t->g_slice = TRUE;
1713   if (self->linked_package)
1714     memcpy (t->data, &self->linked_package->parent.package_uid, 32);
1715   mxf_primer_pack_add_mapping (primer, 0x2701, &t->ul);
1716   ret = g_list_prepend (ret, t);
1717 
1718   t = g_slice_new0 (MXFLocalTag);
1719   memcpy (&t->ul, MXF_UL (BODY_SID), 16);
1720   t->size = 4;
1721   t->data = g_slice_alloc (4);
1722   t->g_slice = TRUE;
1723   GST_WRITE_UINT32_BE (t->data, self->body_sid);
1724   mxf_primer_pack_add_mapping (primer, 0x3f07, &t->ul);
1725   ret = g_list_prepend (ret, t);
1726 
1727   if (self->index_sid) {
1728     t = g_slice_new0 (MXFLocalTag);
1729     memcpy (&t->ul, MXF_UL (INDEX_SID), 16);
1730     t->size = 4;
1731     t->data = g_slice_alloc (4);
1732     t->g_slice = TRUE;
1733     GST_WRITE_UINT32_BE (t->data, self->index_sid);
1734     mxf_primer_pack_add_mapping (primer, 0x3f06, &t->ul);
1735     ret = g_list_prepend (ret, t);
1736   }
1737 
1738   return ret;
1739 }
1740 
1741 static void
mxf_metadata_essence_container_data_init(MXFMetadataEssenceContainerData * self)1742 mxf_metadata_essence_container_data_init (MXFMetadataEssenceContainerData *
1743     self)
1744 {
1745 
1746 }
1747 
1748 static void
mxf_metadata_essence_container_data_class_init(MXFMetadataEssenceContainerDataClass * klass)1749     mxf_metadata_essence_container_data_class_init
1750     (MXFMetadataEssenceContainerDataClass * klass)
1751 {
1752   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
1753   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
1754 
1755   metadata_base_class->handle_tag =
1756       mxf_metadata_essence_container_data_handle_tag;
1757   metadata_base_class->resolve = mxf_metadata_essence_container_data_resolve;
1758   metadata_base_class->name_quark = MXF_QUARK (ESSENCE_CONTAINER_DATA);
1759   metadata_base_class->to_structure =
1760       mxf_metadata_essence_container_data_to_structure;
1761   metadata_base_class->write_tags =
1762       mxf_metadata_essence_container_data_write_tags;
1763   metadata_class->type = 0x0123;
1764 }
1765 
1766 G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericPackage, mxf_metadata_generic_package,
1767     MXF_TYPE_METADATA);
1768 
1769 static void
mxf_metadata_generic_package_finalize(GObject * object)1770 mxf_metadata_generic_package_finalize (GObject * object)
1771 {
1772   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (object);
1773 
1774   g_free (self->name);
1775   self->name = NULL;
1776   g_free (self->tracks_uids);
1777   self->tracks_uids = NULL;
1778 
1779   g_free (self->tracks);
1780   self->tracks = NULL;
1781 
1782   G_OBJECT_CLASS (mxf_metadata_generic_package_parent_class)->finalize (object);
1783 }
1784 
1785 static gboolean
mxf_metadata_generic_package_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)1786 mxf_metadata_generic_package_handle_tag (MXFMetadataBase * metadata,
1787     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
1788     guint tag_size)
1789 {
1790   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (metadata);
1791   gboolean ret = TRUE;
1792 #ifndef GST_DISABLE_GST_DEBUG
1793   gchar str[96];
1794 #endif
1795 
1796   switch (tag) {
1797     case 0x4401:
1798       if (tag_size != 32)
1799         goto error;
1800       memcpy (&self->package_uid, tag_data, 32);
1801       GST_DEBUG ("  UMID = %s", mxf_umid_to_string (&self->package_uid, str));
1802       break;
1803     case 0x4402:
1804       self->name = mxf_utf16_to_utf8 (tag_data, tag_size);
1805       GST_DEBUG ("  name = %s", GST_STR_NULL (self->name));
1806       break;
1807     case 0x4405:
1808       if (!mxf_timestamp_parse (&self->package_creation_date,
1809               tag_data, tag_size))
1810         goto error;
1811       GST_DEBUG ("  creation date = %s",
1812           mxf_timestamp_to_string (&self->package_creation_date, str));
1813       break;
1814     case 0x4404:
1815       if (!mxf_timestamp_parse (&self->package_modified_date,
1816               tag_data, tag_size))
1817         goto error;
1818       GST_DEBUG ("  modification date = %s",
1819           mxf_timestamp_to_string (&self->package_modified_date, str));
1820       break;
1821     case 0x4403:
1822       if (!mxf_uuid_array_parse (&self->tracks_uids, &self->n_tracks, tag_data,
1823               tag_size))
1824         goto error;
1825 
1826       GST_DEBUG ("  number of tracks = %u", self->n_tracks);
1827 #ifndef GST_DISABLE_GST_DEBUG
1828       {
1829         guint i;
1830         for (i = 0; i < self->n_tracks; i++) {
1831           GST_DEBUG ("  track %u = %s", i,
1832               mxf_uuid_to_string (&self->tracks_uids[i], str));
1833         }
1834       }
1835 #endif
1836       break;
1837     default:
1838       ret =
1839           MXF_METADATA_BASE_CLASS
1840           (mxf_metadata_generic_package_parent_class)->handle_tag (metadata,
1841           primer, tag, tag_data, tag_size);
1842       break;
1843   }
1844 
1845   return ret;
1846 
1847 error:
1848 
1849   GST_ERROR ("Invalid generic package local tag 0x%04x of size %u", tag,
1850       tag_size);
1851 
1852   return FALSE;
1853 }
1854 
1855 static gboolean
mxf_metadata_generic_package_resolve(MXFMetadataBase * m,GHashTable * metadata)1856 mxf_metadata_generic_package_resolve (MXFMetadataBase * m,
1857     GHashTable * metadata)
1858 {
1859   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
1860   MXFMetadataBase *current = NULL;
1861   guint i;
1862   gboolean have_track = FALSE;
1863 #ifndef GST_DISABLE_GST_DEBUG
1864   gchar str[48];
1865 #endif
1866 
1867   if (self->tracks)
1868     memset (self->tracks, 0, sizeof (gpointer) * self->n_tracks);
1869   else
1870     self->tracks = g_new0 (MXFMetadataTrack *, self->n_tracks);
1871   for (i = 0; i < self->n_tracks; i++) {
1872     current = g_hash_table_lookup (metadata, &self->tracks_uids[i]);
1873     if (current && MXF_IS_METADATA_TRACK (current)) {
1874       if (mxf_metadata_base_resolve (current, metadata)) {
1875         MXFMetadataTrack *track = MXF_METADATA_TRACK (current);
1876 
1877         self->tracks[i] = track;
1878         have_track = TRUE;
1879         if ((track->type & 0xf0) == 0x10)
1880           self->n_timecode_tracks++;
1881         else if ((track->type & 0xf0) == 0x20)
1882           self->n_metadata_tracks++;
1883         else if ((track->type & 0xf0) == 0x30)
1884           self->n_essence_tracks++;
1885         else if ((track->type & 0xf0) == 0x40)
1886           self->n_other_tracks++;
1887       } else {
1888         GST_ERROR ("Track %s couldn't be resolved",
1889             mxf_uuid_to_string (&self->tracks_uids[i], str));
1890       }
1891     } else {
1892       GST_ERROR ("Track %s not found",
1893           mxf_uuid_to_string (&self->tracks_uids[i], str));
1894     }
1895   }
1896 
1897   if (!have_track) {
1898     GST_ERROR ("Couldn't resolve a track");
1899     return FALSE;
1900   }
1901 
1902   return
1903       MXF_METADATA_BASE_CLASS
1904       (mxf_metadata_generic_package_parent_class)->resolve (m, metadata);
1905 }
1906 
1907 static GstStructure *
mxf_metadata_generic_package_to_structure(MXFMetadataBase * m)1908 mxf_metadata_generic_package_to_structure (MXFMetadataBase * m)
1909 {
1910   GstStructure *ret =
1911       MXF_METADATA_BASE_CLASS
1912       (mxf_metadata_generic_package_parent_class)->to_structure (m);
1913   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
1914   guint i;
1915   gchar str[96];
1916 
1917   mxf_umid_to_string (&self->package_uid, str);
1918   gst_structure_id_set (ret, MXF_QUARK (PACKAGE_UID), G_TYPE_STRING, str, NULL);
1919 
1920   if (self->name)
1921     gst_structure_id_set (ret, MXF_QUARK (NAME), G_TYPE_STRING, self->name,
1922         NULL);
1923 
1924   if (!mxf_timestamp_is_unknown (&self->package_creation_date)) {
1925     mxf_timestamp_to_string (&self->package_creation_date, str);
1926     gst_structure_id_set (ret, MXF_QUARK (PACKAGE_CREATION_DATE), G_TYPE_STRING,
1927         str, NULL);
1928   }
1929 
1930   if (!mxf_timestamp_is_unknown (&self->package_modified_date)) {
1931     mxf_timestamp_to_string (&self->package_modified_date, str);
1932     gst_structure_id_set (ret, MXF_QUARK (PACKAGE_MODIFIED_DATE), G_TYPE_STRING,
1933         str, NULL);
1934   }
1935 
1936   if (self->n_tracks > 0) {
1937     GValue arr = { 0, }
1938     , val = {
1939     0,};
1940 
1941     g_value_init (&arr, GST_TYPE_ARRAY);
1942 
1943     for (i = 0; i < self->n_tracks; i++) {
1944       GstStructure *s;
1945 
1946       if (self->tracks[i] == NULL)
1947         continue;
1948 
1949       g_value_init (&val, GST_TYPE_STRUCTURE);
1950 
1951       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->tracks[i]));
1952       gst_value_set_structure (&val, s);
1953       gst_structure_free (s);
1954       gst_value_array_append_value (&arr, &val);
1955       g_value_unset (&val);
1956     }
1957 
1958     if (gst_value_array_get_size (&arr) > 0)
1959       gst_structure_id_set_value (ret, MXF_QUARK (TRACKS), &arr);
1960 
1961     g_value_unset (&arr);
1962   }
1963 
1964   return ret;
1965 }
1966 
1967 static GList *
mxf_metadata_generic_package_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)1968 mxf_metadata_generic_package_write_tags (MXFMetadataBase * m,
1969     MXFPrimerPack * primer)
1970 {
1971   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
1972   GList *ret =
1973       MXF_METADATA_BASE_CLASS
1974       (mxf_metadata_generic_package_parent_class)->write_tags (m, primer);
1975   MXFLocalTag *t;
1976 
1977   t = g_slice_new0 (MXFLocalTag);
1978   memcpy (&t->ul, MXF_UL (PACKAGE_UID), 16);
1979   t->size = 32;
1980   t->data = g_slice_alloc (t->size);
1981   t->g_slice = TRUE;
1982   memcpy (t->data, &self->package_uid, 32);
1983   mxf_primer_pack_add_mapping (primer, 0x4401, &t->ul);
1984   ret = g_list_prepend (ret, t);
1985 
1986   if (self->name) {
1987     t = g_slice_new0 (MXFLocalTag);
1988     memcpy (&t->ul, MXF_UL (PACKAGE_NAME), 16);
1989     t->data = mxf_utf8_to_utf16 (self->name, &t->size);
1990     mxf_primer_pack_add_mapping (primer, 0x4402, &t->ul);
1991     ret = g_list_prepend (ret, t);
1992   }
1993 
1994   t = g_slice_new0 (MXFLocalTag);
1995   memcpy (&t->ul, MXF_UL (PACKAGE_CREATION_DATE), 16);
1996   t->size = 8;
1997   t->data = g_slice_alloc (t->size);
1998   t->g_slice = TRUE;
1999   mxf_timestamp_write (&self->package_creation_date, t->data);
2000   mxf_primer_pack_add_mapping (primer, 0x4405, &t->ul);
2001   ret = g_list_prepend (ret, t);
2002 
2003   t = g_slice_new0 (MXFLocalTag);
2004   memcpy (&t->ul, MXF_UL (PACKAGE_MODIFIED_DATE), 16);
2005   t->size = 8;
2006   t->data = g_slice_alloc (t->size);
2007   t->g_slice = TRUE;
2008   mxf_timestamp_write (&self->package_modified_date, t->data);
2009   mxf_primer_pack_add_mapping (primer, 0x4404, &t->ul);
2010   ret = g_list_prepend (ret, t);
2011 
2012   if (self->tracks) {
2013     guint i;
2014 
2015     t = g_slice_new0 (MXFLocalTag);
2016     memcpy (&t->ul, MXF_UL (TRACKS), 16);
2017     t->size = 8 + 16 * self->n_tracks;
2018     t->data = g_slice_alloc0 (t->size);
2019     t->g_slice = TRUE;
2020     GST_WRITE_UINT32_BE (t->data, self->n_tracks);
2021     GST_WRITE_UINT32_BE (t->data + 4, 16);
2022     for (i = 0; i < self->n_tracks; i++) {
2023       if (!self->tracks[i])
2024         continue;
2025 
2026       memcpy (t->data + 8 + 16 * i,
2027           &MXF_METADATA_BASE (self->tracks[i])->instance_uid, 16);
2028     }
2029     mxf_primer_pack_add_mapping (primer, 0x4403, &t->ul);
2030     ret = g_list_prepend (ret, t);
2031   }
2032 
2033   return ret;
2034 }
2035 
2036 static void
mxf_metadata_generic_package_init(MXFMetadataGenericPackage * self)2037 mxf_metadata_generic_package_init (MXFMetadataGenericPackage * self)
2038 {
2039 
2040 }
2041 
2042 static void
mxf_metadata_generic_package_class_init(MXFMetadataGenericPackageClass * klass)2043 mxf_metadata_generic_package_class_init (MXFMetadataGenericPackageClass * klass)
2044 {
2045   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2046   GObjectClass *object_class = (GObjectClass *) klass;
2047 
2048   object_class->finalize = mxf_metadata_generic_package_finalize;
2049   metadata_base_class->handle_tag = mxf_metadata_generic_package_handle_tag;
2050   metadata_base_class->resolve = mxf_metadata_generic_package_resolve;
2051   metadata_base_class->to_structure = mxf_metadata_generic_package_to_structure;
2052   metadata_base_class->write_tags = mxf_metadata_generic_package_write_tags;
2053 }
2054 
2055 G_DEFINE_TYPE (MXFMetadataMaterialPackage, mxf_metadata_material_package,
2056     MXF_TYPE_METADATA_GENERIC_PACKAGE);
2057 
2058 static gboolean
mxf_metadata_material_package_resolve(MXFMetadataBase * m,GHashTable * metadata)2059 mxf_metadata_material_package_resolve (MXFMetadataBase * m,
2060     GHashTable * metadata)
2061 {
2062   gboolean ret =
2063       MXF_METADATA_BASE_CLASS
2064       (mxf_metadata_material_package_parent_class)->resolve (m, metadata);
2065   MXFMetadataGenericPackage *self = MXF_METADATA_GENERIC_PACKAGE (m);
2066   guint i;
2067   guint ntracks = 0;
2068 
2069   if (!ret)
2070     return ret;
2071 
2072   for (i = 0; i < self->n_tracks; i++) {
2073     MXFMetadataTrack *track = self->tracks[i];
2074     MXFMetadataSequence *sequence;
2075     guint j;
2076 
2077     if (!track)
2078       continue;
2079 
2080     sequence = track->sequence;
2081 
2082     if (!sequence || !sequence->structural_components)
2083       continue;
2084 
2085     for (j = 0; j < sequence->n_structural_components; j++) {
2086       MXFMetadataSourceClip *sc;
2087       MXFMetadataTimelineTrack *st = NULL;
2088       guint k;
2089 
2090       if (!sequence->structural_components[j]
2091           || !MXF_IS_METADATA_SOURCE_CLIP (sequence->structural_components[j]))
2092         continue;
2093 
2094       sc = MXF_METADATA_SOURCE_CLIP (sequence->structural_components[j]);
2095 
2096       if (!sc->source_package) {
2097         GST_ERROR ("Material package track %u without resolved source package",
2098             i);
2099         track = NULL;
2100         break;
2101       }
2102 
2103       if (!mxf_metadata_base_resolve (MXF_METADATA_BASE (sc->source_package),
2104               metadata)) {
2105         GST_ERROR ("Couldn't resolve source package for track %u", i);
2106         track = NULL;
2107         break;
2108       }
2109 
2110       sc->source_package->top_level = TRUE;
2111       for (k = 0; k < sc->source_package->parent.n_tracks; k++) {
2112         MXFMetadataTimelineTrack *tmp;
2113 
2114         if (!sc->source_package->parent.tracks[k] ||
2115             !MXF_IS_METADATA_TIMELINE_TRACK (sc->source_package->parent.
2116                 tracks[k]))
2117           continue;
2118 
2119         tmp =
2120             MXF_METADATA_TIMELINE_TRACK (sc->source_package->parent.tracks[k]);
2121         if (tmp->parent.track_id == sc->source_track_id) {
2122           st = tmp;
2123           break;
2124         }
2125       }
2126 
2127       if (!st) {
2128         GST_ERROR ("Material package track %u without resolved source track",
2129             i);
2130         track = NULL;
2131       }
2132     }
2133 
2134     if (track)
2135       ntracks++;
2136     else
2137       self->tracks[i] = NULL;
2138   }
2139 
2140   if (ntracks == 0) {
2141     GST_ERROR ("No tracks could be resolved");
2142     return FALSE;
2143   } else if (ntracks != self->n_tracks) {
2144     GST_WARNING ("Not all tracks could be resolved");
2145   }
2146 
2147   return TRUE;
2148 }
2149 
2150 static void
mxf_metadata_material_package_init(MXFMetadataMaterialPackage * self)2151 mxf_metadata_material_package_init (MXFMetadataMaterialPackage * self)
2152 {
2153 }
2154 
2155 static void
mxf_metadata_material_package_class_init(MXFMetadataMaterialPackageClass * klass)2156 mxf_metadata_material_package_class_init (MXFMetadataMaterialPackageClass *
2157     klass)
2158 {
2159   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2160   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2161 
2162   metadata_base_class->resolve = mxf_metadata_material_package_resolve;
2163   metadata_base_class->name_quark = MXF_QUARK (MATERIAL_PACKAGE);
2164   metadata_class->type = 0x0136;
2165 }
2166 
2167 G_DEFINE_TYPE (MXFMetadataSourcePackage, mxf_metadata_source_package,
2168     MXF_TYPE_METADATA_GENERIC_PACKAGE);
2169 
2170 static gboolean
mxf_metadata_source_package_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2171 mxf_metadata_source_package_handle_tag (MXFMetadataBase * metadata,
2172     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2173     guint tag_size)
2174 {
2175   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (metadata);
2176   gboolean ret = TRUE;
2177 #ifndef GST_DISABLE_GST_DEBUG
2178   gchar str[48];
2179 #endif
2180 
2181   switch (tag) {
2182     case 0x4701:
2183       if (tag_size != 16)
2184         goto error;
2185 
2186       memcpy (&self->descriptor_uid, tag_data, 16);
2187       GST_DEBUG ("  descriptor = %s",
2188           mxf_uuid_to_string (&self->descriptor_uid, str));
2189       break;
2190     default:
2191       ret =
2192           MXF_METADATA_BASE_CLASS
2193           (mxf_metadata_source_package_parent_class)->handle_tag (metadata,
2194           primer, tag, tag_data, tag_size);
2195       break;
2196   }
2197 
2198   return ret;
2199 
2200 error:
2201 
2202   GST_ERROR ("Invalid source package local tag 0x%04x of size %u", tag,
2203       tag_size);
2204 
2205   return FALSE;
2206 }
2207 
2208 static gboolean
mxf_metadata_source_package_resolve(MXFMetadataBase * m,GHashTable * metadata)2209 mxf_metadata_source_package_resolve (MXFMetadataBase * m, GHashTable * metadata)
2210 {
2211   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2212   MXFMetadataGenericPackage *package = MXF_METADATA_GENERIC_PACKAGE (m);
2213   MXFMetadataBase *current = NULL;
2214   guint i;
2215   gboolean ret;
2216   MXFMetadataFileDescriptor *d;
2217 #ifndef GST_DISABLE_GST_DEBUG
2218   gchar str[48];
2219 #endif
2220 
2221   if (mxf_uuid_is_zero (&self->descriptor_uid))
2222     return
2223         MXF_METADATA_BASE_CLASS
2224         (mxf_metadata_source_package_parent_class)->resolve (m, metadata);
2225 
2226   current = g_hash_table_lookup (metadata, &self->descriptor_uid);
2227   if (!current) {
2228     GST_ERROR ("Descriptor %s not found",
2229         mxf_uuid_to_string (&self->descriptor_uid, str));
2230     return FALSE;
2231   }
2232 
2233   if (!mxf_metadata_base_resolve (MXF_METADATA_BASE (current), metadata)) {
2234     GST_ERROR ("Couldn't resolve descriptor %s",
2235         mxf_uuid_to_string (&self->descriptor_uid, str));
2236     return FALSE;
2237   }
2238 
2239   self->descriptor = MXF_METADATA_GENERIC_DESCRIPTOR (current);
2240 
2241   ret =
2242       MXF_METADATA_BASE_CLASS
2243       (mxf_metadata_source_package_parent_class)->resolve (m, metadata);
2244 
2245   if (!MXF_IS_METADATA_FILE_DESCRIPTOR (self->descriptor))
2246     return ret;
2247 
2248   d = MXF_METADATA_FILE_DESCRIPTOR (current);
2249 
2250   for (i = 0; i < package->n_tracks; i++) {
2251     if (!package->tracks[i])
2252       continue;
2253 
2254     if (!MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (d)) {
2255       if (d->linked_track_id == package->tracks[i]->track_id ||
2256           (d->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2257               (package->tracks[i]->type & 0xf0) == 0x30)) {
2258         g_free (package->tracks[i]->descriptor);
2259         package->tracks[i]->descriptor =
2260             g_new0 (MXFMetadataFileDescriptor *, 1);
2261         package->tracks[i]->descriptor[0] = d;
2262         package->tracks[i]->n_descriptor = 1;
2263         break;
2264       }
2265     } else {
2266       guint n_descriptor = 0, j, k = 0;
2267       MXFMetadataMultipleDescriptor *md = MXF_METADATA_MULTIPLE_DESCRIPTOR (d);
2268 
2269       for (j = 0; j < md->n_sub_descriptors; j++) {
2270         MXFMetadataFileDescriptor *fd;
2271 
2272         if (!md->sub_descriptors[j] ||
2273             !MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]))
2274           continue;
2275 
2276         fd = MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]);
2277 
2278         if (fd->linked_track_id == package->tracks[i]->track_id ||
2279             (fd->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2280                 (package->tracks[i]->type & 0xf0) == 0x30))
2281           n_descriptor++;
2282       }
2283 
2284       g_free (package->tracks[i]->descriptor);
2285       package->tracks[i]->descriptor =
2286           g_new0 (MXFMetadataFileDescriptor *, n_descriptor);
2287       package->tracks[i]->n_descriptor = n_descriptor;
2288 
2289       for (j = 0; j < md->n_sub_descriptors; j++) {
2290         MXFMetadataFileDescriptor *fd;
2291 
2292         if (!md->sub_descriptors[j] ||
2293             !MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]))
2294           continue;
2295 
2296         fd = MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]);
2297 
2298         if (fd->linked_track_id == package->tracks[i]->track_id ||
2299             (fd->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2300                 (package->tracks[i]->type & 0xf0) == 0x30)) {
2301           package->tracks[i]->descriptor[k] = fd;
2302           k++;
2303         }
2304       }
2305     }
2306   }
2307 
2308   return ret;
2309 }
2310 
2311 static GstStructure *
mxf_metadata_source_package_to_structure(MXFMetadataBase * m)2312 mxf_metadata_source_package_to_structure (MXFMetadataBase * m)
2313 {
2314   GstStructure *ret =
2315       MXF_METADATA_BASE_CLASS
2316       (mxf_metadata_source_package_parent_class)->to_structure (m);
2317   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2318   GstStructure *s;
2319 
2320   if (!self->descriptor)
2321     return ret;
2322 
2323   s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->descriptor));
2324   gst_structure_id_set (ret, MXF_QUARK (DESCRIPTOR), GST_TYPE_STRUCTURE, s,
2325       NULL);
2326   gst_structure_free (s);
2327 
2328   return ret;
2329 }
2330 
2331 static GList *
mxf_metadata_source_package_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2332 mxf_metadata_source_package_write_tags (MXFMetadataBase * m,
2333     MXFPrimerPack * primer)
2334 {
2335   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2336   GList *ret =
2337       MXF_METADATA_BASE_CLASS
2338       (mxf_metadata_source_package_parent_class)->write_tags (m, primer);
2339   MXFLocalTag *t;
2340 
2341   if (self->descriptor) {
2342     t = g_slice_new0 (MXFLocalTag);
2343     memcpy (&t->ul, MXF_UL (DESCRIPTOR), 16);
2344     t->size = 16;
2345     t->data = g_slice_alloc (t->size);
2346     t->g_slice = TRUE;
2347     memcpy (t->data, &MXF_METADATA_BASE (self->descriptor)->instance_uid, 16);
2348     mxf_primer_pack_add_mapping (primer, 0x4701, &t->ul);
2349     ret = g_list_prepend (ret, t);
2350   }
2351 
2352   return ret;
2353 }
2354 
2355 static void
mxf_metadata_source_package_init(MXFMetadataSourcePackage * self)2356 mxf_metadata_source_package_init (MXFMetadataSourcePackage * self)
2357 {
2358 
2359 }
2360 
2361 static void
mxf_metadata_source_package_class_init(MXFMetadataSourcePackageClass * klass)2362 mxf_metadata_source_package_class_init (MXFMetadataSourcePackageClass * klass)
2363 {
2364   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2365   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2366 
2367   metadata_base_class->handle_tag = mxf_metadata_source_package_handle_tag;
2368   metadata_base_class->resolve = mxf_metadata_source_package_resolve;
2369   metadata_base_class->name_quark = MXF_QUARK (SOURCE_PACKAGE);
2370   metadata_base_class->to_structure = mxf_metadata_source_package_to_structure;
2371   metadata_base_class->write_tags = mxf_metadata_source_package_write_tags;
2372   metadata_class->type = 0x0137;
2373 }
2374 
2375 G_DEFINE_ABSTRACT_TYPE (MXFMetadataTrack, mxf_metadata_track,
2376     MXF_TYPE_METADATA);
2377 
2378 static void
mxf_metadata_track_finalize(GObject * object)2379 mxf_metadata_track_finalize (GObject * object)
2380 {
2381   MXFMetadataTrack *self = MXF_METADATA_TRACK (object);
2382 
2383   g_free (self->track_name);
2384   self->track_name = NULL;
2385   g_free (self->descriptor);
2386   self->descriptor = NULL;
2387 
2388   G_OBJECT_CLASS (mxf_metadata_track_parent_class)->finalize (object);
2389 }
2390 
2391 static gboolean
mxf_metadata_track_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2392 mxf_metadata_track_handle_tag (MXFMetadataBase * metadata,
2393     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2394     guint tag_size)
2395 {
2396   MXFMetadataTrack *self = MXF_METADATA_TRACK (metadata);
2397   gboolean ret = TRUE;
2398 #ifndef GST_DISABLE_GST_DEBUG
2399   gchar str[48];
2400 #endif
2401 
2402   switch (tag) {
2403     case 0x4801:
2404       if (tag_size != 4)
2405         goto error;
2406       self->track_id = GST_READ_UINT32_BE (tag_data);
2407       GST_DEBUG ("  track id = %u", self->track_id);
2408       break;
2409     case 0x4804:
2410       if (tag_size != 4)
2411         goto error;
2412       self->track_number = GST_READ_UINT32_BE (tag_data);
2413       GST_DEBUG ("  track number = %u", self->track_number);
2414       break;
2415     case 0x4802:
2416       self->track_name = mxf_utf16_to_utf8 (tag_data, tag_size);
2417       GST_DEBUG ("  track name = %s", GST_STR_NULL (self->track_name));
2418       break;
2419     case 0x4803:
2420       if (tag_size != 16)
2421         goto error;
2422       memcpy (&self->sequence_uid, tag_data, 16);
2423       GST_DEBUG ("  sequence uid = %s",
2424           mxf_uuid_to_string (&self->sequence_uid, str));
2425       break;
2426     default:
2427       ret =
2428           MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->handle_tag
2429           (metadata, primer, tag, tag_data, tag_size);
2430       break;
2431   }
2432 
2433   return ret;
2434 
2435 error:
2436 
2437   GST_ERROR ("Invalid track local tag 0x%04x of size %u", tag, tag_size);
2438 
2439   return FALSE;
2440 }
2441 
2442 static gboolean
mxf_metadata_track_resolve(MXFMetadataBase * m,GHashTable * metadata)2443 mxf_metadata_track_resolve (MXFMetadataBase * m, GHashTable * metadata)
2444 {
2445   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2446   MXFMetadataBase *current = NULL;
2447   guint i;
2448 #ifndef GST_DISABLE_GST_DEBUG
2449   gchar str[48];
2450 #endif
2451 
2452   current = g_hash_table_lookup (metadata, &self->sequence_uid);
2453   if (current && MXF_IS_METADATA_SEQUENCE (current)) {
2454     if (mxf_metadata_base_resolve (current, metadata)) {
2455       self->sequence = MXF_METADATA_SEQUENCE (current);
2456     } else {
2457       GST_ERROR ("Couldn't resolve sequence %s",
2458           mxf_uuid_to_string (&self->sequence_uid, str));
2459       return FALSE;
2460     }
2461   } else {
2462     GST_ERROR ("Couldn't find sequence %s",
2463         mxf_uuid_to_string (&self->sequence_uid, str));
2464     return FALSE;
2465   }
2466 
2467   self->type =
2468       mxf_metadata_track_identifier_parse (&self->sequence->data_definition);
2469   if (self->type == MXF_METADATA_TRACK_UNKNOWN) {
2470     MXFMetadataSequence *sequence = self->sequence;
2471 
2472     for (i = 0; i < sequence->n_structural_components; i++) {
2473       MXFMetadataStructuralComponent *component =
2474           sequence->structural_components[i];
2475 
2476       if (!component)
2477         continue;
2478 
2479       self->type =
2480           mxf_metadata_track_identifier_parse (&component->data_definition);
2481       if (self->type != MXF_METADATA_TRACK_UNKNOWN)
2482         break;
2483     }
2484   }
2485 
2486   return MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->resolve (m,
2487       metadata);
2488 }
2489 
2490 static GstStructure *
mxf_metadata_track_to_structure(MXFMetadataBase * m)2491 mxf_metadata_track_to_structure (MXFMetadataBase * m)
2492 {
2493   GstStructure *ret =
2494       MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->to_structure
2495       (m);
2496   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2497 
2498   gst_structure_id_set (ret, MXF_QUARK (TRACK_ID), G_TYPE_UINT, self->track_id,
2499       MXF_QUARK (TRACK_NUMBER), G_TYPE_UINT, self->track_number, NULL);
2500 
2501   if (self->track_name)
2502     gst_structure_id_set (ret, MXF_QUARK (TRACK_NAME), G_TYPE_STRING,
2503         self->track_name, NULL);
2504 
2505   if (self->sequence) {
2506     GstStructure *s =
2507         mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->sequence));
2508 
2509     gst_structure_id_set (ret, MXF_QUARK (SEQUENCE), GST_TYPE_STRUCTURE, s,
2510         NULL);
2511     gst_structure_free (s);
2512   }
2513 
2514 
2515   return ret;
2516 }
2517 
2518 static GList *
mxf_metadata_track_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2519 mxf_metadata_track_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
2520 {
2521   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2522   GList *ret =
2523       MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->write_tags (m,
2524       primer);
2525   MXFLocalTag *t;
2526 
2527   t = g_slice_new0 (MXFLocalTag);
2528   memcpy (&t->ul, MXF_UL (TRACK_ID), 16);
2529   t->size = 4;
2530   t->data = g_slice_alloc (t->size);
2531   t->g_slice = TRUE;
2532   GST_WRITE_UINT32_BE (t->data, self->track_id);
2533   mxf_primer_pack_add_mapping (primer, 0x4801, &t->ul);
2534   ret = g_list_prepend (ret, t);
2535 
2536   t = g_slice_new0 (MXFLocalTag);
2537   memcpy (&t->ul, MXF_UL (TRACK_NUMBER), 16);
2538   t->size = 4;
2539   t->data = g_slice_alloc (t->size);
2540   t->g_slice = TRUE;
2541   GST_WRITE_UINT32_BE (t->data, self->track_number);
2542   mxf_primer_pack_add_mapping (primer, 0x4804, &t->ul);
2543   ret = g_list_prepend (ret, t);
2544 
2545   if (self->track_name) {
2546     t = g_slice_new0 (MXFLocalTag);
2547     memcpy (&t->ul, MXF_UL (TRACK_NAME), 16);
2548     t->data = mxf_utf8_to_utf16 (self->track_name, &t->size);
2549     mxf_primer_pack_add_mapping (primer, 0x4802, &t->ul);
2550     ret = g_list_prepend (ret, t);
2551   }
2552 
2553   t = g_slice_new0 (MXFLocalTag);
2554   memcpy (&t->ul, MXF_UL (SEQUENCE), 16);
2555   t->size = 16;
2556   t->data = g_slice_alloc (t->size);
2557   t->g_slice = TRUE;
2558   memcpy (t->data, &MXF_METADATA_BASE (self->sequence)->instance_uid, 16);
2559   mxf_primer_pack_add_mapping (primer, 0x4803, &t->ul);
2560   ret = g_list_prepend (ret, t);
2561 
2562   return ret;
2563 }
2564 
2565 static void
mxf_metadata_track_init(MXFMetadataTrack * self)2566 mxf_metadata_track_init (MXFMetadataTrack * self)
2567 {
2568 
2569 }
2570 
2571 static void
mxf_metadata_track_class_init(MXFMetadataTrackClass * klass)2572 mxf_metadata_track_class_init (MXFMetadataTrackClass * klass)
2573 {
2574   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2575   GObjectClass *object_class = (GObjectClass *) klass;
2576 
2577   object_class->finalize = mxf_metadata_track_finalize;
2578   metadata_base_class->handle_tag = mxf_metadata_track_handle_tag;
2579   metadata_base_class->resolve = mxf_metadata_track_resolve;
2580   metadata_base_class->to_structure = mxf_metadata_track_to_structure;
2581   metadata_base_class->write_tags = mxf_metadata_track_write_tags;
2582 }
2583 
2584 /* SMPTE RP224 */
2585 static const struct
2586 {
2587   const MXFUL *ul;
2588   const MXFMetadataTrackType type;
2589 } mxf_metadata_track_identifier[] = {
2590   {
2591   MXF_UL (TRACK_TIMECODE_12M_INACTIVE),
2592         MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE}, {
2593   MXF_UL (TRACK_TIMECODE_12M_ACTIVE), MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE}, {
2594   MXF_UL (TRACK_TIMECODE_309M), MXF_METADATA_TRACK_TIMECODE_309M}, {
2595   MXF_UL (TRACK_METADATA), MXF_METADATA_TRACK_METADATA}, {
2596   MXF_UL (TRACK_PICTURE_ESSENCE), MXF_METADATA_TRACK_PICTURE_ESSENCE}, {
2597   MXF_UL (TRACK_SOUND_ESSENCE), MXF_METADATA_TRACK_SOUND_ESSENCE}, {
2598   MXF_UL (TRACK_DATA_ESSENCE), MXF_METADATA_TRACK_DATA_ESSENCE}, {
2599   MXF_UL (TRACK_AUXILIARY_DATA), MXF_METADATA_TRACK_AUXILIARY_DATA}, {
2600   MXF_UL (TRACK_PARSED_TEXT), MXF_METADATA_TRACK_PARSED_TEXT},
2601       /* Avid video? */
2602   {
2603   MXF_UL (TRACK_AVID_PICTURE_ESSENCE), MXF_METADATA_TRACK_PICTURE_ESSENCE}
2604 };
2605 
2606 MXFMetadataTrackType
mxf_metadata_track_identifier_parse(const MXFUL * track_identifier)2607 mxf_metadata_track_identifier_parse (const MXFUL * track_identifier)
2608 {
2609   guint i;
2610 
2611   for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
2612     if (mxf_ul_is_equal (mxf_metadata_track_identifier[i].ul, track_identifier))
2613       return mxf_metadata_track_identifier[i].type;
2614 
2615   return MXF_METADATA_TRACK_UNKNOWN;
2616 }
2617 
2618 const MXFUL *
mxf_metadata_track_identifier_get(MXFMetadataTrackType type)2619 mxf_metadata_track_identifier_get (MXFMetadataTrackType type)
2620 {
2621   guint i;
2622 
2623   for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
2624     if (mxf_metadata_track_identifier[i].type == type)
2625       return mxf_metadata_track_identifier[i].ul;
2626 
2627   return NULL;
2628 }
2629 
2630 G_DEFINE_TYPE (MXFMetadataTimelineTrack, mxf_metadata_timeline_track,
2631     MXF_TYPE_METADATA_TRACK);
2632 
2633 static gboolean
mxf_metadata_timeline_track_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2634 mxf_metadata_timeline_track_handle_tag (MXFMetadataBase * metadata,
2635     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2636     guint tag_size)
2637 {
2638   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (metadata);
2639   gboolean ret = TRUE;
2640 
2641   switch (tag) {
2642     case 0x4b01:
2643       if (!mxf_fraction_parse (&self->edit_rate, tag_data, tag_size))
2644         goto error;
2645       GST_DEBUG ("  edit rate = %d/%d", self->edit_rate.n, self->edit_rate.d);
2646       break;
2647     case 0x4b02:
2648       if (tag_size != 8)
2649         goto error;
2650       self->origin = GST_READ_UINT64_BE (tag_data);
2651       GST_DEBUG ("  origin = %" G_GINT64_FORMAT, self->origin);
2652       break;
2653     default:
2654       ret =
2655           MXF_METADATA_BASE_CLASS
2656           (mxf_metadata_timeline_track_parent_class)->handle_tag (metadata,
2657           primer, tag, tag_data, tag_size);
2658       break;
2659   }
2660 
2661   return ret;
2662 
2663 error:
2664 
2665   GST_ERROR ("Invalid timeline track local tag 0x%04x of size %u", tag,
2666       tag_size);
2667 
2668   return FALSE;
2669 }
2670 
2671 static GstStructure *
mxf_metadata_timeline_track_to_structure(MXFMetadataBase * m)2672 mxf_metadata_timeline_track_to_structure (MXFMetadataBase * m)
2673 {
2674   GstStructure *ret =
2675       MXF_METADATA_BASE_CLASS
2676       (mxf_metadata_timeline_track_parent_class)->to_structure (m);
2677   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (m);
2678 
2679   gst_structure_id_set (ret, MXF_QUARK (EDIT_RATE), GST_TYPE_FRACTION,
2680       self->edit_rate.n, self->edit_rate.d, MXF_QUARK (ORIGIN), G_TYPE_INT64,
2681       self->origin, NULL);
2682 
2683   return ret;
2684 }
2685 
2686 static GList *
mxf_metadata_timeline_track_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2687 mxf_metadata_timeline_track_write_tags (MXFMetadataBase * m,
2688     MXFPrimerPack * primer)
2689 {
2690   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (m);
2691   GList *ret =
2692       MXF_METADATA_BASE_CLASS
2693       (mxf_metadata_timeline_track_parent_class)->write_tags (m, primer);
2694   MXFLocalTag *t;
2695 
2696   t = g_slice_new0 (MXFLocalTag);
2697   memcpy (&t->ul, MXF_UL (EDIT_RATE), 16);
2698   t->size = 8;
2699   t->data = g_slice_alloc (t->size);
2700   t->g_slice = TRUE;
2701   GST_WRITE_UINT32_BE (t->data, self->edit_rate.n);
2702   GST_WRITE_UINT32_BE (t->data + 4, self->edit_rate.d);
2703   mxf_primer_pack_add_mapping (primer, 0x4b01, &t->ul);
2704   ret = g_list_prepend (ret, t);
2705 
2706   t = g_slice_new0 (MXFLocalTag);
2707   memcpy (&t->ul, MXF_UL (ORIGIN), 16);
2708   t->size = 8;
2709   t->data = g_slice_alloc (t->size);
2710   t->g_slice = TRUE;
2711   GST_WRITE_UINT64_BE (t->data, self->origin);
2712   mxf_primer_pack_add_mapping (primer, 0x4b02, &t->ul);
2713   ret = g_list_prepend (ret, t);
2714 
2715   return ret;
2716 }
2717 
2718 static void
mxf_metadata_timeline_track_init(MXFMetadataTimelineTrack * self)2719 mxf_metadata_timeline_track_init (MXFMetadataTimelineTrack * self)
2720 {
2721 
2722 }
2723 
2724 static void
mxf_metadata_timeline_track_class_init(MXFMetadataTimelineTrackClass * klass)2725 mxf_metadata_timeline_track_class_init (MXFMetadataTimelineTrackClass * klass)
2726 {
2727   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2728   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2729 
2730   metadata_base_class->handle_tag = mxf_metadata_timeline_track_handle_tag;
2731   metadata_base_class->name_quark = MXF_QUARK (TIMELINE_TRACK);
2732   metadata_base_class->to_structure = mxf_metadata_timeline_track_to_structure;
2733   metadata_base_class->write_tags = mxf_metadata_timeline_track_write_tags;
2734   metadata_class->type = 0x013b;
2735 }
2736 
2737 G_DEFINE_TYPE (MXFMetadataEventTrack, mxf_metadata_event_track,
2738     MXF_TYPE_METADATA_TRACK);
2739 
2740 static gboolean
mxf_metadata_event_track_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2741 mxf_metadata_event_track_handle_tag (MXFMetadataBase * metadata,
2742     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2743     guint tag_size)
2744 {
2745   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (metadata);
2746   gboolean ret = TRUE;
2747 
2748   switch (tag) {
2749     case 0x4901:
2750       if (!mxf_fraction_parse (&self->event_edit_rate, tag_data, tag_size))
2751         goto error;
2752       GST_DEBUG ("  event edit rate = %d/%d", self->event_edit_rate.n,
2753           self->event_edit_rate.d);
2754       break;
2755     case 0x4902:
2756       if (tag_size != 8)
2757         goto error;
2758       self->event_origin = GST_READ_UINT64_BE (tag_data);
2759       GST_DEBUG ("  event origin = %" G_GINT64_FORMAT, self->event_origin);
2760       break;
2761     default:
2762       ret =
2763           MXF_METADATA_BASE_CLASS
2764           (mxf_metadata_event_track_parent_class)->handle_tag (metadata, primer,
2765           tag, tag_data, tag_size);
2766       break;
2767   }
2768 
2769   return ret;
2770 
2771 error:
2772 
2773   GST_ERROR ("Invalid event track local tag 0x%04x of size %u", tag, tag_size);
2774 
2775   return FALSE;
2776 }
2777 
2778 static GstStructure *
mxf_metadata_event_track_to_structure(MXFMetadataBase * m)2779 mxf_metadata_event_track_to_structure (MXFMetadataBase * m)
2780 {
2781   GstStructure *ret =
2782       MXF_METADATA_BASE_CLASS
2783       (mxf_metadata_event_track_parent_class)->to_structure (m);
2784   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (m);
2785 
2786   gst_structure_id_set (ret, MXF_QUARK (EVENT_EDIT_RATE), GST_TYPE_FRACTION,
2787       self->event_edit_rate.n, self->event_edit_rate.d,
2788       MXF_QUARK (EVENT_ORIGIN), G_TYPE_INT64, self->event_origin, NULL);
2789 
2790   return ret;
2791 }
2792 
2793 static GList *
mxf_metadata_event_track_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2794 mxf_metadata_event_track_write_tags (MXFMetadataBase * m,
2795     MXFPrimerPack * primer)
2796 {
2797   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (m);
2798   GList *ret =
2799       MXF_METADATA_BASE_CLASS
2800       (mxf_metadata_event_track_parent_class)->write_tags (m, primer);
2801   MXFLocalTag *t;
2802 
2803   t = g_slice_new0 (MXFLocalTag);
2804   memcpy (&t->ul, MXF_UL (EVENT_EDIT_RATE), 16);
2805   t->size = 8;
2806   t->data = g_slice_alloc (t->size);
2807   t->g_slice = TRUE;
2808   GST_WRITE_UINT32_BE (t->data, self->event_edit_rate.n);
2809   GST_WRITE_UINT32_BE (t->data + 4, self->event_edit_rate.d);
2810   mxf_primer_pack_add_mapping (primer, 0x4901, &t->ul);
2811   ret = g_list_prepend (ret, t);
2812 
2813   t = g_slice_new0 (MXFLocalTag);
2814   memcpy (&t->ul, MXF_UL (EVENT_ORIGIN), 16);
2815   t->size = 8;
2816   t->data = g_slice_alloc (t->size);
2817   t->g_slice = TRUE;
2818   GST_WRITE_UINT64_BE (t->data, self->event_origin);
2819   mxf_primer_pack_add_mapping (primer, 0x4902, &t->ul);
2820   ret = g_list_prepend (ret, t);
2821 
2822   return ret;
2823 }
2824 
2825 static void
mxf_metadata_event_track_init(MXFMetadataEventTrack * self)2826 mxf_metadata_event_track_init (MXFMetadataEventTrack * self)
2827 {
2828 
2829 }
2830 
2831 static void
mxf_metadata_event_track_class_init(MXFMetadataEventTrackClass * klass)2832 mxf_metadata_event_track_class_init (MXFMetadataEventTrackClass * klass)
2833 {
2834   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2835   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2836 
2837   metadata_base_class->handle_tag = mxf_metadata_event_track_handle_tag;
2838   metadata_base_class->name_quark = MXF_QUARK (EVENT_TRACK);
2839   metadata_base_class->to_structure = mxf_metadata_event_track_to_structure;
2840   metadata_base_class->write_tags = mxf_metadata_event_track_write_tags;
2841   metadata_class->type = 0x0139;
2842 }
2843 
2844 G_DEFINE_TYPE (MXFMetadataStaticTrack, mxf_metadata_static_track,
2845     MXF_TYPE_METADATA_TRACK);
2846 
2847 static void
mxf_metadata_static_track_init(MXFMetadataStaticTrack * self)2848 mxf_metadata_static_track_init (MXFMetadataStaticTrack * self)
2849 {
2850 }
2851 
2852 static void
mxf_metadata_static_track_class_init(MXFMetadataStaticTrackClass * klass)2853 mxf_metadata_static_track_class_init (MXFMetadataStaticTrackClass * klass)
2854 {
2855   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2856   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2857 
2858   metadata_base_class->name_quark = MXF_QUARK (STATIC_TRACK);
2859   metadata_class->type = 0x013a;
2860 }
2861 
2862 G_DEFINE_TYPE (MXFMetadataSequence, mxf_metadata_sequence, MXF_TYPE_METADATA);
2863 
2864 static void
mxf_metadata_sequence_finalize(GObject * object)2865 mxf_metadata_sequence_finalize (GObject * object)
2866 {
2867   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (object);
2868 
2869   g_free (self->structural_components_uids);
2870   self->structural_components_uids = NULL;
2871   g_free (self->structural_components);
2872   self->structural_components = NULL;
2873 
2874   G_OBJECT_CLASS (mxf_metadata_sequence_parent_class)->finalize (object);
2875 }
2876 
2877 static gboolean
mxf_metadata_sequence_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2878 mxf_metadata_sequence_handle_tag (MXFMetadataBase * metadata,
2879     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2880     guint tag_size)
2881 {
2882   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (metadata);
2883   gboolean ret = TRUE;
2884 #ifndef GST_DISABLE_GST_DEBUG
2885   gchar str[48];
2886 #endif
2887 
2888   switch (tag) {
2889     case 0x0201:
2890       if (tag_size != 16)
2891         goto error;
2892       memcpy (&self->data_definition, tag_data, 16);
2893       GST_DEBUG ("  data definition = %s",
2894           mxf_ul_to_string (&self->data_definition, str));
2895       break;
2896     case 0x0202:
2897       if (tag_size != 8)
2898         goto error;
2899       self->duration = GST_READ_UINT64_BE (tag_data);
2900       GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
2901       break;
2902     case 0x1001:
2903       if (!mxf_uuid_array_parse (&self->structural_components_uids,
2904               &self->n_structural_components, tag_data, tag_size))
2905         goto error;
2906 
2907       GST_DEBUG ("  number of structural components = %u",
2908           self->n_structural_components);
2909 #ifndef GST_DISABLE_GST_DEBUG
2910       {
2911         guint i;
2912         for (i = 0; i < self->n_structural_components; i++) {
2913           GST_DEBUG ("  structural component %u = %s", i,
2914               mxf_uuid_to_string (&self->structural_components_uids[i], str));
2915         }
2916       }
2917 #endif
2918       break;
2919     default:
2920       ret =
2921           MXF_METADATA_BASE_CLASS
2922           (mxf_metadata_sequence_parent_class)->handle_tag (metadata, primer,
2923           tag, tag_data, tag_size);
2924       break;
2925   }
2926 
2927   return ret;
2928 
2929 error:
2930 
2931   GST_ERROR ("Invalid sequence local tag 0x%04x of size %u", tag, tag_size);
2932 
2933   return FALSE;
2934 }
2935 
2936 static gboolean
mxf_metadata_sequence_resolve(MXFMetadataBase * m,GHashTable * metadata)2937 mxf_metadata_sequence_resolve (MXFMetadataBase * m, GHashTable * metadata)
2938 {
2939   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2940   MXFMetadataBase *current = NULL;
2941   guint i;
2942 #ifndef GST_DISABLE_GST_DEBUG
2943   gchar str[48];
2944 #endif
2945 
2946   if (self->structural_components)
2947     memset (self->structural_components, 0,
2948         sizeof (gpointer) * self->n_structural_components);
2949   else
2950     self->structural_components =
2951         g_new0 (MXFMetadataStructuralComponent *,
2952         self->n_structural_components);
2953   for (i = 0; i < self->n_structural_components; i++) {
2954     current =
2955         g_hash_table_lookup (metadata, &self->structural_components_uids[i]);
2956     if (current && MXF_IS_METADATA_STRUCTURAL_COMPONENT (current)) {
2957       if (mxf_metadata_base_resolve (current, metadata)) {
2958         self->structural_components[i] =
2959             MXF_METADATA_STRUCTURAL_COMPONENT (current);
2960       } else {
2961         GST_ERROR ("Couldn't resolve structural component %s",
2962             mxf_uuid_to_string (&self->structural_components_uids[i], str));
2963         return FALSE;
2964       }
2965     } else {
2966       GST_ERROR ("Structural component %s not found",
2967           mxf_uuid_to_string (&self->structural_components_uids[i], str));
2968       return FALSE;
2969     }
2970   }
2971 
2972   return
2973       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->resolve (m,
2974       metadata);
2975 
2976 }
2977 
2978 static GstStructure *
mxf_metadata_sequence_to_structure(MXFMetadataBase * m)2979 mxf_metadata_sequence_to_structure (MXFMetadataBase * m)
2980 {
2981   GstStructure *ret =
2982       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->to_structure
2983       (m);
2984   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2985   guint i;
2986   gchar str[48];
2987 
2988   mxf_ul_to_string (&self->data_definition, str);
2989   gst_structure_id_set (ret, MXF_QUARK (DATA_DEFINITION), G_TYPE_STRING, str,
2990       MXF_QUARK (DURATION), G_TYPE_INT64, self->duration, NULL);
2991 
2992   if (self->n_structural_components > 0) {
2993     GValue arr = { 0, }
2994     , val = {
2995     0,};
2996 
2997     g_value_init (&arr, GST_TYPE_ARRAY);
2998 
2999     for (i = 0; i < self->n_structural_components; i++) {
3000       GstStructure *s;
3001 
3002       if (self->structural_components[i] == NULL)
3003         continue;
3004 
3005       g_value_init (&val, GST_TYPE_STRUCTURE);
3006 
3007       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
3008           (self->structural_components[i]));
3009       gst_value_set_structure (&val, s);
3010       gst_structure_free (s);
3011       gst_value_array_append_value (&arr, &val);
3012       g_value_unset (&val);
3013     }
3014 
3015     if (gst_value_array_get_size (&arr) > 0)
3016       gst_structure_id_set_value (ret, MXF_QUARK (STRUCTURAL_COMPONENTS), &arr);
3017 
3018     g_value_unset (&arr);
3019   }
3020 
3021   return ret;
3022 }
3023 
3024 static GList *
mxf_metadata_sequence_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3025 mxf_metadata_sequence_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
3026 {
3027   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
3028   GList *ret =
3029       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->write_tags
3030       (m, primer);
3031   MXFLocalTag *t;
3032 
3033   t = g_slice_new0 (MXFLocalTag);
3034   memcpy (&t->ul, MXF_UL (DATA_DEFINITION), 16);
3035   t->size = 16;
3036   t->data = g_slice_alloc (t->size);
3037   t->g_slice = TRUE;
3038   memcpy (t->data, &self->data_definition, 16);
3039   mxf_primer_pack_add_mapping (primer, 0x0201, &t->ul);
3040   ret = g_list_prepend (ret, t);
3041 
3042   t = g_slice_new0 (MXFLocalTag);
3043   memcpy (&t->ul, MXF_UL (DURATION), 16);
3044   t->size = 8;
3045   t->data = g_slice_alloc (t->size);
3046   t->g_slice = TRUE;
3047   GST_WRITE_UINT64_BE (t->data, self->duration);
3048   mxf_primer_pack_add_mapping (primer, 0x0202, &t->ul);
3049   ret = g_list_prepend (ret, t);
3050 
3051   if (self->structural_components) {
3052     guint i;
3053     t = g_slice_new0 (MXFLocalTag);
3054     memcpy (&t->ul, MXF_UL (STRUCTURAL_COMPONENTS), 16);
3055     t->size = 8 + 16 * self->n_structural_components;
3056     t->data = g_slice_alloc0 (t->size);
3057     t->g_slice = TRUE;
3058 
3059     GST_WRITE_UINT32_BE (t->data, self->n_structural_components);
3060     GST_WRITE_UINT32_BE (t->data + 4, 16);
3061     for (i = 0; i < self->n_structural_components; i++) {
3062       if (!self->structural_components[i])
3063         continue;
3064 
3065       memcpy (t->data + 8 + i * 16,
3066           &MXF_METADATA_BASE (self->structural_components[i])->instance_uid,
3067           16);
3068     }
3069 
3070     mxf_primer_pack_add_mapping (primer, 0x1001, &t->ul);
3071     ret = g_list_prepend (ret, t);
3072   }
3073 
3074   return ret;
3075 }
3076 
3077 static void
mxf_metadata_sequence_init(MXFMetadataSequence * self)3078 mxf_metadata_sequence_init (MXFMetadataSequence * self)
3079 {
3080   self->duration = -1;
3081 }
3082 
3083 static void
mxf_metadata_sequence_class_init(MXFMetadataSequenceClass * klass)3084 mxf_metadata_sequence_class_init (MXFMetadataSequenceClass * klass)
3085 {
3086   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3087   GObjectClass *object_class = (GObjectClass *) klass;
3088   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3089 
3090   object_class->finalize = mxf_metadata_sequence_finalize;
3091   metadata_base_class->handle_tag = mxf_metadata_sequence_handle_tag;
3092   metadata_base_class->resolve = mxf_metadata_sequence_resolve;
3093   metadata_base_class->name_quark = MXF_QUARK (SEQUENCE);
3094   metadata_base_class->to_structure = mxf_metadata_sequence_to_structure;
3095   metadata_base_class->write_tags = mxf_metadata_sequence_write_tags;
3096   metadata_class->type = 0x010f;
3097 }
3098 
3099 G_DEFINE_TYPE (MXFMetadataStructuralComponent,
3100     mxf_metadata_structural_component, MXF_TYPE_METADATA);
3101 
3102 static gboolean
mxf_metadata_structural_component_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3103 mxf_metadata_structural_component_handle_tag (MXFMetadataBase * metadata,
3104     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3105     guint tag_size)
3106 {
3107   MXFMetadataStructuralComponent *self =
3108       MXF_METADATA_STRUCTURAL_COMPONENT (metadata);
3109   gboolean ret = TRUE;
3110 #ifndef GST_DISABLE_GST_DEBUG
3111   gchar str[48];
3112 #endif
3113 
3114   switch (tag) {
3115     case 0x0201:
3116       if (tag_size != 16)
3117         goto error;
3118       memcpy (&self->data_definition, tag_data, 16);
3119       GST_DEBUG ("  data definition = %s",
3120           mxf_ul_to_string (&self->data_definition, str));
3121       break;
3122     case 0x0202:
3123       if (tag_size != 8)
3124         goto error;
3125       self->duration = GST_READ_UINT64_BE (tag_data);
3126       GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
3127       break;
3128     default:
3129       ret =
3130           MXF_METADATA_BASE_CLASS
3131           (mxf_metadata_structural_component_parent_class)->handle_tag
3132           (metadata, primer, tag, tag_data, tag_size);
3133       break;
3134   }
3135 
3136   return ret;
3137 
3138 error:
3139 
3140   GST_ERROR ("Invalid structural component local tag 0x%04x of size %u", tag,
3141       tag_size);
3142 
3143   return FALSE;
3144 }
3145 
3146 static GstStructure *
mxf_metadata_structural_component_to_structure(MXFMetadataBase * m)3147 mxf_metadata_structural_component_to_structure (MXFMetadataBase * m)
3148 {
3149   GstStructure *ret =
3150       MXF_METADATA_BASE_CLASS
3151       (mxf_metadata_structural_component_parent_class)->to_structure (m);
3152   MXFMetadataStructuralComponent *self = MXF_METADATA_STRUCTURAL_COMPONENT (m);
3153   gchar str[48];
3154 
3155   mxf_ul_to_string (&self->data_definition, str);
3156   gst_structure_id_set (ret, MXF_QUARK (DATA_DEFINITION), G_TYPE_STRING, str,
3157       MXF_QUARK (DURATION), G_TYPE_INT64, self->duration, NULL);
3158 
3159   return ret;
3160 }
3161 
3162 static GList *
mxf_metadata_structural_component_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3163 mxf_metadata_structural_component_write_tags (MXFMetadataBase * m,
3164     MXFPrimerPack * primer)
3165 {
3166   MXFMetadataStructuralComponent *self = MXF_METADATA_STRUCTURAL_COMPONENT (m);
3167   GList *ret =
3168       MXF_METADATA_BASE_CLASS
3169       (mxf_metadata_structural_component_parent_class)->write_tags (m, primer);
3170   MXFLocalTag *t;
3171 
3172   t = g_slice_new0 (MXFLocalTag);
3173   memcpy (&t->ul, MXF_UL (DATA_DEFINITION), 16);
3174   t->size = 16;
3175   t->data = g_slice_alloc (t->size);
3176   t->g_slice = TRUE;
3177   memcpy (t->data, &self->data_definition, 16);
3178   mxf_primer_pack_add_mapping (primer, 0x0201, &t->ul);
3179   ret = g_list_prepend (ret, t);
3180 
3181   t = g_slice_new0 (MXFLocalTag);
3182   memcpy (&t->ul, MXF_UL (DURATION), 16);
3183   t->size = 8;
3184   t->data = g_slice_alloc (t->size);
3185   t->g_slice = TRUE;
3186   GST_WRITE_UINT64_BE (t->data, self->duration);
3187   mxf_primer_pack_add_mapping (primer, 0x0202, &t->ul);
3188   ret = g_list_prepend (ret, t);
3189 
3190   return ret;
3191 }
3192 
3193 static void
mxf_metadata_structural_component_init(MXFMetadataStructuralComponent * self)3194 mxf_metadata_structural_component_init (MXFMetadataStructuralComponent * self)
3195 {
3196   self->duration = -1;
3197 }
3198 
3199 static void
mxf_metadata_structural_component_class_init(MXFMetadataStructuralComponentClass * klass)3200     mxf_metadata_structural_component_class_init
3201     (MXFMetadataStructuralComponentClass * klass)
3202 {
3203   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3204 
3205   metadata_base_class->handle_tag =
3206       mxf_metadata_structural_component_handle_tag;
3207   metadata_base_class->to_structure =
3208       mxf_metadata_structural_component_to_structure;
3209   metadata_base_class->write_tags =
3210       mxf_metadata_structural_component_write_tags;
3211 }
3212 
3213 G_DEFINE_TYPE (MXFMetadataTimecodeComponent, mxf_metadata_timecode_component,
3214     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3215 
3216 static gboolean
mxf_metadata_timecode_component_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3217 mxf_metadata_timecode_component_handle_tag (MXFMetadataBase * metadata,
3218     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3219     guint tag_size)
3220 {
3221   MXFMetadataTimecodeComponent *self =
3222       MXF_METADATA_TIMECODE_COMPONENT (metadata);
3223   gboolean ret = TRUE;
3224 
3225   switch (tag) {
3226     case 0x1502:
3227       if (tag_size != 2)
3228         goto error;
3229       self->rounded_timecode_base = GST_READ_UINT16_BE (tag_data);
3230       GST_DEBUG ("  rounded timecode base = %u", self->rounded_timecode_base);
3231       break;
3232     case 0x1501:
3233       if (tag_size != 8)
3234         goto error;
3235       self->start_timecode = GST_READ_UINT64_BE (tag_data);
3236       GST_DEBUG ("  start timecode = %" G_GINT64_FORMAT, self->start_timecode);
3237       break;
3238     case 0x1503:
3239       if (tag_size != 1)
3240         goto error;
3241       self->drop_frame = (GST_READ_UINT8 (tag_data) != 0);
3242       GST_DEBUG ("  drop frame = %s", (self->drop_frame) ? "yes" : "no");
3243       break;
3244     default:
3245       ret =
3246           MXF_METADATA_BASE_CLASS
3247           (mxf_metadata_timecode_component_parent_class)->handle_tag (metadata,
3248           primer, tag, tag_data, tag_size);
3249       break;
3250   }
3251 
3252   return ret;
3253 
3254 error:
3255 
3256   GST_ERROR ("Invalid timecode component local tag 0x%04x of size %u", tag,
3257       tag_size);
3258 
3259   return FALSE;
3260 }
3261 
3262 static GstStructure *
mxf_metadata_timecode_component_to_structure(MXFMetadataBase * m)3263 mxf_metadata_timecode_component_to_structure (MXFMetadataBase * m)
3264 {
3265   GstStructure *ret =
3266       MXF_METADATA_BASE_CLASS
3267       (mxf_metadata_timecode_component_parent_class)->to_structure (m);
3268   MXFMetadataTimecodeComponent *self = MXF_METADATA_TIMECODE_COMPONENT (m);
3269 
3270   gst_structure_id_set (ret, MXF_QUARK (START_TIMECODE), G_TYPE_INT64,
3271       self->start_timecode, MXF_QUARK (ROUNDED_TIMECODE_BASE), G_TYPE_UINT,
3272       self->rounded_timecode_base, MXF_QUARK (DROP_FRAME), G_TYPE_BOOLEAN,
3273       self->drop_frame, NULL);
3274 
3275   return ret;
3276 }
3277 
3278 static GList *
mxf_metadata_timecode_component_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3279 mxf_metadata_timecode_component_write_tags (MXFMetadataBase * m,
3280     MXFPrimerPack * primer)
3281 {
3282   MXFMetadataTimecodeComponent *self = MXF_METADATA_TIMECODE_COMPONENT (m);
3283   GList *ret =
3284       MXF_METADATA_BASE_CLASS
3285       (mxf_metadata_timecode_component_parent_class)->write_tags (m, primer);
3286   MXFLocalTag *t;
3287 
3288   t = g_slice_new0 (MXFLocalTag);
3289   memcpy (&t->ul, MXF_UL (ROUNDED_TIMECODE_BASE), 16);
3290   t->size = 2;
3291   t->data = g_slice_alloc (t->size);
3292   t->g_slice = TRUE;
3293   GST_WRITE_UINT16_BE (t->data, self->rounded_timecode_base);
3294   mxf_primer_pack_add_mapping (primer, 0x1502, &t->ul);
3295   ret = g_list_prepend (ret, t);
3296 
3297   t = g_slice_new0 (MXFLocalTag);
3298   memcpy (&t->ul, MXF_UL (START_TIMECODE), 16);
3299   t->size = 8;
3300   t->data = g_slice_alloc (t->size);
3301   t->g_slice = TRUE;
3302   GST_WRITE_UINT64_BE (t->data, self->start_timecode);
3303   mxf_primer_pack_add_mapping (primer, 0x1501, &t->ul);
3304   ret = g_list_prepend (ret, t);
3305 
3306   t = g_slice_new0 (MXFLocalTag);
3307   memcpy (&t->ul, MXF_UL (DROP_FRAME), 16);
3308   t->size = 1;
3309   t->data = g_slice_alloc (t->size);
3310   t->g_slice = TRUE;
3311   GST_WRITE_UINT8 (t->data, (self->drop_frame) ? 1 : 0);
3312   mxf_primer_pack_add_mapping (primer, 0x1503, &t->ul);
3313   ret = g_list_prepend (ret, t);
3314 
3315   return ret;
3316 }
3317 
3318 static void
mxf_metadata_timecode_component_init(MXFMetadataTimecodeComponent * self)3319 mxf_metadata_timecode_component_init (MXFMetadataTimecodeComponent * self)
3320 {
3321 
3322 }
3323 
3324 static void
mxf_metadata_timecode_component_class_init(MXFMetadataTimecodeComponentClass * klass)3325 mxf_metadata_timecode_component_class_init (MXFMetadataTimecodeComponentClass *
3326     klass)
3327 {
3328   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3329   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3330 
3331   metadata_base_class->handle_tag = mxf_metadata_timecode_component_handle_tag;
3332   metadata_base_class->name_quark = MXF_QUARK (TIMECODE_COMPONENT);
3333   metadata_base_class->to_structure =
3334       mxf_metadata_timecode_component_to_structure;
3335   metadata_base_class->write_tags = mxf_metadata_timecode_component_write_tags;
3336   metadata_class->type = 0x0114;
3337 }
3338 
3339 G_DEFINE_TYPE (MXFMetadataSourceClip, mxf_metadata_source_clip,
3340     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3341 
3342 static gboolean
mxf_metadata_source_clip_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3343 mxf_metadata_source_clip_handle_tag (MXFMetadataBase * metadata,
3344     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3345     guint tag_size)
3346 {
3347   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (metadata);
3348   gboolean ret = TRUE;
3349 #ifndef GST_DISABLE_GST_DEBUG
3350   gchar str[96];
3351 #endif
3352 
3353   switch (tag) {
3354     case 0x1201:
3355       if (tag_size != 8)
3356         goto error;
3357 
3358       self->start_position = GST_READ_UINT64_BE (tag_data);
3359       GST_DEBUG ("  start position = %" G_GINT64_FORMAT, self->start_position);
3360       break;
3361     case 0x1101:
3362       if (tag_size != 32)
3363         goto error;
3364 
3365       memcpy (&self->source_package_id, tag_data, 32);
3366       GST_DEBUG ("  source package id = %s",
3367           mxf_umid_to_string (&self->source_package_id, str));
3368       break;
3369     case 0x1102:
3370       if (tag_size != 4)
3371         goto error;
3372 
3373       self->source_track_id = GST_READ_UINT32_BE (tag_data);
3374       GST_DEBUG ("  source track id = %u", self->source_track_id);
3375       break;
3376     default:
3377       ret =
3378           MXF_METADATA_BASE_CLASS
3379           (mxf_metadata_source_clip_parent_class)->handle_tag (metadata, primer,
3380           tag, tag_data, tag_size);
3381       break;
3382   }
3383 
3384   return ret;
3385 
3386 error:
3387 
3388   GST_ERROR ("Invalid source clip local tag 0x%04x of size %u", tag, tag_size);
3389 
3390   return FALSE;
3391 }
3392 
3393 static gboolean
mxf_metadata_source_clip_resolve(MXFMetadataBase * m,GHashTable * metadata)3394 mxf_metadata_source_clip_resolve (MXFMetadataBase * m, GHashTable * metadata)
3395 {
3396   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3397   MXFMetadataBase *current = NULL;
3398   GHashTableIter iter;
3399 #ifndef GST_DISABLE_GST_DEBUG
3400   gchar str[96];
3401 #endif
3402 
3403   g_hash_table_iter_init (&iter, metadata);
3404 
3405   while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
3406     if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
3407       MXFMetadataGenericPackage *p = MXF_METADATA_GENERIC_PACKAGE (current);
3408 
3409       if (mxf_umid_is_equal (&p->package_uid, &self->source_package_id)) {
3410         self->source_package = MXF_METADATA_SOURCE_PACKAGE (current);
3411         break;
3412       }
3413     }
3414   }
3415 
3416   if (!self->source_package) {
3417     GST_ERROR ("Couldn't find source package %s",
3418         mxf_umid_to_string (&self->source_package_id, str));
3419   }
3420 
3421   return
3422       MXF_METADATA_BASE_CLASS (mxf_metadata_source_clip_parent_class)->resolve
3423       (m, metadata);
3424 }
3425 
3426 static GstStructure *
mxf_metadata_source_clip_to_structure(MXFMetadataBase * m)3427 mxf_metadata_source_clip_to_structure (MXFMetadataBase * m)
3428 {
3429   GstStructure *ret =
3430       MXF_METADATA_BASE_CLASS
3431       (mxf_metadata_source_clip_parent_class)->to_structure (m);
3432   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3433   gchar str[96];
3434 
3435   mxf_umid_to_string (&self->source_package_id, str);
3436   gst_structure_id_set (ret, MXF_QUARK (START_POSITION), G_TYPE_INT64,
3437       self->start_position, MXF_QUARK (SOURCE_PACKAGE), G_TYPE_STRING, str,
3438       MXF_QUARK (SOURCE_TRACK_ID), G_TYPE_UINT, self->source_track_id, NULL);
3439 
3440   return ret;
3441 }
3442 
3443 static GList *
mxf_metadata_source_clip_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3444 mxf_metadata_source_clip_write_tags (MXFMetadataBase * m,
3445     MXFPrimerPack * primer)
3446 {
3447   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3448   GList *ret =
3449       MXF_METADATA_BASE_CLASS
3450       (mxf_metadata_source_clip_parent_class)->write_tags (m, primer);
3451   MXFLocalTag *t;
3452 
3453   t = g_slice_new0 (MXFLocalTag);
3454   memcpy (&t->ul, MXF_UL (START_POSITION), 16);
3455   t->size = 8;
3456   t->data = g_slice_alloc (t->size);
3457   t->g_slice = TRUE;
3458   GST_WRITE_UINT64_BE (t->data, self->start_position);
3459   mxf_primer_pack_add_mapping (primer, 0x1201, &t->ul);
3460   ret = g_list_prepend (ret, t);
3461 
3462   t = g_slice_new0 (MXFLocalTag);
3463   memcpy (&t->ul, MXF_UL (SOURCE_PACKAGE_ID), 16);
3464   t->size = 32;
3465   t->data = g_slice_alloc (t->size);
3466   t->g_slice = TRUE;
3467   memcpy (t->data, &self->source_package_id, 32);
3468   mxf_primer_pack_add_mapping (primer, 0x1101, &t->ul);
3469   ret = g_list_prepend (ret, t);
3470 
3471   t = g_slice_new0 (MXFLocalTag);
3472   memcpy (&t->ul, MXF_UL (SOURCE_TRACK_ID), 16);
3473   t->size = 4;
3474   t->data = g_slice_alloc (t->size);
3475   t->g_slice = TRUE;
3476   GST_WRITE_UINT32_BE (t->data, self->source_track_id);
3477   mxf_primer_pack_add_mapping (primer, 0x1102, &t->ul);
3478   ret = g_list_prepend (ret, t);
3479 
3480   return ret;
3481 }
3482 
3483 static void
mxf_metadata_source_clip_init(MXFMetadataSourceClip * self)3484 mxf_metadata_source_clip_init (MXFMetadataSourceClip * self)
3485 {
3486 
3487 }
3488 
3489 static void
mxf_metadata_source_clip_class_init(MXFMetadataSourceClipClass * klass)3490 mxf_metadata_source_clip_class_init (MXFMetadataSourceClipClass * klass)
3491 {
3492   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3493   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3494 
3495   metadata_base_class->handle_tag = mxf_metadata_source_clip_handle_tag;
3496   metadata_base_class->resolve = mxf_metadata_source_clip_resolve;
3497   metadata_base_class->name_quark = MXF_QUARK (SOURCE_CLIP);
3498   metadata_base_class->to_structure = mxf_metadata_source_clip_to_structure;
3499   metadata_base_class->write_tags = mxf_metadata_source_clip_write_tags;
3500   metadata_class->type = 0x0111;
3501 }
3502 
3503 
3504 G_DEFINE_TYPE (MXFMetadataFiller, mxf_metadata_filler,
3505     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3506 
3507 static void
mxf_metadata_filler_init(MXFMetadataFiller * self)3508 mxf_metadata_filler_init (MXFMetadataFiller * self)
3509 {
3510 
3511 }
3512 
3513 static void
mxf_metadata_filler_class_init(MXFMetadataFillerClass * klass)3514 mxf_metadata_filler_class_init (MXFMetadataFillerClass * klass)
3515 {
3516   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3517   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3518 
3519   metadata_base_class->name_quark = MXF_QUARK (FILLER);
3520   metadata_class->type = 0x0109;
3521 }
3522 
3523 G_DEFINE_TYPE (MXFMetadataDMSourceClip, mxf_metadata_dm_source_clip,
3524     MXF_TYPE_METADATA_SOURCE_CLIP);
3525 
3526 static void
mxf_metadata_dm_source_clip_finalize(GObject * object)3527 mxf_metadata_dm_source_clip_finalize (GObject * object)
3528 {
3529   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (object);
3530 
3531   g_free (self->track_ids);
3532   self->track_ids = NULL;
3533 
3534   G_OBJECT_CLASS (mxf_metadata_dm_source_clip_parent_class)->finalize (object);
3535 }
3536 
3537 static gboolean
mxf_metadata_dm_source_clip_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3538 mxf_metadata_dm_source_clip_handle_tag (MXFMetadataBase * metadata,
3539     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3540     guint tag_size)
3541 {
3542   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (metadata);
3543   gboolean ret = TRUE;
3544 
3545   switch (tag) {
3546     case 0x6103:
3547     {
3548       guint32 len;
3549       guint i;
3550 
3551       if (tag_size < 8)
3552         goto error;
3553 
3554       len = GST_READ_UINT32_BE (tag_data);
3555       GST_DEBUG ("  number of track ids = %u", len);
3556       if (len == 0)
3557         return TRUE;
3558 
3559       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
3560         goto error;
3561 
3562       tag_data += 8;
3563       tag_size -= 8;
3564 
3565       if (tag_size / 4 < len)
3566         goto error;
3567 
3568       self->n_track_ids = len;
3569       self->track_ids = g_new0 (guint32, len);
3570 
3571       for (i = 0; i < len; i++) {
3572         self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
3573         GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
3574         tag_data += 4;
3575         tag_size -= 4;
3576       }
3577       break;
3578     }
3579     default:
3580       ret =
3581           MXF_METADATA_BASE_CLASS
3582           (mxf_metadata_dm_source_clip_parent_class)->handle_tag (metadata,
3583           primer, tag, tag_data, tag_size);
3584       break;
3585   }
3586 
3587   return ret;
3588 
3589 error:
3590 
3591   GST_ERROR ("Invalid DM source clip local tag 0x%04x of size %u", tag,
3592       tag_size);
3593 
3594   return FALSE;
3595 }
3596 
3597 static GstStructure *
mxf_metadata_dm_source_clip_to_structure(MXFMetadataBase * m)3598 mxf_metadata_dm_source_clip_to_structure (MXFMetadataBase * m)
3599 {
3600   GstStructure *ret =
3601       MXF_METADATA_BASE_CLASS
3602       (mxf_metadata_dm_source_clip_parent_class)->to_structure (m);
3603   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (m);
3604   guint i;
3605 
3606   if (self->n_track_ids > 0) {
3607     GValue arr = { 0, }
3608     , val = {
3609     0,};
3610 
3611     g_value_init (&arr, GST_TYPE_ARRAY);
3612 
3613     for (i = 0; i < self->n_track_ids; i++) {
3614       g_value_init (&val, G_TYPE_UINT);
3615 
3616       g_value_set_uint (&val, self->track_ids[i]);
3617       gst_value_array_append_value (&arr, &val);
3618       g_value_unset (&val);
3619     }
3620 
3621     if (gst_value_array_get_size (&arr) > 0)
3622       gst_structure_id_set_value (ret, MXF_QUARK (TRACK_IDS), &arr);
3623 
3624     g_value_unset (&arr);
3625   }
3626 
3627   return ret;
3628 }
3629 
3630 static GList *
mxf_metadata_dm_source_clip_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3631 mxf_metadata_dm_source_clip_write_tags (MXFMetadataBase * m,
3632     MXFPrimerPack * primer)
3633 {
3634   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (m);
3635   GList *ret =
3636       MXF_METADATA_BASE_CLASS
3637       (mxf_metadata_dm_source_clip_parent_class)->write_tags (m, primer);
3638   MXFLocalTag *t;
3639 
3640   if (self->track_ids) {
3641     guint i;
3642 
3643     t = g_slice_new0 (MXFLocalTag);
3644     memcpy (&t->ul, MXF_UL (DM_SOURCECLIP_TRACK_IDS), 16);
3645     t->size = 8 + 4 * self->n_track_ids;
3646     t->data = g_slice_alloc (t->size);
3647     t->g_slice = TRUE;
3648     GST_WRITE_UINT32_BE (t->data, self->n_track_ids);
3649     GST_WRITE_UINT32_BE (t->data + 4, 4);
3650     for (i = 0; i < self->n_track_ids; i++)
3651       GST_WRITE_UINT32_BE (t->data + 8 + i * 4, self->track_ids[i]);
3652     mxf_primer_pack_add_mapping (primer, 0x6103, &t->ul);
3653     ret = g_list_prepend (ret, t);
3654   }
3655 
3656   return ret;
3657 }
3658 
3659 static void
mxf_metadata_dm_source_clip_init(MXFMetadataDMSourceClip * self)3660 mxf_metadata_dm_source_clip_init (MXFMetadataDMSourceClip * self)
3661 {
3662 
3663 }
3664 
3665 static void
mxf_metadata_dm_source_clip_class_init(MXFMetadataDMSourceClipClass * klass)3666 mxf_metadata_dm_source_clip_class_init (MXFMetadataDMSourceClipClass * klass)
3667 {
3668   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3669   GObjectClass *object_class = (GObjectClass *) klass;
3670   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3671 
3672   object_class->finalize = mxf_metadata_dm_source_clip_finalize;
3673   metadata_base_class->handle_tag = mxf_metadata_dm_source_clip_handle_tag;
3674   metadata_base_class->name_quark = MXF_QUARK (DM_SOURCE_CLIP);
3675   metadata_base_class->to_structure = mxf_metadata_dm_source_clip_to_structure;
3676   metadata_base_class->write_tags = mxf_metadata_dm_source_clip_write_tags;
3677   metadata_class->type = 0x0145;
3678 }
3679 
3680 G_DEFINE_TYPE (MXFMetadataDMSegment, mxf_metadata_dm_segment,
3681     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3682 
3683 static void
mxf_metadata_dm_segment_finalize(GObject * object)3684 mxf_metadata_dm_segment_finalize (GObject * object)
3685 {
3686   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (object);
3687 
3688   g_free (self->track_ids);
3689   self->track_ids = NULL;
3690 
3691   g_free (self->event_comment);
3692   self->event_comment = NULL;
3693 
3694   G_OBJECT_CLASS (mxf_metadata_dm_segment_parent_class)->finalize (object);
3695 }
3696 
3697 static gboolean
mxf_metadata_dm_segment_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3698 mxf_metadata_dm_segment_handle_tag (MXFMetadataBase * metadata,
3699     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3700     guint tag_size)
3701 {
3702   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (metadata);
3703   gboolean ret = TRUE;
3704 #ifndef GST_DISABLE_GST_DEBUG
3705   gchar str[48];
3706 #endif
3707 
3708   switch (tag) {
3709     case 0x0601:
3710       if (tag_size != 8)
3711         goto error;
3712       self->event_start_position = GST_READ_UINT64_BE (tag_data);
3713       GST_DEBUG ("  event start position = %" G_GINT64_FORMAT,
3714           self->event_start_position);
3715       break;
3716     case 0x0602:
3717       self->event_comment = mxf_utf16_to_utf8 (tag_data, tag_size);
3718       GST_DEBUG ("  event comment = %s", GST_STR_NULL (self->event_comment));
3719       break;
3720     case 0x6102:
3721     {
3722       guint32 len;
3723       guint i;
3724 
3725       if (tag_size < 8)
3726         goto error;
3727       len = GST_READ_UINT32_BE (tag_data);
3728       GST_DEBUG ("  number of track ids = %u", len);
3729       if (len == 0)
3730         return TRUE;
3731 
3732       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
3733         goto error;
3734 
3735       tag_data += 8;
3736       tag_size -= 8;
3737 
3738       if (len < tag_size / 4)
3739         goto error;
3740 
3741       self->n_track_ids = len;
3742       self->track_ids = g_new0 (guint32, len);
3743 
3744       tag_data += 8;
3745       tag_size -= 8;
3746 
3747       for (i = 0; i < len; i++) {
3748         self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
3749         GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
3750         tag_data += 4;
3751         tag_size -= 4;
3752       }
3753       break;
3754     }
3755     case 0x6101:
3756       if (tag_size != 16)
3757         goto error;
3758 
3759       memcpy (&self->dm_framework_uid, tag_data, 16);
3760       GST_DEBUG ("  DM framework = %s",
3761           mxf_uuid_to_string (&self->dm_framework_uid, str));
3762       break;
3763     default:
3764       ret =
3765           MXF_METADATA_BASE_CLASS
3766           (mxf_metadata_dm_segment_parent_class)->handle_tag (metadata, primer,
3767           tag, tag_data, tag_size);
3768       break;
3769   }
3770 
3771   return ret;
3772 
3773 error:
3774 
3775   GST_ERROR ("Invalid DM segment local tag 0x%04x of size %u", tag, tag_size);
3776 
3777   return FALSE;
3778 }
3779 
3780 static gboolean
mxf_metadata_dm_segment_resolve(MXFMetadataBase * m,GHashTable * metadata)3781 mxf_metadata_dm_segment_resolve (MXFMetadataBase * m, GHashTable * metadata)
3782 {
3783   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3784   MXFMetadataBase *current = NULL;
3785 #ifndef GST_DISABLE_GST_DEBUG
3786   gchar str[48];
3787 #endif
3788 
3789   current = g_hash_table_lookup (metadata, &self->dm_framework_uid);
3790   if (current && MXF_IS_DESCRIPTIVE_METADATA_FRAMEWORK (current)) {
3791     if (mxf_metadata_base_resolve (current, metadata)) {
3792       self->dm_framework = MXF_DESCRIPTIVE_METADATA_FRAMEWORK (current);
3793     } else {
3794       GST_ERROR ("Couldn't resolve DM framework %s",
3795           mxf_uuid_to_string (&self->dm_framework_uid, str));
3796       return FALSE;
3797     }
3798   } else {
3799     GST_ERROR ("Couldn't find DM framework %s",
3800         mxf_uuid_to_string (&self->dm_framework_uid, str));
3801     return FALSE;
3802   }
3803 
3804 
3805   return
3806       MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->resolve
3807       (m, metadata);
3808 }
3809 
3810 static GstStructure *
mxf_metadata_dm_segment_to_structure(MXFMetadataBase * m)3811 mxf_metadata_dm_segment_to_structure (MXFMetadataBase * m)
3812 {
3813   GstStructure *ret =
3814       MXF_METADATA_BASE_CLASS
3815       (mxf_metadata_dm_segment_parent_class)->to_structure (m);
3816   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3817   guint i;
3818 
3819   gst_structure_id_set (ret, MXF_QUARK (EVENT_START_POSITION), G_TYPE_INT64,
3820       self->event_start_position, NULL);
3821 
3822   if (self->event_comment)
3823     gst_structure_id_set (ret, MXF_QUARK (EVENT_COMMENT), G_TYPE_STRING,
3824         self->event_comment, NULL);
3825   /* FIXME: DMS1 doesn't support serializing to a structure yet */
3826 #if 0
3827   if (self->dm_framework) {
3828     GstStructure *s =
3829         mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->dm_framework));
3830 
3831     gst_structure_id_set (ret, MXF_QUARK (DM_FRAMEWORK), GST_TYPE_STRUCTURE,
3832         s, NULL);
3833     gst_structure_free (s);
3834   }
3835 #endif
3836 
3837   if (self->n_track_ids > 0) {
3838     GValue arr = { 0, }
3839     , val = {
3840     0,};
3841 
3842     g_value_init (&arr, GST_TYPE_ARRAY);
3843 
3844     for (i = 0; i < self->n_track_ids; i++) {
3845       g_value_init (&val, G_TYPE_UINT);
3846 
3847       g_value_set_uint (&val, self->track_ids[i]);
3848       gst_value_array_append_value (&arr, &val);
3849       g_value_unset (&val);
3850     }
3851 
3852     if (gst_value_array_get_size (&arr) > 0)
3853       gst_structure_id_set_value (ret, MXF_QUARK (TRACK_IDS), &arr);
3854 
3855     g_value_unset (&arr);
3856   }
3857 
3858   return ret;
3859 }
3860 
3861 static GList *
mxf_metadata_dm_segment_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3862 mxf_metadata_dm_segment_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
3863 {
3864   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3865   GList *ret =
3866       MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->write_tags
3867       (m, primer);
3868   MXFLocalTag *t;
3869 
3870   if (self->event_start_position != -1) {
3871     t = g_slice_new0 (MXFLocalTag);
3872     memcpy (&t->ul, MXF_UL (EVENT_START_POSITION), 16);
3873     t->size = 8;
3874     t->data = g_slice_alloc (t->size);
3875     t->g_slice = TRUE;
3876     GST_WRITE_UINT64_BE (t->data, self->event_start_position);
3877     mxf_primer_pack_add_mapping (primer, 0x0601, &t->ul);
3878     ret = g_list_prepend (ret, t);
3879   }
3880 
3881   if (self->event_comment) {
3882     t = g_slice_new0 (MXFLocalTag);
3883     memcpy (&t->ul, MXF_UL (EVENT_COMMENT), 16);
3884     t->data = mxf_utf8_to_utf16 (self->event_comment, &t->size);
3885     mxf_primer_pack_add_mapping (primer, 0x0602, &t->ul);
3886     ret = g_list_prepend (ret, t);
3887   }
3888 
3889   if (self->track_ids) {
3890     guint i;
3891 
3892     t = g_slice_new0 (MXFLocalTag);
3893     memcpy (&t->ul, MXF_UL (DM_SEGMENT_TRACK_IDS), 16);
3894     t->size = 8 + 4 * self->n_track_ids;
3895     t->data = g_slice_alloc (t->size);
3896     t->g_slice = TRUE;
3897     GST_WRITE_UINT32_BE (t->data, self->n_track_ids);
3898     GST_WRITE_UINT32_BE (t->data + 4, 4);
3899     for (i = 0; i < self->n_track_ids; i++)
3900       GST_WRITE_UINT32_BE (t->data + 8 + i * 4, self->track_ids[i]);
3901     mxf_primer_pack_add_mapping (primer, 0x6102, &t->ul);
3902     ret = g_list_prepend (ret, t);
3903   }
3904 
3905   if (self->dm_framework) {
3906     t = g_slice_new0 (MXFLocalTag);
3907     memcpy (&t->ul, MXF_UL (DM_FRAMEWORK), 16);
3908     t->size = 16;
3909     t->data = g_slice_alloc (t->size);
3910     t->g_slice = TRUE;
3911     memcpy (t->data, &MXF_METADATA_BASE (self->dm_framework)->instance_uid, 16);
3912     mxf_primer_pack_add_mapping (primer, 0x6101, &t->ul);
3913     ret = g_list_prepend (ret, t);
3914   }
3915 
3916   return ret;
3917 }
3918 
3919 static void
mxf_metadata_dm_segment_init(MXFMetadataDMSegment * self)3920 mxf_metadata_dm_segment_init (MXFMetadataDMSegment * self)
3921 {
3922   self->event_start_position = -1;
3923 }
3924 
3925 static void
mxf_metadata_dm_segment_class_init(MXFMetadataDMSegmentClass * klass)3926 mxf_metadata_dm_segment_class_init (MXFMetadataDMSegmentClass * klass)
3927 {
3928   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3929   GObjectClass *object_class = (GObjectClass *) klass;
3930   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3931 
3932   object_class->finalize = mxf_metadata_dm_segment_finalize;
3933   metadata_base_class->handle_tag = mxf_metadata_dm_segment_handle_tag;
3934   metadata_base_class->resolve = mxf_metadata_dm_segment_resolve;
3935   metadata_base_class->name_quark = MXF_QUARK (DM_SEGMENT);
3936   metadata_base_class->to_structure = mxf_metadata_dm_segment_to_structure;
3937   metadata_base_class->write_tags = mxf_metadata_dm_segment_write_tags;
3938   metadata_class->type = 0x0141;
3939 }
3940 
3941 G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericDescriptor,
3942     mxf_metadata_generic_descriptor, MXF_TYPE_METADATA);
3943 
3944 static void
mxf_metadata_generic_descriptor_finalize(GObject * object)3945 mxf_metadata_generic_descriptor_finalize (GObject * object)
3946 {
3947   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (object);
3948 
3949   g_free (self->locators_uids);
3950   self->locators_uids = NULL;
3951 
3952   g_free (self->locators);
3953   self->locators = NULL;
3954 
3955   G_OBJECT_CLASS (mxf_metadata_generic_descriptor_parent_class)->finalize
3956       (object);
3957 }
3958 
3959 static gboolean
mxf_metadata_generic_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3960 mxf_metadata_generic_descriptor_handle_tag (MXFMetadataBase * metadata,
3961     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3962     guint tag_size)
3963 {
3964   MXFMetadataGenericDescriptor *self =
3965       MXF_METADATA_GENERIC_DESCRIPTOR (metadata);
3966   gboolean ret = TRUE;
3967 #ifndef GST_DISABLE_GST_DEBUG
3968   gchar str[48];
3969 #endif
3970 
3971   switch (tag) {
3972     case 0x2f01:
3973       if (!mxf_uuid_array_parse (&self->locators_uids, &self->n_locators,
3974               tag_data, tag_size))
3975         goto error;
3976 
3977       GST_DEBUG ("  number of locators = %u", self->n_locators);
3978 #ifndef GST_DISABLE_GST_DEBUG
3979       {
3980         guint i;
3981         for (i = 0; i < self->n_locators; i++) {
3982           GST_DEBUG ("  locator %u = %s", i,
3983               mxf_uuid_to_string (&self->locators_uids[i], str));
3984         }
3985       }
3986 #endif
3987       break;
3988     default:
3989       ret =
3990           MXF_METADATA_BASE_CLASS
3991           (mxf_metadata_generic_descriptor_parent_class)->handle_tag (metadata,
3992           primer, tag, tag_data, tag_size);
3993       break;
3994   }
3995 
3996   return ret;
3997 
3998 error:
3999 
4000   GST_ERROR ("Invalid generic descriptor local tag 0x%04x of size %u", tag,
4001       tag_size);
4002 
4003   return FALSE;
4004 }
4005 
4006 static gboolean
mxf_metadata_generic_descriptor_resolve(MXFMetadataBase * m,GHashTable * metadata)4007 mxf_metadata_generic_descriptor_resolve (MXFMetadataBase * m,
4008     GHashTable * metadata)
4009 {
4010   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
4011   MXFMetadataBase *current = NULL;
4012   guint i;
4013   gboolean have_locator = FALSE;
4014 #ifndef GST_DISABLE_GST_DEBUG
4015   gchar str[48];
4016 #endif
4017 
4018   if (self->locators)
4019     memset (self->locators, 0, sizeof (gpointer) * self->n_locators);
4020   else
4021     self->locators = g_new0 (MXFMetadataLocator *, self->n_locators);
4022   for (i = 0; i < self->n_locators; i++) {
4023     current = g_hash_table_lookup (metadata, &self->locators_uids[i]);
4024     if (current && MXF_IS_METADATA_LOCATOR (current)) {
4025       if (mxf_metadata_base_resolve (current, metadata)) {
4026         self->locators[i] = MXF_METADATA_LOCATOR (current);
4027         have_locator = TRUE;
4028       } else {
4029         GST_ERROR ("Couldn't resolve locator %s",
4030             mxf_uuid_to_string (&self->locators_uids[i], str));
4031       }
4032     } else {
4033       GST_ERROR ("Locator %s not found",
4034           mxf_uuid_to_string (&self->locators_uids[i], str));
4035     }
4036   }
4037 
4038   if (!have_locator && self->n_locators > 0) {
4039     GST_ERROR ("Couldn't resolve a locator");
4040     return FALSE;
4041   }
4042 
4043   return
4044       MXF_METADATA_BASE_CLASS
4045       (mxf_metadata_generic_descriptor_parent_class)->resolve (m, metadata);
4046 }
4047 
4048 static GstStructure *
mxf_metadata_generic_descriptor_to_structure(MXFMetadataBase * m)4049 mxf_metadata_generic_descriptor_to_structure (MXFMetadataBase * m)
4050 {
4051   GstStructure *ret =
4052       MXF_METADATA_BASE_CLASS
4053       (mxf_metadata_generic_descriptor_parent_class)->to_structure (m);
4054   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
4055   guint i;
4056 
4057   if (self->n_locators > 0) {
4058     GValue arr = { 0, }
4059     , val = {
4060     0,};
4061 
4062     g_value_init (&arr, GST_TYPE_ARRAY);
4063 
4064     for (i = 0; i < self->n_locators; i++) {
4065       GstStructure *s;
4066 
4067       if (self->locators[i] == NULL)
4068         continue;
4069 
4070       g_value_init (&val, GST_TYPE_STRUCTURE);
4071 
4072       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->locators
4073               [i]));
4074       gst_value_set_structure (&val, s);
4075       gst_structure_free (s);
4076       gst_value_array_append_value (&arr, &val);
4077       g_value_unset (&val);
4078     }
4079 
4080     if (gst_value_array_get_size (&arr) > 0)
4081       gst_structure_id_set_value (ret, MXF_QUARK (LOCATORS), &arr);
4082 
4083     g_value_unset (&arr);
4084   }
4085 
4086   return ret;
4087 }
4088 
4089 static GList *
mxf_metadata_generic_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)4090 mxf_metadata_generic_descriptor_write_tags (MXFMetadataBase * m,
4091     MXFPrimerPack * primer)
4092 {
4093   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
4094   GList *ret =
4095       MXF_METADATA_BASE_CLASS
4096       (mxf_metadata_generic_descriptor_parent_class)->write_tags (m, primer);
4097   MXFLocalTag *t;
4098 
4099   if (self->locators) {
4100     guint i;
4101 
4102     t = g_slice_new0 (MXFLocalTag);
4103     memcpy (&t->ul, MXF_UL (LOCATORS), 16);
4104     t->size = 8 + 16 * self->n_locators;
4105     t->data = g_slice_alloc0 (t->size);
4106     t->g_slice = TRUE;
4107     GST_WRITE_UINT32_BE (t->data, self->n_locators);
4108     GST_WRITE_UINT32_BE (t->data + 4, 16);
4109     for (i = 0; i < self->n_locators; i++) {
4110       if (!self->locators[i])
4111         continue;
4112       memcpy (t->data + 8 + 16 * i,
4113           &MXF_METADATA_BASE (self->locators[i])->instance_uid, 16);
4114     }
4115     mxf_primer_pack_add_mapping (primer, 0x2f01, &t->ul);
4116     ret = g_list_prepend (ret, t);
4117   }
4118 
4119   return ret;
4120 }
4121 
4122 static void
mxf_metadata_generic_descriptor_init(MXFMetadataGenericDescriptor * self)4123 mxf_metadata_generic_descriptor_init (MXFMetadataGenericDescriptor * self)
4124 {
4125 
4126 }
4127 
4128 static void
mxf_metadata_generic_descriptor_class_init(MXFMetadataGenericDescriptorClass * klass)4129 mxf_metadata_generic_descriptor_class_init (MXFMetadataGenericDescriptorClass *
4130     klass)
4131 {
4132   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4133   GObjectClass *object_class = (GObjectClass *) klass;
4134 
4135   object_class->finalize = mxf_metadata_generic_descriptor_finalize;
4136   metadata_base_class->handle_tag = mxf_metadata_generic_descriptor_handle_tag;
4137   metadata_base_class->resolve = mxf_metadata_generic_descriptor_resolve;
4138   metadata_base_class->to_structure =
4139       mxf_metadata_generic_descriptor_to_structure;
4140   metadata_base_class->write_tags = mxf_metadata_generic_descriptor_write_tags;
4141 }
4142 
4143 G_DEFINE_TYPE (MXFMetadataFileDescriptor, mxf_metadata_file_descriptor,
4144     MXF_TYPE_METADATA_GENERIC_DESCRIPTOR);
4145 
4146 static gboolean
mxf_metadata_file_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)4147 mxf_metadata_file_descriptor_handle_tag (MXFMetadataBase * metadata,
4148     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4149     guint tag_size)
4150 {
4151   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (metadata);
4152   gboolean ret = TRUE;
4153 #ifndef GST_DISABLE_GST_DEBUG
4154   gchar str[48];
4155 #endif
4156 
4157   switch (tag) {
4158     case 0x3006:
4159       if (tag_size != 4)
4160         goto error;
4161       self->linked_track_id = GST_READ_UINT32_BE (tag_data);
4162       GST_DEBUG ("  linked track id = %u", self->linked_track_id);
4163       break;
4164     case 0x3001:
4165       if (!mxf_fraction_parse (&self->sample_rate, tag_data, tag_size))
4166         goto error;
4167       GST_DEBUG ("  sample rate = %d/%d", self->sample_rate.n,
4168           self->sample_rate.d);
4169       break;
4170     case 0x3002:
4171       if (tag_size != 8)
4172         goto error;
4173       self->container_duration = GST_READ_UINT64_BE (tag_data);
4174       GST_DEBUG ("  container duration = %" G_GINT64_FORMAT,
4175           self->container_duration);
4176       break;
4177     case 0x3004:
4178       if (tag_size != 16)
4179         goto error;
4180       memcpy (&self->essence_container, tag_data, 16);
4181       GST_DEBUG ("  essence container = %s",
4182           mxf_ul_to_string (&self->essence_container, str));
4183       break;
4184     case 0x3005:
4185       if (tag_size != 16)
4186         goto error;
4187       memcpy (&self->codec, tag_data, 16);
4188       GST_DEBUG ("  codec = %s", mxf_ul_to_string (&self->codec, str));
4189       break;
4190     default:
4191       ret =
4192           MXF_METADATA_BASE_CLASS
4193           (mxf_metadata_file_descriptor_parent_class)->handle_tag (metadata,
4194           primer, tag, tag_data, tag_size);
4195       break;
4196   }
4197 
4198   return ret;
4199 
4200 error:
4201 
4202   GST_ERROR ("Invalid file descriptor local tag 0x%04x of size %u", tag,
4203       tag_size);
4204 
4205   return FALSE;
4206 }
4207 
4208 static GstStructure *
mxf_metadata_file_descriptor_to_structure(MXFMetadataBase * m)4209 mxf_metadata_file_descriptor_to_structure (MXFMetadataBase * m)
4210 {
4211   GstStructure *ret =
4212       MXF_METADATA_BASE_CLASS
4213       (mxf_metadata_file_descriptor_parent_class)->to_structure (m);
4214   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (m);
4215   gchar str[48];
4216 
4217   if (self->linked_track_id)
4218     gst_structure_id_set (ret, MXF_QUARK (LINKED_TRACK_ID), G_TYPE_UINT,
4219         self->linked_track_id, NULL);
4220 
4221   if (self->sample_rate.n && self->sample_rate.d)
4222     gst_structure_id_set (ret, MXF_QUARK (SAMPLE_RATE), GST_TYPE_FRACTION,
4223         self->sample_rate.n, self->sample_rate.d, NULL);
4224 
4225   if (self->container_duration)
4226     gst_structure_id_set (ret, MXF_QUARK (CONTAINER_DURATION), G_TYPE_INT64,
4227         self->container_duration, NULL);
4228 
4229   mxf_ul_to_string (&self->essence_container, str);
4230   gst_structure_id_set (ret, MXF_QUARK (ESSENCE_CONTAINER), G_TYPE_STRING, str,
4231       NULL);
4232 
4233   if (!mxf_ul_is_zero (&self->codec)) {
4234     mxf_ul_to_string (&self->codec, str);
4235     gst_structure_id_set (ret, MXF_QUARK (CODEC), G_TYPE_STRING, str, NULL);
4236   }
4237 
4238   return ret;
4239 }
4240 
4241 static GList *
mxf_metadata_file_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)4242 mxf_metadata_file_descriptor_write_tags (MXFMetadataBase * m,
4243     MXFPrimerPack * primer)
4244 {
4245   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (m);
4246   GList *ret =
4247       MXF_METADATA_BASE_CLASS
4248       (mxf_metadata_file_descriptor_parent_class)->write_tags (m, primer);
4249   MXFLocalTag *t;
4250 
4251   if (self->linked_track_id) {
4252     t = g_slice_new0 (MXFLocalTag);
4253     memcpy (&t->ul, MXF_UL (LINKED_TRACK_ID), 16);
4254     t->size = 4;
4255     t->data = g_slice_alloc (t->size);
4256     t->g_slice = TRUE;
4257     GST_WRITE_UINT32_BE (t->data, self->linked_track_id);
4258     mxf_primer_pack_add_mapping (primer, 0x3006, &t->ul);
4259     ret = g_list_prepend (ret, t);
4260   }
4261 
4262   t = g_slice_new0 (MXFLocalTag);
4263   memcpy (&t->ul, MXF_UL (SAMPLE_RATE), 16);
4264   t->size = 8;
4265   t->data = g_slice_alloc (t->size);
4266   t->g_slice = TRUE;
4267   GST_WRITE_UINT32_BE (t->data, self->sample_rate.n);
4268   GST_WRITE_UINT32_BE (t->data + 4, self->sample_rate.d);
4269   mxf_primer_pack_add_mapping (primer, 0x3001, &t->ul);
4270   ret = g_list_prepend (ret, t);
4271 
4272   if (self->container_duration > 0) {
4273     t = g_slice_new0 (MXFLocalTag);
4274     memcpy (&t->ul, MXF_UL (CONTAINER_DURATION), 16);
4275     t->size = 8;
4276     t->data = g_slice_alloc (t->size);
4277     t->g_slice = TRUE;
4278     GST_WRITE_UINT64_BE (t->data, self->container_duration);
4279     mxf_primer_pack_add_mapping (primer, 0x3002, &t->ul);
4280     ret = g_list_prepend (ret, t);
4281   }
4282 
4283   t = g_slice_new0 (MXFLocalTag);
4284   memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINER), 16);
4285   t->size = 16;
4286   t->data = g_slice_alloc (t->size);
4287   t->g_slice = TRUE;
4288   memcpy (t->data, &self->essence_container, 16);
4289   mxf_primer_pack_add_mapping (primer, 0x3004, &t->ul);
4290   ret = g_list_prepend (ret, t);
4291 
4292   if (!mxf_ul_is_zero (&self->codec)) {
4293     t = g_slice_new0 (MXFLocalTag);
4294     memcpy (&t->ul, MXF_UL (CODEC), 16);
4295     t->size = 16;
4296     t->data = g_slice_alloc (t->size);
4297     t->g_slice = TRUE;
4298     memcpy (t->data, &self->codec, 16);
4299     mxf_primer_pack_add_mapping (primer, 0x3005, &t->ul);
4300     ret = g_list_prepend (ret, t);
4301   }
4302 
4303   return ret;
4304 }
4305 
4306 static void
mxf_metadata_file_descriptor_init(MXFMetadataFileDescriptor * self)4307 mxf_metadata_file_descriptor_init (MXFMetadataFileDescriptor * self)
4308 {
4309 
4310 }
4311 
4312 static void
mxf_metadata_file_descriptor_class_init(MXFMetadataFileDescriptorClass * klass)4313 mxf_metadata_file_descriptor_class_init (MXFMetadataFileDescriptorClass * klass)
4314 {
4315   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4316   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
4317 
4318   metadata_base_class->handle_tag = mxf_metadata_file_descriptor_handle_tag;
4319   metadata_base_class->name_quark = MXF_QUARK (FILE_DESCRIPTOR);
4320   metadata_base_class->to_structure = mxf_metadata_file_descriptor_to_structure;
4321   metadata_base_class->write_tags = mxf_metadata_file_descriptor_write_tags;
4322   metadata_class->type = 0x0125;
4323 }
4324 
4325 G_DEFINE_TYPE (MXFMetadataGenericPictureEssenceDescriptor,
4326     mxf_metadata_generic_picture_essence_descriptor,
4327     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
4328 
4329 static gboolean
mxf_metadata_generic_picture_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)4330 mxf_metadata_generic_picture_essence_descriptor_handle_tag (MXFMetadataBase *
4331     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4332     guint tag_size)
4333 {
4334   MXFMetadataGenericPictureEssenceDescriptor *self =
4335       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (metadata);
4336   gboolean ret = TRUE;
4337 #ifndef GST_DISABLE_GST_DEBUG
4338   gchar str[48];
4339 #endif
4340 
4341   switch (tag) {
4342     case 0x3215:
4343       if (tag_size != 1)
4344         goto error;
4345       self->signal_standard = GST_READ_UINT8 (tag_data);
4346       GST_DEBUG ("  signal standard = %u", self->signal_standard);
4347       break;
4348     case 0x320c:
4349       if (tag_size != 1)
4350         goto error;
4351       self->frame_layout = GST_READ_UINT8 (tag_data);
4352       GST_DEBUG ("  frame layout = %u", self->frame_layout);
4353       break;
4354     case 0x3203:
4355       if (tag_size != 4)
4356         goto error;
4357       self->stored_width = GST_READ_UINT32_BE (tag_data);
4358       GST_DEBUG ("  stored width = %u", self->stored_width);
4359       break;
4360     case 0x3202:
4361       if (tag_size != 4)
4362         goto error;
4363       self->stored_height = GST_READ_UINT32_BE (tag_data);
4364       GST_DEBUG ("  stored height = %u", self->stored_height);
4365       break;
4366     case 0x3216:
4367       if (tag_size != 4)
4368         goto error;
4369       self->stored_f2_offset = GST_READ_UINT32_BE (tag_data);
4370       GST_DEBUG ("  stored f2 offset = %d", self->stored_f2_offset);
4371       break;
4372     case 0x3205:
4373       if (tag_size != 4)
4374         goto error;
4375       self->sampled_width = GST_READ_UINT32_BE (tag_data);
4376       GST_DEBUG ("  sampled width = %u", self->sampled_width);
4377       break;
4378     case 0x3204:
4379       if (tag_size != 4)
4380         goto error;
4381       self->sampled_height = GST_READ_UINT32_BE (tag_data);
4382       GST_DEBUG ("  sampled height = %u", self->sampled_height);
4383       break;
4384     case 0x3206:
4385       if (tag_size != 4)
4386         goto error;
4387       self->sampled_x_offset = GST_READ_UINT32_BE (tag_data);
4388       GST_DEBUG ("  sampled x offset = %d", self->sampled_x_offset);
4389       break;
4390     case 0x3207:
4391       if (tag_size != 4)
4392         goto error;
4393       self->sampled_y_offset = GST_READ_UINT32_BE (tag_data);
4394       GST_DEBUG ("  sampled y offset = %d", self->sampled_y_offset);
4395       break;
4396     case 0x3208:
4397       if (tag_size != 4)
4398         goto error;
4399       self->display_height = GST_READ_UINT32_BE (tag_data);
4400       GST_DEBUG ("  display height = %u", self->display_height);
4401       break;
4402     case 0x3209:
4403       if (tag_size != 4)
4404         goto error;
4405       self->display_width = GST_READ_UINT32_BE (tag_data);
4406       GST_DEBUG ("  display width = %u", self->display_width);
4407       break;
4408     case 0x320a:
4409       if (tag_size != 4)
4410         goto error;
4411       self->display_x_offset = GST_READ_UINT32_BE (tag_data);
4412       GST_DEBUG ("  display x offset = %d", self->display_x_offset);
4413       break;
4414     case 0x320b:
4415       if (tag_size != 4)
4416         goto error;
4417       self->display_y_offset = GST_READ_UINT32_BE (tag_data);
4418       GST_DEBUG ("  display y offset = %d", self->display_y_offset);
4419       break;
4420     case 0x3217:
4421       if (tag_size != 4)
4422         goto error;
4423       self->display_f2_offset = GST_READ_UINT32_BE (tag_data);
4424       GST_DEBUG ("  display f2 offset = %d", self->display_f2_offset);
4425       break;
4426     case 0x320e:
4427       if (!mxf_fraction_parse (&self->aspect_ratio, tag_data, tag_size))
4428         goto error;
4429       GST_DEBUG ("  aspect ratio = %d/%d", self->aspect_ratio.n,
4430           self->aspect_ratio.d);
4431       break;
4432     case 0x3218:
4433       if (tag_size != 1)
4434         goto error;
4435       self->active_format_descriptor = GST_READ_UINT8 (tag_data);
4436       GST_DEBUG ("  active format descriptor = %u",
4437           self->active_format_descriptor);
4438       break;
4439     case 0x320d:
4440       if (tag_size < 8)
4441         goto error;
4442 
4443       if (GST_READ_UINT32_BE (tag_data) == 0)
4444         return TRUE;
4445 
4446       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
4447         goto error;
4448 
4449       if (GST_READ_UINT32_BE (tag_data) != 1 &&
4450           GST_READ_UINT32_BE (tag_data) != 2)
4451         goto error;
4452 
4453       if ((GST_READ_UINT32_BE (tag_data) == 1 && tag_size != 12) ||
4454           (GST_READ_UINT32_BE (tag_data) == 2 && tag_size != 16))
4455         goto error;
4456 
4457       self->video_line_map[0] = GST_READ_UINT32_BE (tag_data + 8);
4458 
4459       /* Workaround for files created by ffmpeg */
4460       if (GST_READ_UINT32_BE (tag_data) == 1)
4461         self->video_line_map[0] = 0;
4462       else
4463         self->video_line_map[1] = GST_READ_UINT32_BE (tag_data + 12);
4464 
4465       GST_DEBUG ("  video line map = {%i, %i}", self->video_line_map[0],
4466           self->video_line_map[1]);
4467       break;
4468     case 0x320f:
4469       if (tag_size != 1)
4470         goto error;
4471       self->alpha_transparency = GST_READ_UINT8 (tag_data);
4472       GST_DEBUG ("  alpha transparency = %u", self->alpha_transparency);
4473       break;
4474     case 0x3210:
4475       if (tag_size != 16)
4476         goto error;
4477       memcpy (&self->capture_gamma, tag_data, 16);
4478       GST_DEBUG ("  capture gamma = %s",
4479           mxf_ul_to_string (&self->capture_gamma, str));
4480       break;
4481     case 0x3211:
4482       if (tag_size != 4)
4483         goto error;
4484       self->image_alignment_offset = GST_READ_UINT32_BE (tag_data);
4485       GST_DEBUG ("  image alignment offset = %u", self->image_alignment_offset);
4486       break;
4487     case 0x3213:
4488       if (tag_size != 4)
4489         goto error;
4490       self->image_start_offset = GST_READ_UINT32_BE (tag_data);
4491       GST_DEBUG ("  image start offset = %u", self->image_start_offset);
4492       break;
4493     case 0x3214:
4494       if (tag_size != 4)
4495         goto error;
4496       self->image_end_offset = GST_READ_UINT32_BE (tag_data);
4497       GST_DEBUG ("  image end offset = %u", self->image_end_offset);
4498       break;
4499     case 0x3212:
4500       if (tag_size != 1)
4501         goto error;
4502       self->field_dominance = GST_READ_UINT8 (tag_data);
4503       GST_DEBUG ("  field dominance = %u", self->field_dominance);
4504       break;
4505     case 0x3201:
4506       if (tag_size != 16)
4507         goto error;
4508       memcpy (&self->picture_essence_coding, tag_data, 16);
4509       GST_DEBUG ("  picture essence coding = %s",
4510           mxf_ul_to_string (&self->picture_essence_coding, str));
4511       break;
4512     default:
4513       ret =
4514           MXF_METADATA_BASE_CLASS
4515           (mxf_metadata_generic_picture_essence_descriptor_parent_class)->handle_tag
4516           (metadata, primer, tag, tag_data, tag_size);
4517       break;
4518   }
4519 
4520   return ret;
4521 
4522 error:
4523 
4524   GST_ERROR
4525       ("Invalid generic picture essence descriptor local tag 0x%04x of size %u",
4526       tag, tag_size);
4527 
4528   return FALSE;
4529 }
4530 
4531 static GstStructure *
mxf_metadata_generic_picture_essence_descriptor_to_structure(MXFMetadataBase * m)4532 mxf_metadata_generic_picture_essence_descriptor_to_structure (MXFMetadataBase *
4533     m)
4534 {
4535   GstStructure *ret =
4536       MXF_METADATA_BASE_CLASS
4537       (mxf_metadata_generic_picture_essence_descriptor_parent_class)->to_structure
4538       (m);
4539   MXFMetadataGenericPictureEssenceDescriptor *self =
4540       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (m);
4541   gchar str[48];
4542 
4543   gst_structure_id_set (ret, MXF_QUARK (SIGNAL_STANDARD), G_TYPE_UCHAR,
4544       self->signal_standard, NULL);
4545 
4546   gst_structure_id_set (ret, MXF_QUARK (FRAME_LAYOUT), G_TYPE_UCHAR,
4547       self->frame_layout, NULL);
4548 
4549   gst_structure_id_set (ret, MXF_QUARK (STORED_WIDTH), G_TYPE_UINT,
4550       self->stored_width, MXF_QUARK (STORED_HEIGHT), G_TYPE_UINT,
4551       self->stored_height, NULL);
4552 
4553   if (self->stored_f2_offset != 0)
4554     gst_structure_id_set (ret, MXF_QUARK (STORED_F2_OFFSET), G_TYPE_INT,
4555         self->stored_f2_offset, NULL);
4556 
4557   if (self->sampled_width != 0 && self->sampled_height != 0)
4558     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_WIDTH), G_TYPE_UINT,
4559         self->sampled_width, MXF_QUARK (SAMPLED_HEIGHT), G_TYPE_UINT,
4560         self->sampled_height, NULL);
4561 
4562   if (self->sampled_x_offset != 0)
4563     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_X_OFFSET), G_TYPE_INT,
4564         self->sampled_x_offset, NULL);
4565 
4566   if (self->sampled_y_offset != 0)
4567     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_Y_OFFSET), G_TYPE_INT,
4568         self->sampled_y_offset, NULL);
4569 
4570   if (self->display_width != 0 && self->display_height != 0)
4571     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_WIDTH), G_TYPE_UINT,
4572         self->display_width, MXF_QUARK (DISPLAY_HEIGHT), G_TYPE_UINT,
4573         self->display_height, NULL);
4574 
4575   if (self->display_x_offset != 0)
4576     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_X_OFFSET), G_TYPE_INT,
4577         self->display_x_offset, NULL);
4578 
4579   if (self->display_y_offset != 0)
4580     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_Y_OFFSET), G_TYPE_INT,
4581         self->display_y_offset, NULL);
4582 
4583   if (self->display_f2_offset != 0)
4584     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_F2_OFFSET), G_TYPE_INT,
4585         self->display_f2_offset, NULL);
4586 
4587   if (self->aspect_ratio.n != 0 && self->aspect_ratio.d != 0)
4588     gst_structure_id_set (ret, MXF_QUARK (ASPECT_RATIO), GST_TYPE_FRACTION,
4589         self->aspect_ratio.n, self->aspect_ratio.d, NULL);
4590 
4591   if (self->active_format_descriptor)
4592     gst_structure_id_set (ret, MXF_QUARK (ACTIVE_FORMAT_DESCRIPTOR),
4593         G_TYPE_UCHAR, self->active_format_descriptor, NULL);
4594 
4595   gst_structure_id_set (ret, MXF_QUARK (VIDEO_LINE_MAP_0), G_TYPE_UINT,
4596       self->video_line_map[0], MXF_QUARK (VIDEO_LINE_MAP_1), G_TYPE_UINT,
4597       self->video_line_map[1], NULL);
4598 
4599   if (self->alpha_transparency != 0)
4600     gst_structure_id_set (ret, MXF_QUARK (ALPHA_TRANSPARENCY), G_TYPE_UCHAR,
4601         self->alpha_transparency, NULL);
4602 
4603   if (!mxf_ul_is_zero (&self->capture_gamma)) {
4604     mxf_ul_to_string (&self->capture_gamma, str);
4605     gst_structure_id_set (ret, MXF_QUARK (CAPTURE_GAMMA), G_TYPE_STRING, str,
4606         NULL);
4607   }
4608 
4609   if (self->image_alignment_offset != 0)
4610     gst_structure_id_set (ret, MXF_QUARK (IMAGE_ALIGNMENT_OFFSET), G_TYPE_UINT,
4611         self->image_alignment_offset, NULL);
4612 
4613   if (self->image_start_offset != 0)
4614     gst_structure_id_set (ret, MXF_QUARK (IMAGE_START_OFFSET), G_TYPE_UINT,
4615         self->image_start_offset, NULL);
4616 
4617   if (self->image_end_offset != 0)
4618     gst_structure_id_set (ret, MXF_QUARK (IMAGE_END_OFFSET), G_TYPE_UINT,
4619         self->image_end_offset, NULL);
4620 
4621   if (self->field_dominance != 0)
4622     gst_structure_id_set (ret, MXF_QUARK (FIELD_DOMINANCE), G_TYPE_UCHAR,
4623         self->field_dominance, NULL);
4624 
4625   if (!mxf_ul_is_zero (&self->picture_essence_coding)) {
4626     mxf_ul_to_string (&self->picture_essence_coding, str);
4627     gst_structure_id_set (ret, MXF_QUARK (PICTURE_ESSENCE_CODING),
4628         G_TYPE_STRING, str, NULL);
4629   }
4630 
4631   return ret;
4632 }
4633 
4634 static GList *
mxf_metadata_generic_picture_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)4635 mxf_metadata_generic_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
4636     MXFPrimerPack * primer)
4637 {
4638   MXFMetadataGenericPictureEssenceDescriptor *self =
4639       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (m);
4640   GList *ret =
4641       MXF_METADATA_BASE_CLASS
4642       (mxf_metadata_generic_picture_essence_descriptor_parent_class)->write_tags
4643       (m, primer);
4644   MXFLocalTag *t;
4645 
4646   if (self->signal_standard != 1) {
4647     t = g_slice_new0 (MXFLocalTag);
4648     memcpy (&t->ul, MXF_UL (SIGNAL_STANDARD), 16);
4649     t->size = 1;
4650     t->data = g_slice_alloc (t->size);
4651     t->g_slice = TRUE;
4652     GST_WRITE_UINT8 (t->data, self->signal_standard);
4653     mxf_primer_pack_add_mapping (primer, 0x3215, &t->ul);
4654     ret = g_list_prepend (ret, t);
4655   }
4656 
4657   t = g_slice_new0 (MXFLocalTag);
4658   memcpy (&t->ul, MXF_UL (FRAME_LAYOUT), 16);
4659   t->size = 1;
4660   t->data = g_slice_alloc (t->size);
4661   t->g_slice = TRUE;
4662   GST_WRITE_UINT8 (t->data, self->frame_layout);
4663   mxf_primer_pack_add_mapping (primer, 0x320c, &t->ul);
4664   ret = g_list_prepend (ret, t);
4665 
4666   t = g_slice_new0 (MXFLocalTag);
4667   memcpy (&t->ul, MXF_UL (STORED_WIDTH), 16);
4668   t->size = 4;
4669   t->data = g_slice_alloc (t->size);
4670   t->g_slice = TRUE;
4671   GST_WRITE_UINT32_BE (t->data, self->stored_width);
4672   mxf_primer_pack_add_mapping (primer, 0x3203, &t->ul);
4673   ret = g_list_prepend (ret, t);
4674 
4675   t = g_slice_new0 (MXFLocalTag);
4676   memcpy (&t->ul, MXF_UL (STORED_HEIGHT), 16);
4677   t->size = 4;
4678   t->data = g_slice_alloc (t->size);
4679   t->g_slice = TRUE;
4680   GST_WRITE_UINT32_BE (t->data, self->stored_height);
4681   mxf_primer_pack_add_mapping (primer, 0x3202, &t->ul);
4682   ret = g_list_prepend (ret, t);
4683 
4684   if (self->stored_f2_offset != 0) {
4685     t = g_slice_new0 (MXFLocalTag);
4686     memcpy (&t->ul, MXF_UL (STORED_F2_OFFSET), 16);
4687     t->size = 4;
4688     t->data = g_slice_alloc (t->size);
4689     t->g_slice = TRUE;
4690     GST_WRITE_UINT32_BE (t->data, self->stored_f2_offset);
4691     mxf_primer_pack_add_mapping (primer, 0x3216, &t->ul);
4692     ret = g_list_prepend (ret, t);
4693   }
4694 
4695   if (self->sampled_width != 0) {
4696     t = g_slice_new0 (MXFLocalTag);
4697     memcpy (&t->ul, MXF_UL (SAMPLED_WIDTH), 16);
4698     t->size = 4;
4699     t->data = g_slice_alloc (t->size);
4700     t->g_slice = TRUE;
4701     GST_WRITE_UINT32_BE (t->data, self->sampled_width);
4702     mxf_primer_pack_add_mapping (primer, 0x3205, &t->ul);
4703     ret = g_list_prepend (ret, t);
4704   }
4705 
4706   if (self->sampled_height != 0) {
4707     t = g_slice_new0 (MXFLocalTag);
4708     memcpy (&t->ul, MXF_UL (SAMPLED_HEIGHT), 16);
4709     t->size = 4;
4710     t->data = g_slice_alloc (t->size);
4711     t->g_slice = TRUE;
4712     GST_WRITE_UINT32_BE (t->data, self->sampled_height);
4713     mxf_primer_pack_add_mapping (primer, 0x3204, &t->ul);
4714     ret = g_list_prepend (ret, t);
4715   }
4716 
4717   if (self->sampled_x_offset != 0) {
4718     t = g_slice_new0 (MXFLocalTag);
4719     memcpy (&t->ul, MXF_UL (SAMPLED_X_OFFSET), 16);
4720     t->size = 4;
4721     t->data = g_slice_alloc (t->size);
4722     t->g_slice = TRUE;
4723     GST_WRITE_UINT32_BE (t->data, self->sampled_x_offset);
4724     mxf_primer_pack_add_mapping (primer, 0x3206, &t->ul);
4725     ret = g_list_prepend (ret, t);
4726   }
4727 
4728   if (self->sampled_y_offset != 0) {
4729     t = g_slice_new0 (MXFLocalTag);
4730     memcpy (&t->ul, MXF_UL (SAMPLED_Y_OFFSET), 16);
4731     t->size = 4;
4732     t->data = g_slice_alloc (t->size);
4733     t->g_slice = TRUE;
4734     GST_WRITE_UINT32_BE (t->data, self->sampled_y_offset);
4735     mxf_primer_pack_add_mapping (primer, 0x3207, &t->ul);
4736     ret = g_list_prepend (ret, t);
4737   }
4738 
4739   if (self->display_height != 0) {
4740     t = g_slice_new0 (MXFLocalTag);
4741     memcpy (&t->ul, MXF_UL (DISPLAY_HEIGHT), 16);
4742     t->size = 4;
4743     t->data = g_slice_alloc (t->size);
4744     t->g_slice = TRUE;
4745     GST_WRITE_UINT32_BE (t->data, self->display_height);
4746     mxf_primer_pack_add_mapping (primer, 0x3208, &t->ul);
4747     ret = g_list_prepend (ret, t);
4748   }
4749 
4750   if (self->display_width != 0) {
4751     t = g_slice_new0 (MXFLocalTag);
4752     memcpy (&t->ul, MXF_UL (DISPLAY_WIDTH), 16);
4753     t->size = 4;
4754     t->data = g_slice_alloc (t->size);
4755     t->g_slice = TRUE;
4756     GST_WRITE_UINT32_BE (t->data, self->display_width);
4757     mxf_primer_pack_add_mapping (primer, 0x3209, &t->ul);
4758     ret = g_list_prepend (ret, t);
4759   }
4760 
4761   if (self->display_x_offset != 0) {
4762     t = g_slice_new0 (MXFLocalTag);
4763     memcpy (&t->ul, MXF_UL (DISPLAY_X_OFFSET), 16);
4764     t->size = 4;
4765     t->data = g_slice_alloc (t->size);
4766     t->g_slice = TRUE;
4767     GST_WRITE_UINT32_BE (t->data, self->display_x_offset);
4768     mxf_primer_pack_add_mapping (primer, 0x320a, &t->ul);
4769     ret = g_list_prepend (ret, t);
4770   }
4771 
4772   if (self->display_y_offset != 0) {
4773     t = g_slice_new0 (MXFLocalTag);
4774     memcpy (&t->ul, MXF_UL (DISPLAY_Y_OFFSET), 16);
4775     t->size = 4;
4776     t->data = g_slice_alloc (t->size);
4777     t->g_slice = TRUE;
4778     GST_WRITE_UINT32_BE (t->data, self->display_y_offset);
4779     mxf_primer_pack_add_mapping (primer, 0x320b, &t->ul);
4780     ret = g_list_prepend (ret, t);
4781   }
4782 
4783   if (self->display_f2_offset != 0) {
4784     t = g_slice_new0 (MXFLocalTag);
4785     memcpy (&t->ul, MXF_UL (DISPLAY_F2_OFFSET), 16);
4786     t->size = 4;
4787     t->data = g_slice_alloc (t->size);
4788     t->g_slice = TRUE;
4789     GST_WRITE_UINT32_BE (t->data, self->display_f2_offset);
4790     mxf_primer_pack_add_mapping (primer, 0x3217, &t->ul);
4791     ret = g_list_prepend (ret, t);
4792   }
4793 
4794   t = g_slice_new0 (MXFLocalTag);
4795   memcpy (&t->ul, MXF_UL (ASPECT_RATIO), 16);
4796   t->size = 8;
4797   t->data = g_slice_alloc (t->size);
4798   t->g_slice = TRUE;
4799   GST_WRITE_UINT32_BE (t->data, self->aspect_ratio.n);
4800   GST_WRITE_UINT32_BE (t->data + 4, self->aspect_ratio.d);
4801   mxf_primer_pack_add_mapping (primer, 0x320e, &t->ul);
4802   ret = g_list_prepend (ret, t);
4803 
4804   if (self->active_format_descriptor != 0) {
4805     t = g_slice_new0 (MXFLocalTag);
4806     memcpy (&t->ul, MXF_UL (ACTIVE_FORMAT_DESCRIPTOR), 16);
4807     t->size = 1;
4808     t->data = g_slice_alloc (t->size);
4809     t->g_slice = TRUE;
4810     GST_WRITE_UINT8 (t->data, self->active_format_descriptor);
4811     mxf_primer_pack_add_mapping (primer, 0x3218, &t->ul);
4812     ret = g_list_prepend (ret, t);
4813   }
4814 
4815   t = g_slice_new0 (MXFLocalTag);
4816   memcpy (&t->ul, MXF_UL (VIDEO_LINE_MAP), 16);
4817   t->size = 16;
4818   t->data = g_slice_alloc (t->size);
4819   t->g_slice = TRUE;
4820   GST_WRITE_UINT32_BE (t->data, 2);
4821   GST_WRITE_UINT32_BE (t->data + 4, 4);
4822   GST_WRITE_UINT32_BE (t->data + 8, self->video_line_map[0]);
4823   GST_WRITE_UINT32_BE (t->data + 12, self->video_line_map[1]);
4824   mxf_primer_pack_add_mapping (primer, 0x320d, &t->ul);
4825   ret = g_list_prepend (ret, t);
4826 
4827   if (self->alpha_transparency != 0) {
4828     t = g_slice_new0 (MXFLocalTag);
4829     memcpy (&t->ul, MXF_UL (ALPHA_TRANSPARENCY), 16);
4830     t->size = 1;
4831     t->data = g_slice_alloc (t->size);
4832     t->g_slice = TRUE;
4833     GST_WRITE_UINT8 (t->data, self->alpha_transparency);
4834     mxf_primer_pack_add_mapping (primer, 0x320f, &t->ul);
4835     ret = g_list_prepend (ret, t);
4836   }
4837 
4838   if (!mxf_ul_is_zero (&self->capture_gamma)) {
4839     t = g_slice_new0 (MXFLocalTag);
4840     memcpy (&t->ul, MXF_UL (CAPTURE_GAMMA), 16);
4841     t->size = 16;
4842     t->data = g_slice_alloc (t->size);
4843     t->g_slice = TRUE;
4844     memcpy (t->data, &self->capture_gamma, 16);
4845     mxf_primer_pack_add_mapping (primer, 0x3210, &t->ul);
4846     ret = g_list_prepend (ret, t);
4847   }
4848 
4849   if (self->image_alignment_offset != 0) {
4850     t = g_slice_new0 (MXFLocalTag);
4851     memcpy (&t->ul, MXF_UL (IMAGE_ALIGNMENT_OFFSET), 16);
4852     t->size = 4;
4853     t->data = g_slice_alloc (t->size);
4854     t->g_slice = TRUE;
4855     GST_WRITE_UINT32_BE (t->data, self->image_alignment_offset);
4856     mxf_primer_pack_add_mapping (primer, 0x3211, &t->ul);
4857     ret = g_list_prepend (ret, t);
4858   }
4859 
4860   if (self->image_start_offset != 0) {
4861     t = g_slice_new0 (MXFLocalTag);
4862     memcpy (&t->ul, MXF_UL (IMAGE_START_OFFSET), 16);
4863     t->size = 4;
4864     t->data = g_slice_alloc (t->size);
4865     t->g_slice = TRUE;
4866     GST_WRITE_UINT32_BE (t->data, self->image_start_offset);
4867     mxf_primer_pack_add_mapping (primer, 0x3213, &t->ul);
4868     ret = g_list_prepend (ret, t);
4869   }
4870 
4871   if (self->image_end_offset != 0) {
4872     t = g_slice_new0 (MXFLocalTag);
4873     memcpy (&t->ul, MXF_UL (IMAGE_END_OFFSET), 16);
4874     t->size = 4;
4875     t->data = g_slice_alloc (t->size);
4876     t->g_slice = TRUE;
4877     GST_WRITE_UINT32_BE (t->data, self->image_end_offset);
4878     mxf_primer_pack_add_mapping (primer, 0x3214, &t->ul);
4879     ret = g_list_prepend (ret, t);
4880   }
4881 
4882   if (self->field_dominance != 0) {
4883     t = g_slice_new0 (MXFLocalTag);
4884     memcpy (&t->ul, MXF_UL (FIELD_DOMINANCE), 16);
4885     t->size = 1;
4886     t->data = g_slice_alloc (t->size);
4887     t->g_slice = TRUE;
4888     GST_WRITE_UINT8 (t->data, self->field_dominance);
4889     mxf_primer_pack_add_mapping (primer, 0x3212, &t->ul);
4890     ret = g_list_prepend (ret, t);
4891   }
4892 
4893   if (!mxf_ul_is_zero (&self->picture_essence_coding)) {
4894     t = g_slice_new0 (MXFLocalTag);
4895     memcpy (&t->ul, MXF_UL (PICTURE_ESSENCE_CODING), 16);
4896     t->size = 16;
4897     t->data = g_slice_alloc (t->size);
4898     t->g_slice = TRUE;
4899     memcpy (t->data, &self->picture_essence_coding, 16);
4900     mxf_primer_pack_add_mapping (primer, 0x3201, &t->ul);
4901     ret = g_list_prepend (ret, t);
4902   }
4903 
4904   return ret;
4905 }
4906 
4907 static void
mxf_metadata_generic_picture_essence_descriptor_init(MXFMetadataGenericPictureEssenceDescriptor * self)4908     mxf_metadata_generic_picture_essence_descriptor_init
4909     (MXFMetadataGenericPictureEssenceDescriptor * self)
4910 {
4911   self->signal_standard = 1;
4912   self->frame_layout = 255;
4913 }
4914 
4915 static void
mxf_metadata_generic_picture_essence_descriptor_class_init(MXFMetadataGenericPictureEssenceDescriptorClass * klass)4916     mxf_metadata_generic_picture_essence_descriptor_class_init
4917     (MXFMetadataGenericPictureEssenceDescriptorClass * klass)
4918 {
4919   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4920   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
4921 
4922   metadata_base_class->handle_tag =
4923       mxf_metadata_generic_picture_essence_descriptor_handle_tag;
4924   metadata_base_class->name_quark =
4925       MXF_QUARK (GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
4926   metadata_base_class->to_structure =
4927       mxf_metadata_generic_picture_essence_descriptor_to_structure;
4928   metadata_base_class->write_tags =
4929       mxf_metadata_generic_picture_essence_descriptor_write_tags;
4930   metadata_class->type = 0x0127;
4931 }
4932 
mxf_metadata_generic_picture_essence_descriptor_set_caps(MXFMetadataGenericPictureEssenceDescriptor * self,GstCaps * caps)4933 void mxf_metadata_generic_picture_essence_descriptor_set_caps
4934     (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps)
4935 {
4936   guint par_n, par_d;
4937   guint width, height;
4938   MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
4939 
4940   g_return_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (self));
4941   g_return_if_fail (GST_IS_CAPS (caps));
4942 
4943   if (f->sample_rate.d == 0) {
4944     GST_ERROR ("Invalid framerate");
4945   } else {
4946     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, f->sample_rate.n,
4947         f->sample_rate.d, NULL);
4948   }
4949 
4950   width = self->stored_width;
4951   height = self->stored_height;
4952   if (self->sampled_width && self->sampled_height) {
4953     width = self->sampled_width;
4954     height = self->sampled_height;
4955   }
4956   if (self->display_width && self->display_height) {
4957     width = self->display_width;
4958     height = self->display_height;
4959   }
4960 
4961   /* If the video is stored as separate fields the
4962    * height is only the height of one field, i.e.
4963    * half the height of the frame.
4964    *
4965    * See SMPTE 377M E2.2 and E1.2
4966    */
4967   if (self->frame_layout == 1 || self->frame_layout == 2
4968       || self->frame_layout == 4) {
4969     height *= 2;
4970     gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
4971 
4972     if (self->field_dominance == 2) {
4973       gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
4974           "bottom-field-first", NULL);
4975     } else {
4976       gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
4977           "top-field-first", NULL);
4978     }
4979   }
4980 
4981   if (width == 0 || height == 0) {
4982     GST_ERROR ("Invalid width/height");
4983     return;
4984   }
4985 
4986   gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", G_TYPE_INT,
4987       height, NULL);
4988 
4989   if (self->aspect_ratio.n == 0 && self->aspect_ratio.d == 0) {
4990     gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
4991         1, 1, NULL);
4992   } else if (self->aspect_ratio.n == 0 || self->aspect_ratio.d == 0) {
4993     GST_ERROR ("Invalid aspect ratio");
4994   } else {
4995     par_n = height * self->aspect_ratio.n;
4996     par_d = width * self->aspect_ratio.d;
4997 
4998     gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
4999         par_n, par_d, NULL);
5000   }
5001 }
5002 
5003 static gint
gst_greatest_common_divisor(gint a,gint b)5004 gst_greatest_common_divisor (gint a, gint b)
5005 {
5006   while (b != 0) {
5007     int temp = a;
5008 
5009     a = b;
5010     b = temp % b;
5011   }
5012 
5013   return ABS (a);
5014 }
5015 
5016 gboolean
mxf_metadata_generic_picture_essence_descriptor_from_caps(MXFMetadataGenericPictureEssenceDescriptor * self,GstCaps * caps)5017     mxf_metadata_generic_picture_essence_descriptor_from_caps
5018     (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps) {
5019   gint par_n, par_d, gcd;
5020   gint width, height;
5021   gint fps_n, fps_d;
5022   MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
5023   GstStructure *s;
5024   gboolean interlaced = FALSE;
5025   const gchar *field_order = NULL;
5026 
5027   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR
5028       (self), FALSE);
5029   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
5030 
5031   s = gst_caps_get_structure (caps, 0);
5032 
5033   if (!gst_structure_get_boolean (s, "interlaced", &interlaced) || !interlaced) {
5034     self->frame_layout = 0;
5035   } else {
5036     self->frame_layout = 3;
5037     field_order = gst_structure_get_string (s, "field-order");
5038     if (!field_order || strcmp (field_order, "top-field-first") == 0)
5039       self->field_dominance = 1;
5040     else
5041       self->field_dominance = 2;
5042   }
5043 
5044   if (!gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
5045     GST_ERROR ("Invalid framerate");
5046     return FALSE;
5047   }
5048   f->sample_rate.n = fps_n;
5049   f->sample_rate.d = fps_d;
5050 
5051   if (!gst_structure_get_int (s, "width", &width) ||
5052       !gst_structure_get_int (s, "height", &height)) {
5053     GST_ERROR ("Invalid width/height");
5054     return FALSE;
5055   }
5056 
5057   self->stored_width = width;
5058   self->stored_height = height;
5059 
5060   if (!gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d)) {
5061     par_n = 1;
5062     par_d = 1;
5063   }
5064 
5065   self->aspect_ratio.n = par_n * width;
5066   self->aspect_ratio.d = par_d * height;
5067   gcd =
5068       gst_greatest_common_divisor (self->aspect_ratio.n, self->aspect_ratio.d);
5069   self->aspect_ratio.n /= gcd;
5070   self->aspect_ratio.d /= gcd;
5071 
5072   return TRUE;
5073 }
5074 
5075 
5076 G_DEFINE_TYPE (MXFMetadataGenericSoundEssenceDescriptor,
5077     mxf_metadata_generic_sound_essence_descriptor,
5078     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
5079 
5080 static gboolean
mxf_metadata_generic_sound_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5081 mxf_metadata_generic_sound_essence_descriptor_handle_tag (MXFMetadataBase *
5082     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5083     guint tag_size)
5084 {
5085   MXFMetadataGenericSoundEssenceDescriptor *self =
5086       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (metadata);
5087   gboolean ret = TRUE;
5088 #ifndef GST_DISABLE_GST_DEBUG
5089   gchar str[48];
5090 #endif
5091 
5092   switch (tag) {
5093     case 0x3d03:
5094       if (!mxf_fraction_parse (&self->audio_sampling_rate, tag_data, tag_size))
5095         goto error;
5096       GST_DEBUG ("  audio sampling rate = %d/%d",
5097           self->audio_sampling_rate.n, self->audio_sampling_rate.d);
5098       break;
5099     case 0x3d02:
5100       if (tag_size != 1)
5101         goto error;
5102       self->locked = (GST_READ_UINT8 (tag_data) != 0);
5103       GST_DEBUG ("  locked = %s", (self->locked) ? "yes" : "no");
5104       break;
5105     case 0x3d04:
5106       if (tag_size != 1)
5107         goto error;
5108       self->audio_ref_level = GST_READ_UINT8 (tag_data);
5109       GST_DEBUG ("  audio ref level = %d", self->audio_ref_level);
5110       break;
5111     case 0x3d05:
5112       if (tag_size != 1)
5113         goto error;
5114       self->electro_spatial_formulation = GST_READ_UINT8 (tag_data);
5115       GST_DEBUG ("  electro spatial formulation = %u",
5116           self->electro_spatial_formulation);
5117       break;
5118     case 0x3d07:
5119       if (tag_size != 4)
5120         goto error;
5121       self->channel_count = GST_READ_UINT32_BE (tag_data);
5122       GST_DEBUG ("  channel count = %u", self->channel_count);
5123       break;
5124     case 0x3d01:
5125       if (tag_size != 4)
5126         goto error;
5127       self->quantization_bits = GST_READ_UINT32_BE (tag_data);
5128       GST_DEBUG ("  quantization bits = %u", self->quantization_bits);
5129       break;
5130     case 0x3d0c:
5131       if (tag_size != 1)
5132         goto error;
5133       self->dial_norm = GST_READ_UINT8 (tag_data);
5134       GST_DEBUG ("  dial norm = %d", self->dial_norm);
5135       break;
5136     case 0x3d06:
5137       if (tag_size != 16)
5138         goto error;
5139       memcpy (&self->sound_essence_compression, tag_data, 16);
5140       GST_DEBUG ("  sound essence compression = %s",
5141           mxf_ul_to_string (&self->sound_essence_compression, str));
5142       break;
5143     default:
5144       ret =
5145           MXF_METADATA_BASE_CLASS
5146           (mxf_metadata_generic_sound_essence_descriptor_parent_class)->handle_tag
5147           (metadata, primer, tag, tag_data, tag_size);
5148       break;
5149   }
5150 
5151   return ret;
5152 
5153 error:
5154 
5155   GST_ERROR
5156       ("Invalid generic sound essence descriptor local tag 0x%04x of size %u",
5157       tag, tag_size);
5158 
5159   return FALSE;
5160 }
5161 
5162 static GstStructure *
mxf_metadata_generic_sound_essence_descriptor_to_structure(MXFMetadataBase * m)5163 mxf_metadata_generic_sound_essence_descriptor_to_structure (MXFMetadataBase * m)
5164 {
5165   GstStructure *ret =
5166       MXF_METADATA_BASE_CLASS
5167       (mxf_metadata_generic_sound_essence_descriptor_parent_class)->to_structure
5168       (m);
5169   MXFMetadataGenericSoundEssenceDescriptor *self =
5170       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (m);
5171 
5172   gst_structure_id_set (ret, MXF_QUARK (AUDIO_SAMPLING_RATE), GST_TYPE_FRACTION,
5173       self->audio_sampling_rate.n, self->audio_sampling_rate.d, NULL);
5174 
5175   gst_structure_id_set (ret, MXF_QUARK (LOCKED), G_TYPE_BOOLEAN, self->locked,
5176       NULL);
5177 
5178   if (self->electro_spatial_formulation != 0)
5179     gst_structure_id_set (ret, MXF_QUARK (ELECTRO_SPATIAL_FORMULATION),
5180         G_TYPE_UCHAR, self->electro_spatial_formulation, NULL);
5181 
5182   gst_structure_id_set (ret, MXF_QUARK (CHANNEL_COUNT), G_TYPE_UINT,
5183       self->channel_count, NULL);
5184 
5185   gst_structure_id_set (ret, MXF_QUARK (QUANTIZATION_BITS), G_TYPE_UINT,
5186       self->quantization_bits, NULL);
5187 
5188   if (self->dial_norm != 0)
5189     gst_structure_id_set (ret, MXF_QUARK (DIAL_NORM), G_TYPE_CHAR,
5190         self->dial_norm, NULL);
5191 
5192   if (!mxf_ul_is_zero (&self->sound_essence_compression)) {
5193     gchar str[48];
5194 
5195     mxf_ul_to_string (&self->sound_essence_compression, str);
5196     gst_structure_id_set (ret, MXF_QUARK (SOUND_ESSENCE_COMPRESSION),
5197         G_TYPE_STRING, str, NULL);
5198   }
5199 
5200   return ret;
5201 }
5202 
5203 static GList *
mxf_metadata_generic_sound_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)5204 mxf_metadata_generic_sound_essence_descriptor_write_tags (MXFMetadataBase * m,
5205     MXFPrimerPack * primer)
5206 {
5207   MXFMetadataGenericSoundEssenceDescriptor *self =
5208       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (m);
5209   GList *ret =
5210       MXF_METADATA_BASE_CLASS
5211       (mxf_metadata_generic_sound_essence_descriptor_parent_class)->write_tags
5212       (m, primer);
5213   MXFLocalTag *t;
5214 
5215   t = g_slice_new0 (MXFLocalTag);
5216   memcpy (&t->ul, MXF_UL (AUDIO_SAMPLING_RATE), 16);
5217   t->size = 8;
5218   t->data = g_slice_alloc (t->size);
5219   t->g_slice = TRUE;
5220   GST_WRITE_UINT32_BE (t->data, self->audio_sampling_rate.n);
5221   GST_WRITE_UINT32_BE (t->data + 4, self->audio_sampling_rate.d);
5222   mxf_primer_pack_add_mapping (primer, 0x3d03, &t->ul);
5223   ret = g_list_prepend (ret, t);
5224 
5225   t = g_slice_new0 (MXFLocalTag);
5226   memcpy (&t->ul, MXF_UL (LOCKED), 16);
5227   t->size = 1;
5228   t->data = g_slice_alloc (t->size);
5229   t->g_slice = TRUE;
5230   GST_WRITE_UINT8 (t->data, (self->locked) ? 1 : 0);
5231   mxf_primer_pack_add_mapping (primer, 0x3d02, &t->ul);
5232   ret = g_list_prepend (ret, t);
5233 
5234   if (self->audio_ref_level) {
5235     t = g_slice_new0 (MXFLocalTag);
5236     memcpy (&t->ul, MXF_UL (AUDIO_REF_LEVEL), 16);
5237     t->size = 1;
5238     t->data = g_slice_alloc (t->size);
5239     t->g_slice = TRUE;
5240     GST_WRITE_UINT8 (t->data, self->audio_ref_level);
5241     mxf_primer_pack_add_mapping (primer, 0x3d04, &t->ul);
5242     ret = g_list_prepend (ret, t);
5243   }
5244 
5245   if (self->electro_spatial_formulation != 255) {
5246     t = g_slice_new0 (MXFLocalTag);
5247     memcpy (&t->ul, MXF_UL (ELECTRO_SPATIAL_FORMULATION), 16);
5248     t->size = 1;
5249     t->data = g_slice_alloc (t->size);
5250     t->g_slice = TRUE;
5251     GST_WRITE_UINT8 (t->data, self->electro_spatial_formulation);
5252     mxf_primer_pack_add_mapping (primer, 0x3d05, &t->ul);
5253     ret = g_list_prepend (ret, t);
5254   }
5255 
5256   t = g_slice_new0 (MXFLocalTag);
5257   memcpy (&t->ul, MXF_UL (CHANNEL_COUNT), 16);
5258   t->size = 4;
5259   t->data = g_slice_alloc (t->size);
5260   t->g_slice = TRUE;
5261   GST_WRITE_UINT32_BE (t->data, self->channel_count);
5262   mxf_primer_pack_add_mapping (primer, 0x3d07, &t->ul);
5263   ret = g_list_prepend (ret, t);
5264 
5265   t = g_slice_new0 (MXFLocalTag);
5266   memcpy (&t->ul, MXF_UL (QUANTIZATION_BITS), 16);
5267   t->size = 4;
5268   t->data = g_slice_alloc (t->size);
5269   t->g_slice = TRUE;
5270   GST_WRITE_UINT32_BE (t->data, self->quantization_bits);
5271   mxf_primer_pack_add_mapping (primer, 0x3d01, &t->ul);
5272   ret = g_list_prepend (ret, t);
5273 
5274   if (self->dial_norm != 0) {
5275     t = g_slice_new0 (MXFLocalTag);
5276     memcpy (&t->ul, MXF_UL (DIAL_NORM), 16);
5277     t->size = 1;
5278     t->data = g_slice_alloc (t->size);
5279     t->g_slice = TRUE;
5280     GST_WRITE_UINT8 (t->data, self->dial_norm);
5281     mxf_primer_pack_add_mapping (primer, 0x3d0c, &t->ul);
5282     ret = g_list_prepend (ret, t);
5283   }
5284 
5285   if (!mxf_ul_is_zero (&self->sound_essence_compression)) {
5286     t = g_slice_new0 (MXFLocalTag);
5287     memcpy (&t->ul, MXF_UL (SOUND_ESSENCE_COMPRESSION), 16);
5288     t->size = 16;
5289     t->data = g_slice_alloc (t->size);
5290     t->g_slice = TRUE;
5291     memcpy (t->data, &self->sound_essence_compression, 16);
5292     mxf_primer_pack_add_mapping (primer, 0x3d06, &t->ul);
5293     ret = g_list_prepend (ret, t);
5294   }
5295 
5296   return ret;
5297 }
5298 
5299 static void
mxf_metadata_generic_sound_essence_descriptor_init(MXFMetadataGenericSoundEssenceDescriptor * self)5300     mxf_metadata_generic_sound_essence_descriptor_init
5301     (MXFMetadataGenericSoundEssenceDescriptor * self)
5302 {
5303   self->audio_sampling_rate.n = 0;
5304   self->audio_sampling_rate.d = 1;
5305   self->electro_spatial_formulation = 255;
5306 }
5307 
5308 static void
mxf_metadata_generic_sound_essence_descriptor_class_init(MXFMetadataGenericSoundEssenceDescriptorClass * klass)5309     mxf_metadata_generic_sound_essence_descriptor_class_init
5310     (MXFMetadataGenericSoundEssenceDescriptorClass * klass)
5311 {
5312   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5313   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5314 
5315   metadata_base_class->handle_tag =
5316       mxf_metadata_generic_sound_essence_descriptor_handle_tag;
5317   metadata_base_class->name_quark =
5318       MXF_QUARK (GENERIC_SOUND_ESSENCE_DESCRIPTOR);
5319   metadata_base_class->to_structure =
5320       mxf_metadata_generic_sound_essence_descriptor_to_structure;
5321   metadata_base_class->write_tags =
5322       mxf_metadata_generic_sound_essence_descriptor_write_tags;
5323   metadata_class->type = 0x0142;
5324 }
5325 
mxf_metadata_generic_sound_essence_descriptor_set_caps(MXFMetadataGenericSoundEssenceDescriptor * self,GstCaps * caps)5326 void mxf_metadata_generic_sound_essence_descriptor_set_caps
5327     (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps)
5328 {
5329   g_return_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self));
5330   g_return_if_fail (GST_IS_CAPS (caps));
5331 
5332   if (self->audio_sampling_rate.n == 0 || self->audio_sampling_rate.d == 0) {
5333     GST_ERROR ("Invalid audio sampling rate");
5334   } else {
5335     gst_caps_set_simple (caps, "rate", G_TYPE_INT,
5336         (gint) (mxf_fraction_to_double (&self->audio_sampling_rate) + 0.5),
5337         NULL);
5338   }
5339 
5340   if (self->channel_count == 0) {
5341     GST_ERROR ("Invalid number of channels (0)");
5342   } else {
5343     gst_caps_set_simple (caps, "channels", G_TYPE_INT, self->channel_count,
5344         NULL);
5345   }
5346 }
5347 
mxf_metadata_generic_sound_essence_descriptor_create_caps(MXFMetadataGenericSoundEssenceDescriptor * self,GstAudioFormat * format)5348 GstCaps *mxf_metadata_generic_sound_essence_descriptor_create_caps
5349     (MXFMetadataGenericSoundEssenceDescriptor * self, GstAudioFormat * format)
5350 {
5351   GstAudioInfo info;
5352   gint rate = 0;
5353   gint channels = 0;
5354 
5355   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self),
5356       NULL);
5357 
5358   gst_audio_info_init (&info);
5359 
5360   if (self->audio_sampling_rate.n == 0 || self->audio_sampling_rate.d == 0) {
5361     GST_ERROR ("Invalid audio sampling rate");
5362   } else {
5363     rate = (gint) (mxf_fraction_to_double (&self->audio_sampling_rate)
5364         + 0.5);
5365   }
5366 
5367   if (self->channel_count == 0) {
5368     GST_ERROR ("Invalid number of channels (0)");
5369   } else {
5370     channels = self->channel_count;
5371   }
5372 
5373   gst_audio_info_set_format (&info, *format, rate, channels, NULL);
5374 
5375   return gst_audio_info_to_caps (&info);
5376 }
5377 
5378 gboolean
mxf_metadata_generic_sound_essence_descriptor_from_caps(MXFMetadataGenericSoundEssenceDescriptor * self,GstCaps * caps)5379     mxf_metadata_generic_sound_essence_descriptor_from_caps
5380     (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps) {
5381   gint rate;
5382   gint channels;
5383   GstStructure *s;
5384 
5385   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self),
5386       FALSE);
5387   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
5388 
5389   s = gst_caps_get_structure (caps, 0);
5390 
5391   if (!gst_structure_get_int (s, "rate", &rate) || rate == 0) {
5392     GST_WARNING ("No samplerate");
5393     return FALSE;
5394   } else {
5395     self->audio_sampling_rate.n = rate;
5396     self->audio_sampling_rate.d = 1;
5397   }
5398 
5399   if (!gst_structure_get_int (s, "channels", &channels) || channels == 0) {
5400     GST_WARNING ("No channels");
5401     return FALSE;
5402   } else {
5403     self->channel_count = channels;
5404   }
5405 
5406   return TRUE;
5407 }
5408 
5409 
5410 G_DEFINE_TYPE (MXFMetadataCDCIPictureEssenceDescriptor,
5411     mxf_metadata_cdci_picture_essence_descriptor,
5412     MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
5413 
5414 static gboolean
mxf_metadata_cdci_picture_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5415 mxf_metadata_cdci_picture_essence_descriptor_handle_tag (MXFMetadataBase *
5416     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5417     guint tag_size)
5418 {
5419   MXFMetadataCDCIPictureEssenceDescriptor *self =
5420       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (metadata);
5421   gboolean ret = TRUE;
5422 
5423   switch (tag) {
5424     case 0x3301:
5425       if (tag_size != 4)
5426         goto error;
5427       self->component_depth = GST_READ_UINT32_BE (tag_data);
5428       GST_DEBUG ("  component depth = %u", self->component_depth);
5429       break;
5430     case 0x3302:
5431       if (tag_size != 4)
5432         goto error;
5433       self->horizontal_subsampling = GST_READ_UINT32_BE (tag_data);
5434       GST_DEBUG ("  horizontal subsampling = %u", self->horizontal_subsampling);
5435       break;
5436     case 0x3308:
5437       if (tag_size != 4)
5438         goto error;
5439       self->vertical_subsampling = GST_READ_UINT32_BE (tag_data);
5440       GST_DEBUG ("  vertical subsampling = %u", self->vertical_subsampling);
5441       break;
5442     case 0x3303:
5443       if (tag_size != 1)
5444         goto error;
5445       self->color_siting = GST_READ_UINT8 (tag_data);
5446       GST_DEBUG ("  color siting = %u", self->color_siting);
5447       break;
5448     case 0x330b:
5449       if (tag_size != 1)
5450         goto error;
5451       self->reversed_byte_order = GST_READ_UINT8 (tag_data);
5452       GST_DEBUG ("  reversed byte order = %s",
5453           (self->reversed_byte_order) ? "yes" : "no");
5454       break;
5455     case 0x3307:
5456       if (tag_size != 2)
5457         goto error;
5458       self->padding_bits = GST_READ_UINT16_BE (tag_data);
5459       GST_DEBUG ("  padding bits = %d", self->padding_bits);
5460       break;
5461     case 0x3309:
5462       if (tag_size != 4)
5463         goto error;
5464       self->alpha_sample_depth = GST_READ_UINT32_BE (tag_data);
5465       GST_DEBUG ("  alpha sample depth = %u", self->alpha_sample_depth);
5466       break;
5467     case 0x3304:
5468       if (tag_size != 4)
5469         goto error;
5470       self->black_ref_level = GST_READ_UINT32_BE (tag_data);
5471       GST_DEBUG ("  black ref level = %u", self->black_ref_level);
5472       break;
5473     case 0x3305:
5474       if (tag_size != 4)
5475         goto error;
5476       self->white_ref_level = GST_READ_UINT32_BE (tag_data);
5477       GST_DEBUG ("  white ref level = %u", self->white_ref_level);
5478       break;
5479     case 0x3306:
5480       if (tag_size != 4)
5481         goto error;
5482       self->color_range = GST_READ_UINT32_BE (tag_data);
5483       GST_DEBUG ("  color range = %u", self->color_range);
5484       break;
5485     default:
5486       ret =
5487           MXF_METADATA_BASE_CLASS
5488           (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->handle_tag
5489           (metadata, primer, tag, tag_data, tag_size);
5490       break;
5491   }
5492 
5493   return ret;
5494 
5495 error:
5496 
5497   GST_ERROR
5498       ("Invalid CDCI picture essence descriptor local tag 0x%04x of size %u",
5499       tag, tag_size);
5500 
5501   return FALSE;
5502 }
5503 
5504 static GstStructure *
mxf_metadata_cdci_picture_essence_descriptor_to_structure(MXFMetadataBase * m)5505 mxf_metadata_cdci_picture_essence_descriptor_to_structure (MXFMetadataBase * m)
5506 {
5507   GstStructure *ret =
5508       MXF_METADATA_BASE_CLASS
5509       (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->to_structure
5510       (m);
5511   MXFMetadataCDCIPictureEssenceDescriptor *self =
5512       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (m);
5513 
5514   gst_structure_id_set (ret, MXF_QUARK (COMPONENT_DEPTH), G_TYPE_UINT,
5515       self->component_depth, NULL);
5516 
5517   gst_structure_id_set (ret, MXF_QUARK (HORIZONTAL_SUBSAMPLING), G_TYPE_UINT,
5518       self->horizontal_subsampling, NULL);
5519 
5520   if (self->vertical_subsampling != 0)
5521     gst_structure_id_set (ret, MXF_QUARK (VERTICAL_SUBSAMPLING), G_TYPE_UINT,
5522         self->vertical_subsampling, NULL);
5523 
5524   if (self->color_siting != 255)
5525     gst_structure_id_set (ret, MXF_QUARK (COLOR_SITING), G_TYPE_UCHAR,
5526         self->color_siting, NULL);
5527 
5528   gst_structure_id_set (ret, MXF_QUARK (REVERSED_BYTE_ORDER), G_TYPE_BOOLEAN,
5529       self->reversed_byte_order, NULL);
5530 
5531   if (self->padding_bits != 0)
5532     gst_structure_id_set (ret, MXF_QUARK (PADDING_BITS), G_TYPE_INT,
5533         self->padding_bits, NULL);
5534 
5535   if (self->alpha_sample_depth != 0)
5536     gst_structure_id_set (ret, MXF_QUARK (ALPHA_SAMPLE_DEPTH), G_TYPE_UINT,
5537         self->alpha_sample_depth, NULL);
5538 
5539   if (self->black_ref_level != 0)
5540     gst_structure_id_set (ret, MXF_QUARK (BLACK_REF_LEVEL), G_TYPE_UINT,
5541         self->black_ref_level, NULL);
5542 
5543   if (self->white_ref_level != 0)
5544     gst_structure_id_set (ret, MXF_QUARK (WHITE_REF_LEVEL), G_TYPE_UINT,
5545         self->white_ref_level, NULL);
5546 
5547   if (self->color_range != 0)
5548     gst_structure_id_set (ret, MXF_QUARK (COLOR_RANGE), G_TYPE_UINT,
5549         self->color_range, NULL);
5550 
5551   return ret;
5552 }
5553 
5554 static GList *
mxf_metadata_cdci_picture_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)5555 mxf_metadata_cdci_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
5556     MXFPrimerPack * primer)
5557 {
5558   MXFMetadataCDCIPictureEssenceDescriptor *self =
5559       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (m);
5560   GList *ret =
5561       MXF_METADATA_BASE_CLASS
5562       (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->write_tags
5563       (m, primer);
5564   MXFLocalTag *t;
5565 
5566   t = g_slice_new0 (MXFLocalTag);
5567   memcpy (&t->ul, MXF_UL (COMPONENT_DEPTH), 16);
5568   t->size = 4;
5569   t->data = g_slice_alloc (t->size);
5570   t->g_slice = TRUE;
5571   GST_WRITE_UINT32_BE (t->data, self->component_depth);
5572   mxf_primer_pack_add_mapping (primer, 0x3301, &t->ul);
5573   ret = g_list_prepend (ret, t);
5574 
5575   t = g_slice_new0 (MXFLocalTag);
5576   memcpy (&t->ul, MXF_UL (HORIZONTAL_SUBSAMPLING), 16);
5577   t->size = 4;
5578   t->data = g_slice_alloc (t->size);
5579   t->g_slice = TRUE;
5580   GST_WRITE_UINT32_BE (t->data, self->horizontal_subsampling);
5581   mxf_primer_pack_add_mapping (primer, 0x3302, &t->ul);
5582   ret = g_list_prepend (ret, t);
5583 
5584   if (self->vertical_subsampling) {
5585     t = g_slice_new0 (MXFLocalTag);
5586     memcpy (&t->ul, MXF_UL (VERTICAL_SUBSAMPLING), 16);
5587     t->size = 4;
5588     t->data = g_slice_alloc (t->size);
5589     t->g_slice = TRUE;
5590     GST_WRITE_UINT32_BE (t->data, self->vertical_subsampling);
5591     mxf_primer_pack_add_mapping (primer, 0x3308, &t->ul);
5592     ret = g_list_prepend (ret, t);
5593   }
5594 
5595   if (self->color_siting != 0xff) {
5596     t = g_slice_new0 (MXFLocalTag);
5597     memcpy (&t->ul, MXF_UL (COLOR_SITING), 16);
5598     t->size = 1;
5599     t->data = g_slice_alloc (t->size);
5600     t->g_slice = TRUE;
5601     GST_WRITE_UINT8 (t->data, self->color_siting);
5602     mxf_primer_pack_add_mapping (primer, 0x3303, &t->ul);
5603     ret = g_list_prepend (ret, t);
5604   }
5605 
5606   if (self->reversed_byte_order) {
5607     t = g_slice_new0 (MXFLocalTag);
5608     memcpy (&t->ul, MXF_UL (REVERSED_BYTE_ORDER), 16);
5609     t->size = 1;
5610     t->data = g_slice_alloc (t->size);
5611     t->g_slice = TRUE;
5612     GST_WRITE_UINT8 (t->data, (self->reversed_byte_order) ? 1 : 0);
5613     mxf_primer_pack_add_mapping (primer, 0x330b, &t->ul);
5614     ret = g_list_prepend (ret, t);
5615   }
5616 
5617   if (self->padding_bits) {
5618     t = g_slice_new0 (MXFLocalTag);
5619     memcpy (&t->ul, MXF_UL (PADDING_BITS), 16);
5620     t->size = 2;
5621     t->data = g_slice_alloc (t->size);
5622     t->g_slice = TRUE;
5623     GST_WRITE_UINT16_BE (t->data, self->padding_bits);
5624     mxf_primer_pack_add_mapping (primer, 0x3307, &t->ul);
5625     ret = g_list_prepend (ret, t);
5626   }
5627 
5628   if (self->alpha_sample_depth) {
5629     t = g_slice_new0 (MXFLocalTag);
5630     memcpy (&t->ul, MXF_UL (ALPHA_SAMPLE_DEPTH), 16);
5631     t->size = 4;
5632     t->data = g_slice_alloc (t->size);
5633     t->g_slice = TRUE;
5634     GST_WRITE_UINT32_BE (t->data, self->alpha_sample_depth);
5635     mxf_primer_pack_add_mapping (primer, 0x3309, &t->ul);
5636     ret = g_list_prepend (ret, t);
5637   }
5638 
5639   if (self->black_ref_level) {
5640     t = g_slice_new0 (MXFLocalTag);
5641     memcpy (&t->ul, MXF_UL (BLACK_REF_LEVEL), 16);
5642     t->size = 4;
5643     t->data = g_slice_alloc (t->size);
5644     t->g_slice = TRUE;
5645     GST_WRITE_UINT32_BE (t->data, self->black_ref_level);
5646     mxf_primer_pack_add_mapping (primer, 0x3304, &t->ul);
5647     ret = g_list_prepend (ret, t);
5648   }
5649 
5650   if (self->white_ref_level) {
5651     t = g_slice_new0 (MXFLocalTag);
5652     memcpy (&t->ul, MXF_UL (WHITE_REF_LEVEL), 16);
5653     t->size = 4;
5654     t->data = g_slice_alloc (t->size);
5655     t->g_slice = TRUE;
5656     GST_WRITE_UINT32_BE (t->data, self->white_ref_level);
5657     mxf_primer_pack_add_mapping (primer, 0x3305, &t->ul);
5658     ret = g_list_prepend (ret, t);
5659   }
5660 
5661   if (self->color_range) {
5662     t = g_slice_new0 (MXFLocalTag);
5663     memcpy (&t->ul, MXF_UL (COLOR_RANGE), 16);
5664     t->size = 4;
5665     t->data = g_slice_alloc (t->size);
5666     t->g_slice = TRUE;
5667     GST_WRITE_UINT32_BE (t->data, self->color_range);
5668     mxf_primer_pack_add_mapping (primer, 0x3306, &t->ul);
5669     ret = g_list_prepend (ret, t);
5670   }
5671 
5672   return ret;
5673 }
5674 
5675 static void
mxf_metadata_cdci_picture_essence_descriptor_init(MXFMetadataCDCIPictureEssenceDescriptor * self)5676     mxf_metadata_cdci_picture_essence_descriptor_init
5677     (MXFMetadataCDCIPictureEssenceDescriptor * self)
5678 {
5679   self->color_siting = 0xff;
5680 }
5681 
5682 static void
mxf_metadata_cdci_picture_essence_descriptor_class_init(MXFMetadataCDCIPictureEssenceDescriptorClass * klass)5683     mxf_metadata_cdci_picture_essence_descriptor_class_init
5684     (MXFMetadataCDCIPictureEssenceDescriptorClass * klass)
5685 {
5686   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5687   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5688 
5689   metadata_base_class->handle_tag =
5690       mxf_metadata_cdci_picture_essence_descriptor_handle_tag;
5691   metadata_base_class->name_quark = MXF_QUARK (CDCI_PICTURE_ESSENCE_DESCRIPTOR);
5692   metadata_base_class->to_structure =
5693       mxf_metadata_cdci_picture_essence_descriptor_to_structure;
5694   metadata_base_class->write_tags =
5695       mxf_metadata_cdci_picture_essence_descriptor_write_tags;
5696   metadata_class->type = 0x0128;
5697 }
5698 
5699 G_DEFINE_TYPE (MXFMetadataRGBAPictureEssenceDescriptor,
5700     mxf_metadata_rgba_picture_essence_descriptor,
5701     MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
5702 
5703 static void
mxf_metadata_rgba_picture_essence_descriptor_finalize(GObject * object)5704 mxf_metadata_rgba_picture_essence_descriptor_finalize (GObject * object)
5705 {
5706   MXFMetadataRGBAPictureEssenceDescriptor *self =
5707       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (object);
5708 
5709   g_free (self->pixel_layout);
5710   self->pixel_layout = NULL;
5711 
5712   G_OBJECT_CLASS
5713       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->finalize
5714       (object);
5715 }
5716 
5717 static gboolean
mxf_metadata_rgba_picture_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5718 mxf_metadata_rgba_picture_essence_descriptor_handle_tag (MXFMetadataBase *
5719     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5720     guint tag_size)
5721 {
5722   MXFMetadataRGBAPictureEssenceDescriptor *self =
5723       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (metadata);
5724   gboolean ret = TRUE;
5725 
5726   switch (tag) {
5727     case 0x3406:
5728       if (tag_size != 4)
5729         goto error;
5730       self->component_max_ref = GST_READ_UINT32_BE (tag_data);
5731       GST_DEBUG ("  component max ref = %u", self->component_max_ref);
5732       break;
5733     case 0x3407:
5734       if (tag_size != 4)
5735         goto error;
5736       self->component_min_ref = GST_READ_UINT32_BE (tag_data);
5737       GST_DEBUG ("  component min ref = %u", self->component_min_ref);
5738       break;
5739     case 0x3408:
5740       if (tag_size != 4)
5741         goto error;
5742       self->alpha_max_ref = GST_READ_UINT32_BE (tag_data);
5743       GST_DEBUG ("  alpha max ref = %u", self->alpha_max_ref);
5744       break;
5745     case 0x3409:
5746       if (tag_size != 4)
5747         goto error;
5748       self->alpha_min_ref = GST_READ_UINT32_BE (tag_data);
5749       GST_DEBUG ("  alpha min ref = %u", self->alpha_min_ref);
5750       break;
5751     case 0x3405:
5752       if (tag_size != 1)
5753         goto error;
5754       self->scanning_direction = GST_READ_UINT8 (tag_data);
5755       GST_DEBUG ("  scanning direction = %u", self->scanning_direction);
5756       break;
5757     case 0x3401:{
5758       guint i, len;
5759 
5760       if (tag_size % 2 != 0 || tag_size > 16)
5761         goto error;
5762 
5763       i = 0;
5764       while (tag_data[i] != 0 && tag_data[i + 1] != 0 && i + 2 <= tag_size)
5765         i += 2;
5766       len = i / 2;
5767 
5768       self->n_pixel_layout = len;
5769       GST_DEBUG ("  number of pixel layouts = %u", len);
5770       if (len == 0)
5771         return TRUE;
5772 
5773       self->pixel_layout = g_malloc0 (16);
5774 
5775       for (i = 0; i < len; i++) {
5776         self->pixel_layout[2 * i] = tag_data[2 * i];
5777         self->pixel_layout[2 * i + 1] = tag_data[2 * i + 1];
5778         GST_DEBUG ("    pixel layout %u = %c : %u", i,
5779             (gchar) self->pixel_layout[2 * i], self->pixel_layout[2 * i + 1]);
5780       }
5781 
5782       break;
5783     }
5784     case 0x3403:
5785     case 0x3404:
5786       /* TODO: handle this */
5787       GST_WARNING ("  tag 0x%04x not implemented yet", tag);
5788       break;
5789     default:
5790       ret =
5791           MXF_METADATA_BASE_CLASS
5792           (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->handle_tag
5793           (metadata, primer, tag, tag_data, tag_size);
5794       break;
5795   }
5796 
5797   return ret;
5798 
5799 error:
5800 
5801   GST_ERROR
5802       ("Invalid RGBA picture essence descriptor local tag 0x%04x of size %u",
5803       tag, tag_size);
5804 
5805   return FALSE;
5806 }
5807 
5808 static GstStructure *
mxf_metadata_rgba_picture_essence_descriptor_to_structure(MXFMetadataBase * m)5809 mxf_metadata_rgba_picture_essence_descriptor_to_structure (MXFMetadataBase * m)
5810 {
5811   GstStructure *ret =
5812       MXF_METADATA_BASE_CLASS
5813       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->to_structure
5814       (m);
5815   MXFMetadataRGBAPictureEssenceDescriptor *self =
5816       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (m);
5817 
5818   if (self->component_max_ref != 255)
5819     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_MAX_REF), G_TYPE_UINT,
5820         self->component_max_ref, NULL);
5821 
5822   if (self->component_min_ref != 0)
5823     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_MIN_REF), G_TYPE_UINT,
5824         self->component_min_ref, NULL);
5825 
5826   if (self->alpha_max_ref != 255)
5827     gst_structure_id_set (ret, MXF_QUARK (ALPHA_MAX_REF), G_TYPE_UINT,
5828         self->alpha_max_ref, NULL);
5829 
5830   if (self->alpha_min_ref != 0)
5831     gst_structure_id_set (ret, MXF_QUARK (ALPHA_MIN_REF), G_TYPE_UINT,
5832         self->alpha_min_ref, NULL);
5833 
5834   if (self->scanning_direction != 0)
5835     gst_structure_id_set (ret, MXF_QUARK (SCANNING_DIRECTION), G_TYPE_UCHAR,
5836         self->scanning_direction, NULL);
5837 
5838   if (self->n_pixel_layout != 0) {
5839     gchar *pl = g_new0 (gchar, self->n_pixel_layout * 2 + 1);
5840 
5841     memcpy (pl, self->pixel_layout, self->n_pixel_layout * 2);
5842 
5843     gst_structure_id_set (ret, MXF_QUARK (PIXEL_LAYOUT), G_TYPE_STRING, pl,
5844         NULL);
5845 
5846     g_free (pl);
5847   }
5848 
5849   return ret;
5850 }
5851 
5852 static GList *
mxf_metadata_rgba_picture_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)5853 mxf_metadata_rgba_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
5854     MXFPrimerPack * primer)
5855 {
5856   MXFMetadataRGBAPictureEssenceDescriptor *self =
5857       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (m);
5858   GList *ret =
5859       MXF_METADATA_BASE_CLASS
5860       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->write_tags
5861       (m, primer);
5862   MXFLocalTag *t;
5863 
5864   if (self->component_max_ref != 255) {
5865     t = g_slice_new0 (MXFLocalTag);
5866     memcpy (&t->ul, MXF_UL (COMPONENT_MAX_REF), 16);
5867     t->size = 4;
5868     t->data = g_slice_alloc (t->size);
5869     t->g_slice = TRUE;
5870     GST_WRITE_UINT32_BE (t->data, self->component_max_ref);
5871     mxf_primer_pack_add_mapping (primer, 0x3406, &t->ul);
5872     ret = g_list_prepend (ret, t);
5873   }
5874 
5875   if (self->component_min_ref) {
5876     t = g_slice_new0 (MXFLocalTag);
5877     memcpy (&t->ul, MXF_UL (COMPONENT_MIN_REF), 16);
5878     t->size = 4;
5879     t->data = g_slice_alloc (t->size);
5880     t->g_slice = TRUE;
5881     GST_WRITE_UINT32_BE (t->data, self->component_min_ref);
5882     mxf_primer_pack_add_mapping (primer, 0x3407, &t->ul);
5883     ret = g_list_prepend (ret, t);
5884   }
5885 
5886   if (self->alpha_max_ref != 255) {
5887     t = g_slice_new0 (MXFLocalTag);
5888     memcpy (&t->ul, MXF_UL (ALPHA_MAX_REF), 16);
5889     t->size = 4;
5890     t->data = g_slice_alloc (t->size);
5891     t->g_slice = TRUE;
5892     GST_WRITE_UINT32_BE (t->data, self->alpha_max_ref);
5893     mxf_primer_pack_add_mapping (primer, 0x3408, &t->ul);
5894     ret = g_list_prepend (ret, t);
5895   }
5896 
5897   if (self->alpha_min_ref) {
5898     t = g_slice_new0 (MXFLocalTag);
5899     memcpy (&t->ul, MXF_UL (ALPHA_MIN_REF), 16);
5900     t->size = 4;
5901     t->data = g_slice_alloc (t->size);
5902     t->g_slice = TRUE;
5903     GST_WRITE_UINT32_BE (t->data, self->alpha_min_ref);
5904     mxf_primer_pack_add_mapping (primer, 0x3409, &t->ul);
5905     ret = g_list_prepend (ret, t);
5906   }
5907 
5908   if (self->scanning_direction) {
5909     t = g_slice_new0 (MXFLocalTag);
5910     memcpy (&t->ul, MXF_UL (SCANNING_DIRECTION), 16);
5911     t->size = 1;
5912     t->data = g_slice_alloc (t->size);
5913     t->g_slice = TRUE;
5914     GST_WRITE_UINT8 (t->data, self->scanning_direction);
5915     mxf_primer_pack_add_mapping (primer, 0x3405, &t->ul);
5916     ret = g_list_prepend (ret, t);
5917   }
5918 
5919   t = g_slice_new0 (MXFLocalTag);
5920   memcpy (&t->ul, MXF_UL (PIXEL_LAYOUT), 16);
5921   t->size = 16;
5922   t->data = g_slice_alloc0 (t->size);
5923   t->g_slice = TRUE;
5924   if (self->pixel_layout)
5925     memcpy (t->data, self->pixel_layout, self->n_pixel_layout * 2);
5926   mxf_primer_pack_add_mapping (primer, 0x3401, &t->ul);
5927   ret = g_list_prepend (ret, t);
5928 
5929   return ret;
5930 }
5931 
5932 static void
mxf_metadata_rgba_picture_essence_descriptor_init(MXFMetadataRGBAPictureEssenceDescriptor * self)5933     mxf_metadata_rgba_picture_essence_descriptor_init
5934     (MXFMetadataRGBAPictureEssenceDescriptor * self)
5935 {
5936   self->component_max_ref = 255;
5937   self->alpha_max_ref = 255;
5938 }
5939 
5940 static void
mxf_metadata_rgba_picture_essence_descriptor_class_init(MXFMetadataRGBAPictureEssenceDescriptorClass * klass)5941     mxf_metadata_rgba_picture_essence_descriptor_class_init
5942     (MXFMetadataRGBAPictureEssenceDescriptorClass * klass)
5943 {
5944   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5945   GObjectClass *object_class = (GObjectClass *) klass;
5946   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5947 
5948   object_class->finalize =
5949       mxf_metadata_rgba_picture_essence_descriptor_finalize;
5950   metadata_base_class->handle_tag =
5951       mxf_metadata_rgba_picture_essence_descriptor_handle_tag;
5952   metadata_base_class->name_quark = MXF_QUARK (RGBA_PICTURE_ESSENCE_DESCRIPTOR);
5953   metadata_base_class->to_structure =
5954       mxf_metadata_rgba_picture_essence_descriptor_to_structure;
5955   metadata_base_class->write_tags =
5956       mxf_metadata_rgba_picture_essence_descriptor_write_tags;
5957   metadata_class->type = 0x0129;
5958 }
5959 
5960 G_DEFINE_TYPE (MXFMetadataGenericDataEssenceDescriptor,
5961     mxf_metadata_generic_data_essence_descriptor,
5962     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
5963 
5964 static gboolean
mxf_metadata_generic_data_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5965 mxf_metadata_generic_data_essence_descriptor_handle_tag (MXFMetadataBase *
5966     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5967     guint tag_size)
5968 {
5969   MXFMetadataGenericDataEssenceDescriptor *self =
5970       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (metadata);
5971   gboolean ret = TRUE;
5972 #ifndef GST_DISABLE_GST_DEBUG
5973   gchar str[48];
5974 #endif
5975 
5976   switch (tag) {
5977     case 0x3e01:
5978       if (tag_size != 16)
5979         goto error;
5980       memcpy (&self->data_essence_coding, tag_data, 16);
5981       GST_DEBUG ("  data essence coding = %s",
5982           mxf_ul_to_string (&self->data_essence_coding, str));
5983       break;
5984     default:
5985       ret =
5986           MXF_METADATA_BASE_CLASS
5987           (mxf_metadata_generic_data_essence_descriptor_parent_class)->handle_tag
5988           (metadata, primer, tag, tag_data, tag_size);
5989       break;
5990   }
5991 
5992   return ret;
5993 
5994 error:
5995 
5996   GST_ERROR
5997       ("Invalid generic data essence descriptor local tag 0x%04x of size %u",
5998       tag, tag_size);
5999 
6000   return FALSE;
6001 }
6002 
6003 static GstStructure *
mxf_metadata_generic_data_essence_descriptor_to_structure(MXFMetadataBase * m)6004 mxf_metadata_generic_data_essence_descriptor_to_structure (MXFMetadataBase * m)
6005 {
6006   GstStructure *ret =
6007       MXF_METADATA_BASE_CLASS
6008       (mxf_metadata_generic_data_essence_descriptor_parent_class)->to_structure
6009       (m);
6010   MXFMetadataGenericDataEssenceDescriptor *self =
6011       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (m);
6012   gchar str[48];
6013 
6014   if (!mxf_ul_is_zero (&self->data_essence_coding)) {
6015     mxf_ul_to_string (&self->data_essence_coding, str);
6016     gst_structure_id_set (ret, MXF_QUARK (DATA_ESSENCE_CODING), G_TYPE_STRING,
6017         str, NULL);
6018   }
6019 
6020   return ret;
6021 }
6022 
6023 static GList *
mxf_metadata_generic_data_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6024 mxf_metadata_generic_data_essence_descriptor_write_tags (MXFMetadataBase * m,
6025     MXFPrimerPack * primer)
6026 {
6027   MXFMetadataGenericDataEssenceDescriptor *self =
6028       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (m);
6029   GList *ret =
6030       MXF_METADATA_BASE_CLASS
6031       (mxf_metadata_generic_data_essence_descriptor_parent_class)->write_tags
6032       (m, primer);
6033   MXFLocalTag *t;
6034 
6035   if (!mxf_ul_is_zero (&self->data_essence_coding)) {
6036     t = g_slice_new0 (MXFLocalTag);
6037     memcpy (&t->ul, MXF_UL (DATA_ESSENCE_CODING), 16);
6038     t->size = 16;
6039     t->data = g_slice_alloc (t->size);
6040     t->g_slice = TRUE;
6041     memcpy (t->data, &self->data_essence_coding, 16);
6042     mxf_primer_pack_add_mapping (primer, 0x3e01, &t->ul);
6043     ret = g_list_prepend (ret, t);
6044   }
6045 
6046   return ret;
6047 }
6048 
6049 static void
mxf_metadata_generic_data_essence_descriptor_init(MXFMetadataGenericDataEssenceDescriptor * self)6050     mxf_metadata_generic_data_essence_descriptor_init
6051     (MXFMetadataGenericDataEssenceDescriptor * self)
6052 {
6053 
6054 }
6055 
6056 static void
mxf_metadata_generic_data_essence_descriptor_class_init(MXFMetadataGenericDataEssenceDescriptorClass * klass)6057     mxf_metadata_generic_data_essence_descriptor_class_init
6058     (MXFMetadataGenericDataEssenceDescriptorClass * klass)
6059 {
6060   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6061   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6062 
6063   metadata_base_class->handle_tag =
6064       mxf_metadata_generic_data_essence_descriptor_handle_tag;
6065   metadata_base_class->name_quark = MXF_QUARK (GENERIC_DATA_ESSENCE_DESCRIPTOR);
6066   metadata_base_class->to_structure =
6067       mxf_metadata_generic_data_essence_descriptor_to_structure;
6068   metadata_base_class->write_tags =
6069       mxf_metadata_generic_data_essence_descriptor_write_tags;
6070   metadata_class->type = 0x0143;
6071 }
6072 
6073 G_DEFINE_TYPE (MXFMetadataMultipleDescriptor, mxf_metadata_multiple_descriptor,
6074     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
6075 
6076 static void
mxf_metadata_multiple_descriptor_finalize(GObject * object)6077 mxf_metadata_multiple_descriptor_finalize (GObject * object)
6078 {
6079   MXFMetadataMultipleDescriptor *self =
6080       MXF_METADATA_MULTIPLE_DESCRIPTOR (object);
6081 
6082   g_free (self->sub_descriptors_uids);
6083   self->sub_descriptors_uids = NULL;
6084   g_free (self->sub_descriptors);
6085   self->sub_descriptors = NULL;
6086 
6087   G_OBJECT_CLASS
6088       (mxf_metadata_multiple_descriptor_parent_class)->finalize (object);
6089 }
6090 
6091 static gboolean
mxf_metadata_multiple_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)6092 mxf_metadata_multiple_descriptor_handle_tag (MXFMetadataBase * metadata,
6093     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6094     guint tag_size)
6095 {
6096   MXFMetadataMultipleDescriptor *self =
6097       MXF_METADATA_MULTIPLE_DESCRIPTOR (metadata);
6098   gboolean ret = TRUE;
6099 #ifndef GST_DISABLE_GST_DEBUG
6100   gchar str[48];
6101 #endif
6102 
6103   switch (tag) {
6104     case 0x3f01:
6105       if (!mxf_uuid_array_parse (&self->sub_descriptors_uids,
6106               &self->n_sub_descriptors, tag_data, tag_size))
6107         goto error;
6108 
6109       GST_DEBUG ("  number of sub descriptors = %u", self->n_sub_descriptors);
6110 #ifndef GST_DISABLE_GST_DEBUG
6111       {
6112         guint i;
6113         for (i = 0; i < self->n_sub_descriptors; i++) {
6114           GST_DEBUG ("    sub descriptor %u = %s", i,
6115               mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
6116         }
6117       }
6118 #endif
6119 
6120       break;
6121     default:
6122       ret =
6123           MXF_METADATA_BASE_CLASS
6124           (mxf_metadata_multiple_descriptor_parent_class)->handle_tag (metadata,
6125           primer, tag, tag_data, tag_size);
6126       break;
6127   }
6128 
6129   return ret;
6130 
6131 error:
6132 
6133   GST_ERROR ("Invalid multiple descriptor local tag 0x%04x of size %u", tag,
6134       tag_size);
6135 
6136   return FALSE;
6137 }
6138 
6139 static gboolean
mxf_metadata_multiple_descriptor_resolve(MXFMetadataBase * m,GHashTable * metadata)6140 mxf_metadata_multiple_descriptor_resolve (MXFMetadataBase * m,
6141     GHashTable * metadata)
6142 {
6143   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6144   MXFMetadataBase *current = NULL;
6145   guint i, have_subdescriptors = 0;
6146 #ifndef GST_DISABLE_GST_DEBUG
6147   gchar str[48];
6148 #endif
6149 
6150   if (self->sub_descriptors)
6151     memset (self->sub_descriptors, 0,
6152         sizeof (gpointer) * self->n_sub_descriptors);
6153   else
6154     self->sub_descriptors =
6155         g_new0 (MXFMetadataGenericDescriptor *, self->n_sub_descriptors);
6156   for (i = 0; i < self->n_sub_descriptors; i++) {
6157     current = g_hash_table_lookup (metadata, &self->sub_descriptors_uids[i]);
6158     if (current && MXF_IS_METADATA_GENERIC_DESCRIPTOR (current)) {
6159       if (mxf_metadata_base_resolve (current, metadata)) {
6160         self->sub_descriptors[i] = MXF_METADATA_GENERIC_DESCRIPTOR (current);
6161         have_subdescriptors++;
6162       } else {
6163         GST_ERROR ("Couldn't resolve descriptor %s",
6164             mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
6165         return FALSE;
6166       }
6167     } else {
6168       GST_ERROR ("Descriptor %s not found",
6169           mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
6170     }
6171   }
6172 
6173   return
6174       MXF_METADATA_BASE_CLASS
6175       (mxf_metadata_multiple_descriptor_parent_class)->resolve (m, metadata);
6176 }
6177 
6178 static GstStructure *
mxf_metadata_multiple_descriptor_to_structure(MXFMetadataBase * m)6179 mxf_metadata_multiple_descriptor_to_structure (MXFMetadataBase * m)
6180 {
6181   GstStructure *ret =
6182       MXF_METADATA_BASE_CLASS
6183       (mxf_metadata_multiple_descriptor_parent_class)->to_structure (m);
6184   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6185   guint i;
6186 
6187   if (self->n_sub_descriptors > 0) {
6188     GValue arr = { 0, }
6189     , val = {
6190     0,};
6191 
6192     g_value_init (&arr, GST_TYPE_ARRAY);
6193 
6194     for (i = 0; i < self->n_sub_descriptors; i++) {
6195       GstStructure *s;
6196 
6197       if (self->sub_descriptors[i] == NULL)
6198         continue;
6199 
6200       g_value_init (&val, GST_TYPE_STRUCTURE);
6201 
6202       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
6203           (self->sub_descriptors[i]));
6204       gst_value_set_structure (&val, s);
6205       gst_structure_free (s);
6206       gst_value_array_append_value (&arr, &val);
6207       g_value_unset (&val);
6208     }
6209 
6210     if (gst_value_array_get_size (&arr) > 0)
6211       gst_structure_id_set_value (ret, MXF_QUARK (SUB_DESCRIPTORS), &arr);
6212 
6213     g_value_unset (&arr);
6214   }
6215 
6216   return ret;
6217 }
6218 
6219 static GList *
mxf_metadata_multiple_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6220 mxf_metadata_multiple_descriptor_write_tags (MXFMetadataBase * m,
6221     MXFPrimerPack * primer)
6222 {
6223   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6224   GList *ret =
6225       MXF_METADATA_BASE_CLASS
6226       (mxf_metadata_multiple_descriptor_parent_class)->write_tags (m, primer);
6227   MXFLocalTag *t;
6228 
6229   if (self->sub_descriptors) {
6230     guint i;
6231 
6232     t = g_slice_new0 (MXFLocalTag);
6233     memcpy (&t->ul, MXF_UL (SUB_DESCRIPTORS), 16);
6234     t->size = 8 + 16 * self->n_sub_descriptors;
6235     t->data = g_slice_alloc0 (t->size);
6236     t->g_slice = TRUE;
6237     GST_WRITE_UINT32_BE (t->data, self->n_sub_descriptors);
6238     GST_WRITE_UINT32_BE (t->data + 4, 16);
6239     for (i = 0; i < self->n_sub_descriptors; i++) {
6240       if (!self->sub_descriptors[i])
6241         continue;
6242 
6243       memcpy (t->data + 8 + 16 * i,
6244           &MXF_METADATA_BASE (self->sub_descriptors[i])->instance_uid, 16);
6245     }
6246     mxf_primer_pack_add_mapping (primer, 0x3f01, &t->ul);
6247     ret = g_list_prepend (ret, t);
6248   }
6249 
6250   return ret;
6251 }
6252 
6253 static void
mxf_metadata_multiple_descriptor_init(MXFMetadataMultipleDescriptor * self)6254 mxf_metadata_multiple_descriptor_init (MXFMetadataMultipleDescriptor * self)
6255 {
6256 
6257 }
6258 
6259 static void
mxf_metadata_multiple_descriptor_class_init(MXFMetadataMultipleDescriptorClass * klass)6260 mxf_metadata_multiple_descriptor_class_init (MXFMetadataMultipleDescriptorClass
6261     * klass)
6262 {
6263   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6264   GObjectClass *object_class = (GObjectClass *) klass;
6265   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6266 
6267   object_class->finalize = mxf_metadata_multiple_descriptor_finalize;
6268   metadata_base_class->handle_tag = mxf_metadata_multiple_descriptor_handle_tag;
6269   metadata_base_class->resolve = mxf_metadata_multiple_descriptor_resolve;
6270   metadata_base_class->name_quark = MXF_QUARK (MULTIPLE_DESCRIPTOR);
6271   metadata_base_class->to_structure =
6272       mxf_metadata_multiple_descriptor_to_structure;
6273   metadata_base_class->write_tags = mxf_metadata_multiple_descriptor_write_tags;
6274   metadata_class->type = 0x0144;
6275 }
6276 
6277 G_DEFINE_ABSTRACT_TYPE (MXFMetadataLocator, mxf_metadata_locator,
6278     MXF_TYPE_METADATA);
6279 
6280 static void
mxf_metadata_locator_init(MXFMetadataLocator * self)6281 mxf_metadata_locator_init (MXFMetadataLocator * self)
6282 {
6283 }
6284 
6285 static void
mxf_metadata_locator_class_init(MXFMetadataLocatorClass * klass)6286 mxf_metadata_locator_class_init (MXFMetadataLocatorClass * klass)
6287 {
6288 }
6289 
6290 G_DEFINE_TYPE (MXFMetadataTextLocator, mxf_metadata_text_locator,
6291     MXF_TYPE_METADATA_LOCATOR);
6292 
6293 static void
mxf_metadata_text_locator_finalize(GObject * object)6294 mxf_metadata_text_locator_finalize (GObject * object)
6295 {
6296   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (object);
6297 
6298   g_free (self->locator_name);
6299   self->locator_name = NULL;
6300 
6301   G_OBJECT_CLASS (mxf_metadata_text_locator_parent_class)->finalize (object);
6302 }
6303 
6304 static gboolean
mxf_metadata_text_locator_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)6305 mxf_metadata_text_locator_handle_tag (MXFMetadataBase * metadata,
6306     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6307     guint tag_size)
6308 {
6309   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (metadata);
6310   gboolean ret = TRUE;
6311 
6312   switch (tag) {
6313     case 0x4101:
6314       self->locator_name = mxf_utf16_to_utf8 (tag_data, tag_size);
6315       GST_DEBUG ("  text locator = %s", GST_STR_NULL (self->locator_name));
6316       break;
6317     default:
6318       ret =
6319           MXF_METADATA_BASE_CLASS
6320           (mxf_metadata_text_locator_parent_class)->handle_tag (metadata,
6321           primer, tag, tag_data, tag_size);
6322       break;
6323   }
6324 
6325   return ret;
6326 }
6327 
6328 static GstStructure *
mxf_metadata_text_locator_to_structure(MXFMetadataBase * m)6329 mxf_metadata_text_locator_to_structure (MXFMetadataBase * m)
6330 {
6331   GstStructure *ret =
6332       MXF_METADATA_BASE_CLASS
6333       (mxf_metadata_text_locator_parent_class)->to_structure (m);
6334   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (m);
6335 
6336   gst_structure_id_set (ret, MXF_QUARK (LOCATOR_NAME), G_TYPE_STRING,
6337       self->locator_name, NULL);
6338 
6339   return ret;
6340 }
6341 
6342 static GList *
mxf_metadata_text_locator_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6343 mxf_metadata_text_locator_write_tags (MXFMetadataBase * m,
6344     MXFPrimerPack * primer)
6345 {
6346   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (m);
6347   GList *ret =
6348       MXF_METADATA_BASE_CLASS
6349       (mxf_metadata_text_locator_parent_class)->write_tags (m, primer);
6350   MXFLocalTag *t;
6351 
6352   if (self->locator_name) {
6353     t = g_slice_new0 (MXFLocalTag);
6354     memcpy (&t->ul, MXF_UL (LOCATOR_NAME), 16);
6355     t->data = mxf_utf8_to_utf16 (self->locator_name, &t->size);
6356     mxf_primer_pack_add_mapping (primer, 0x4101, &t->ul);
6357     ret = g_list_prepend (ret, t);
6358   }
6359 
6360   return ret;
6361 }
6362 
6363 static void
mxf_metadata_text_locator_init(MXFMetadataTextLocator * self)6364 mxf_metadata_text_locator_init (MXFMetadataTextLocator * self)
6365 {
6366 
6367 }
6368 
6369 static void
mxf_metadata_text_locator_class_init(MXFMetadataTextLocatorClass * klass)6370 mxf_metadata_text_locator_class_init (MXFMetadataTextLocatorClass * klass)
6371 {
6372   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6373   GObjectClass *object_class = (GObjectClass *) klass;
6374   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6375 
6376   object_class->finalize = mxf_metadata_text_locator_finalize;
6377   metadata_base_class->handle_tag = mxf_metadata_text_locator_handle_tag;
6378   metadata_base_class->name_quark = MXF_QUARK (TEXT_LOCATOR);
6379   metadata_base_class->to_structure = mxf_metadata_text_locator_to_structure;
6380   metadata_base_class->write_tags = mxf_metadata_text_locator_write_tags;
6381   metadata_class->type = 0x0133;
6382 }
6383 
6384 G_DEFINE_TYPE (MXFMetadataNetworkLocator, mxf_metadata_network_locator,
6385     MXF_TYPE_METADATA_LOCATOR);
6386 
6387 static void
mxf_metadata_network_locator_finalize(GObject * object)6388 mxf_metadata_network_locator_finalize (GObject * object)
6389 {
6390   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (object);
6391 
6392   g_free (self->url_string);
6393   self->url_string = NULL;
6394 
6395   G_OBJECT_CLASS (mxf_metadata_network_locator_parent_class)->finalize (object);
6396 }
6397 
6398 static gboolean
mxf_metadata_network_locator_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)6399 mxf_metadata_network_locator_handle_tag (MXFMetadataBase * metadata,
6400     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6401     guint tag_size)
6402 {
6403   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (metadata);
6404   gboolean ret = TRUE;
6405 
6406   switch (tag) {
6407     case 0x4101:
6408       self->url_string = mxf_utf16_to_utf8 (tag_data, tag_size);
6409       GST_DEBUG ("  url string = %s", GST_STR_NULL (self->url_string));
6410       break;
6411     default:
6412       ret =
6413           MXF_METADATA_BASE_CLASS
6414           (mxf_metadata_network_locator_parent_class)->handle_tag (metadata,
6415           primer, tag, tag_data, tag_size);
6416       break;
6417   }
6418 
6419   return ret;
6420 }
6421 
6422 static GstStructure *
mxf_metadata_network_locator_to_structure(MXFMetadataBase * m)6423 mxf_metadata_network_locator_to_structure (MXFMetadataBase * m)
6424 {
6425   GstStructure *ret =
6426       MXF_METADATA_BASE_CLASS
6427       (mxf_metadata_network_locator_parent_class)->to_structure (m);
6428   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (m);
6429 
6430   gst_structure_id_set (ret, MXF_QUARK (URL_STRING), G_TYPE_STRING,
6431       self->url_string, NULL);
6432 
6433   return ret;
6434 }
6435 
6436 static GList *
mxf_metadata_network_locator_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6437 mxf_metadata_network_locator_write_tags (MXFMetadataBase * m,
6438     MXFPrimerPack * primer)
6439 {
6440   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (m);
6441   GList *ret =
6442       MXF_METADATA_BASE_CLASS
6443       (mxf_metadata_network_locator_parent_class)->write_tags (m, primer);
6444   MXFLocalTag *t;
6445 
6446   if (self->url_string) {
6447     t = g_slice_new0 (MXFLocalTag);
6448     memcpy (&t->ul, MXF_UL (URL_STRING), 16);
6449     t->data = mxf_utf8_to_utf16 (self->url_string, &t->size);
6450     mxf_primer_pack_add_mapping (primer, 0x4001, &t->ul);
6451     ret = g_list_prepend (ret, t);
6452   }
6453 
6454   return ret;
6455 }
6456 
6457 static void
mxf_metadata_network_locator_init(MXFMetadataNetworkLocator * self)6458 mxf_metadata_network_locator_init (MXFMetadataNetworkLocator * self)
6459 {
6460 }
6461 
6462 static void
mxf_metadata_network_locator_class_init(MXFMetadataNetworkLocatorClass * klass)6463 mxf_metadata_network_locator_class_init (MXFMetadataNetworkLocatorClass * klass)
6464 {
6465   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6466   GObjectClass *object_class = (GObjectClass *) klass;
6467   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6468 
6469   object_class->finalize = mxf_metadata_network_locator_finalize;
6470   metadata_base_class->handle_tag = mxf_metadata_network_locator_handle_tag;
6471   metadata_base_class->name_quark = MXF_QUARK (NETWORK_LOCATOR);
6472   metadata_base_class->to_structure = mxf_metadata_network_locator_to_structure;
6473   metadata_base_class->write_tags = mxf_metadata_network_locator_write_tags;
6474   metadata_class->type = 0x0133;
6475 }
6476 
6477 G_DEFINE_ABSTRACT_TYPE (MXFDescriptiveMetadata, mxf_descriptive_metadata,
6478     MXF_TYPE_METADATA_BASE);
6479 
6480 static void
mxf_descriptive_metadata_init(MXFDescriptiveMetadata * self)6481 mxf_descriptive_metadata_init (MXFDescriptiveMetadata * self)
6482 {
6483 }
6484 
6485 static void
mxf_descriptive_metadata_class_init(MXFDescriptiveMetadataClass * klass)6486 mxf_descriptive_metadata_class_init (MXFDescriptiveMetadataClass * klass)
6487 {
6488 }
6489 
6490 typedef struct
6491 {
6492   guint8 scheme;
6493   GType *types;
6494 } _MXFDescriptiveMetadataScheme;
6495 
6496 static GArray *_dm_schemes = NULL;
6497 
6498 void
mxf_descriptive_metadata_register(guint8 scheme,GType * types)6499 mxf_descriptive_metadata_register (guint8 scheme, GType * types)
6500 {
6501   _MXFDescriptiveMetadataScheme s;
6502 
6503   if (!_dm_schemes)
6504     _dm_schemes =
6505         g_array_new (FALSE, TRUE, sizeof (_MXFDescriptiveMetadataScheme));
6506 
6507   s.scheme = scheme;
6508   s.types = types;
6509 
6510   g_array_append_val (_dm_schemes, s);
6511 }
6512 
6513 MXFDescriptiveMetadata *
mxf_descriptive_metadata_new(guint8 scheme,guint32 type,MXFPrimerPack * primer,guint64 offset,const guint8 * data,guint size)6514 mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
6515     MXFPrimerPack * primer, guint64 offset, const guint8 * data, guint size)
6516 {
6517   guint i;
6518   GType t = G_TYPE_INVALID, *p;
6519   _MXFDescriptiveMetadataScheme *s = NULL;
6520   MXFDescriptiveMetadata *ret = NULL;
6521 
6522   g_return_val_if_fail (primer != NULL, NULL);
6523 
6524   if (G_UNLIKELY (type == 0)) {
6525     GST_WARNING ("Type 0 is invalid");
6526     return NULL;
6527   }
6528 
6529   for (i = 0; _dm_schemes && i < _dm_schemes->len; i++) {
6530     _MXFDescriptiveMetadataScheme *data =
6531         &g_array_index (_dm_schemes, _MXFDescriptiveMetadataScheme, i);
6532 
6533     if (data->scheme == scheme) {
6534       s = data;
6535       break;
6536     }
6537   }
6538 
6539   if (s == NULL) {
6540     GST_WARNING ("Descriptive metadata scheme 0x%02x not supported", scheme);
6541     return NULL;
6542   }
6543 
6544   p = s->types;
6545   while (*p) {
6546     GType tmp = *p;
6547     MXFDescriptiveMetadataClass *klass =
6548         MXF_DESCRIPTIVE_METADATA_CLASS (g_type_class_ref (tmp));
6549 
6550     if (klass->type == type) {
6551       g_type_class_unref (klass);
6552       t = tmp;
6553       break;
6554     }
6555     g_type_class_unref (klass);
6556     p++;
6557   }
6558 
6559   if (t == G_TYPE_INVALID) {
6560     GST_WARNING
6561         ("No handler for type 0x%06x of descriptive metadata scheme 0x%02x found",
6562         type, scheme);
6563     return NULL;
6564   }
6565 
6566   GST_DEBUG ("DM scheme 0x%02x type 0x%06x is handled by type %s", scheme, type,
6567       g_type_name (t));
6568 
6569   ret = (MXFDescriptiveMetadata *) g_type_create_instance (t);
6570   if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
6571     GST_ERROR ("Parsing metadata failed");
6572     g_object_unref (ret);
6573     return NULL;
6574   }
6575 
6576   ret->parent.offset = offset;
6577 
6578   return ret;
6579 }
6580 
6581 GType
mxf_descriptive_metadata_framework_get_type(void)6582 mxf_descriptive_metadata_framework_get_type (void)
6583 {
6584   static volatile gsize type = 0;
6585   if (g_once_init_enter (&type)) {
6586     GType _type = 0;
6587     static const GTypeInfo info = {
6588       sizeof (MXFDescriptiveMetadataFrameworkInterface),
6589       NULL,                     /* base_init */
6590       NULL,                     /* base_finalize */
6591       NULL,                     /* class_init */
6592       NULL,                     /* class_finalize */
6593       NULL,                     /* class_data */
6594       0,                        /* instance_size */
6595       0,                        /* n_preallocs */
6596       NULL                      /* instance_init */
6597     };
6598     _type = g_type_register_static (G_TYPE_INTERFACE,
6599         "MXFDescriptiveMetadataFrameworkInterface", &info, 0);
6600 
6601     g_type_interface_add_prerequisite (_type, MXF_TYPE_DESCRIPTIVE_METADATA);
6602 
6603     g_once_init_leave (&type, (gsize) _type);
6604   }
6605 
6606   return (GType) type;
6607 }
6608 
6609 GHashTable *
mxf_metadata_hash_table_new(void)6610 mxf_metadata_hash_table_new (void)
6611 {
6612   return g_hash_table_new_full ((GHashFunc) mxf_uuid_hash,
6613       (GEqualFunc) mxf_uuid_is_equal, (GDestroyNotify) NULL,
6614       (GDestroyNotify) g_object_unref);
6615 }
6616