• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_memdup2 (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   self->is_interleaved = MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (self->descriptor);
2251 
2252   for (i = 0; i < package->n_tracks; i++) {
2253     if (!package->tracks[i])
2254       continue;
2255 
2256     if (!MXF_IS_METADATA_MULTIPLE_DESCRIPTOR (d)) {
2257       if (d->linked_track_id == package->tracks[i]->track_id ||
2258           (d->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2259               (package->tracks[i]->type & 0xf0) == 0x30)) {
2260         g_free (package->tracks[i]->descriptor);
2261         package->tracks[i]->descriptor =
2262             g_new0 (MXFMetadataFileDescriptor *, 1);
2263         package->tracks[i]->descriptor[0] = d;
2264         package->tracks[i]->n_descriptor = 1;
2265         break;
2266       }
2267     } else {
2268       guint n_descriptor = 0, j, k = 0;
2269       MXFMetadataMultipleDescriptor *md = MXF_METADATA_MULTIPLE_DESCRIPTOR (d);
2270 
2271       for (j = 0; j < md->n_sub_descriptors; j++) {
2272         MXFMetadataFileDescriptor *fd;
2273 
2274         if (!md->sub_descriptors[j] ||
2275             !MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]))
2276           continue;
2277 
2278         fd = MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]);
2279 
2280         if (fd->linked_track_id == package->tracks[i]->track_id ||
2281             (fd->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2282                 (package->tracks[i]->type & 0xf0) == 0x30))
2283           n_descriptor++;
2284       }
2285 
2286       g_free (package->tracks[i]->descriptor);
2287       package->tracks[i]->descriptor =
2288           g_new0 (MXFMetadataFileDescriptor *, n_descriptor);
2289       package->tracks[i]->n_descriptor = n_descriptor;
2290 
2291       for (j = 0; j < md->n_sub_descriptors; j++) {
2292         MXFMetadataFileDescriptor *fd;
2293 
2294         if (!md->sub_descriptors[j] ||
2295             !MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]))
2296           continue;
2297 
2298         fd = MXF_METADATA_FILE_DESCRIPTOR (md->sub_descriptors[j]);
2299 
2300         if (fd->linked_track_id == package->tracks[i]->track_id ||
2301             (fd->linked_track_id == 0 && package->n_essence_tracks == 1 &&
2302                 (package->tracks[i]->type & 0xf0) == 0x30)) {
2303           package->tracks[i]->descriptor[k] = fd;
2304           k++;
2305         }
2306       }
2307     }
2308   }
2309 
2310   return ret;
2311 }
2312 
2313 static GstStructure *
mxf_metadata_source_package_to_structure(MXFMetadataBase * m)2314 mxf_metadata_source_package_to_structure (MXFMetadataBase * m)
2315 {
2316   GstStructure *ret =
2317       MXF_METADATA_BASE_CLASS
2318       (mxf_metadata_source_package_parent_class)->to_structure (m);
2319   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2320   GstStructure *s;
2321 
2322   if (!self->descriptor)
2323     return ret;
2324 
2325   s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->descriptor));
2326   gst_structure_id_set (ret, MXF_QUARK (DESCRIPTOR), GST_TYPE_STRUCTURE, s,
2327       NULL);
2328   gst_structure_free (s);
2329 
2330   return ret;
2331 }
2332 
2333 static GList *
mxf_metadata_source_package_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2334 mxf_metadata_source_package_write_tags (MXFMetadataBase * m,
2335     MXFPrimerPack * primer)
2336 {
2337   MXFMetadataSourcePackage *self = MXF_METADATA_SOURCE_PACKAGE (m);
2338   GList *ret =
2339       MXF_METADATA_BASE_CLASS
2340       (mxf_metadata_source_package_parent_class)->write_tags (m, primer);
2341   MXFLocalTag *t;
2342 
2343   if (self->descriptor) {
2344     t = g_slice_new0 (MXFLocalTag);
2345     memcpy (&t->ul, MXF_UL (DESCRIPTOR), 16);
2346     t->size = 16;
2347     t->data = g_slice_alloc (t->size);
2348     t->g_slice = TRUE;
2349     memcpy (t->data, &MXF_METADATA_BASE (self->descriptor)->instance_uid, 16);
2350     mxf_primer_pack_add_mapping (primer, 0x4701, &t->ul);
2351     ret = g_list_prepend (ret, t);
2352   }
2353 
2354   return ret;
2355 }
2356 
2357 static void
mxf_metadata_source_package_init(MXFMetadataSourcePackage * self)2358 mxf_metadata_source_package_init (MXFMetadataSourcePackage * self)
2359 {
2360 
2361 }
2362 
2363 static void
mxf_metadata_source_package_class_init(MXFMetadataSourcePackageClass * klass)2364 mxf_metadata_source_package_class_init (MXFMetadataSourcePackageClass * klass)
2365 {
2366   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2367   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2368 
2369   metadata_base_class->handle_tag = mxf_metadata_source_package_handle_tag;
2370   metadata_base_class->resolve = mxf_metadata_source_package_resolve;
2371   metadata_base_class->name_quark = MXF_QUARK (SOURCE_PACKAGE);
2372   metadata_base_class->to_structure = mxf_metadata_source_package_to_structure;
2373   metadata_base_class->write_tags = mxf_metadata_source_package_write_tags;
2374   metadata_class->type = 0x0137;
2375 }
2376 
2377 G_DEFINE_ABSTRACT_TYPE (MXFMetadataTrack, mxf_metadata_track,
2378     MXF_TYPE_METADATA);
2379 
2380 static void
mxf_metadata_track_finalize(GObject * object)2381 mxf_metadata_track_finalize (GObject * object)
2382 {
2383   MXFMetadataTrack *self = MXF_METADATA_TRACK (object);
2384 
2385   g_free (self->track_name);
2386   self->track_name = NULL;
2387   g_free (self->descriptor);
2388   self->descriptor = NULL;
2389 
2390   G_OBJECT_CLASS (mxf_metadata_track_parent_class)->finalize (object);
2391 }
2392 
2393 static gboolean
mxf_metadata_track_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2394 mxf_metadata_track_handle_tag (MXFMetadataBase * metadata,
2395     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2396     guint tag_size)
2397 {
2398   MXFMetadataTrack *self = MXF_METADATA_TRACK (metadata);
2399   gboolean ret = TRUE;
2400 #ifndef GST_DISABLE_GST_DEBUG
2401   gchar str[48];
2402 #endif
2403 
2404   switch (tag) {
2405     case 0x4801:
2406       if (tag_size != 4)
2407         goto error;
2408       self->track_id = GST_READ_UINT32_BE (tag_data);
2409       GST_DEBUG ("  track id = %u", self->track_id);
2410       break;
2411     case 0x4804:
2412       if (tag_size != 4)
2413         goto error;
2414       self->track_number = GST_READ_UINT32_BE (tag_data);
2415       GST_DEBUG ("  track number = %u", self->track_number);
2416       break;
2417     case 0x4802:
2418       self->track_name = mxf_utf16_to_utf8 (tag_data, tag_size);
2419       GST_DEBUG ("  track name = %s", GST_STR_NULL (self->track_name));
2420       break;
2421     case 0x4803:
2422       if (tag_size != 16)
2423         goto error;
2424       memcpy (&self->sequence_uid, tag_data, 16);
2425       GST_DEBUG ("  sequence uid = %s",
2426           mxf_uuid_to_string (&self->sequence_uid, str));
2427       break;
2428     default:
2429       ret =
2430           MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->handle_tag
2431           (metadata, primer, tag, tag_data, tag_size);
2432       break;
2433   }
2434 
2435   return ret;
2436 
2437 error:
2438 
2439   GST_ERROR ("Invalid track local tag 0x%04x of size %u", tag, tag_size);
2440 
2441   return FALSE;
2442 }
2443 
2444 static gboolean
mxf_metadata_track_resolve(MXFMetadataBase * m,GHashTable * metadata)2445 mxf_metadata_track_resolve (MXFMetadataBase * m, GHashTable * metadata)
2446 {
2447   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2448   MXFMetadataBase *current = NULL;
2449   guint i;
2450 #ifndef GST_DISABLE_GST_DEBUG
2451   gchar str[48];
2452 #endif
2453 
2454   current = g_hash_table_lookup (metadata, &self->sequence_uid);
2455   if (current && MXF_IS_METADATA_SEQUENCE (current)) {
2456     if (mxf_metadata_base_resolve (current, metadata)) {
2457       self->sequence = MXF_METADATA_SEQUENCE (current);
2458     } else {
2459       GST_ERROR ("Couldn't resolve sequence %s",
2460           mxf_uuid_to_string (&self->sequence_uid, str));
2461       return FALSE;
2462     }
2463   } else {
2464     GST_ERROR ("Couldn't find sequence %s",
2465         mxf_uuid_to_string (&self->sequence_uid, str));
2466     return FALSE;
2467   }
2468 
2469   self->type =
2470       mxf_metadata_track_identifier_parse (&self->sequence->data_definition);
2471   if (self->type == MXF_METADATA_TRACK_UNKNOWN) {
2472     MXFMetadataSequence *sequence = self->sequence;
2473 
2474     for (i = 0; i < sequence->n_structural_components; i++) {
2475       MXFMetadataStructuralComponent *component =
2476           sequence->structural_components[i];
2477 
2478       if (!component)
2479         continue;
2480 
2481       self->type =
2482           mxf_metadata_track_identifier_parse (&component->data_definition);
2483       if (self->type != MXF_METADATA_TRACK_UNKNOWN)
2484         break;
2485     }
2486   }
2487 
2488   return MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->resolve (m,
2489       metadata);
2490 }
2491 
2492 static GstStructure *
mxf_metadata_track_to_structure(MXFMetadataBase * m)2493 mxf_metadata_track_to_structure (MXFMetadataBase * m)
2494 {
2495   GstStructure *ret =
2496       MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->to_structure
2497       (m);
2498   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2499 
2500   gst_structure_id_set (ret, MXF_QUARK (TRACK_ID), G_TYPE_UINT, self->track_id,
2501       MXF_QUARK (TRACK_NUMBER), G_TYPE_UINT, self->track_number, NULL);
2502 
2503   if (self->track_name)
2504     gst_structure_id_set (ret, MXF_QUARK (TRACK_NAME), G_TYPE_STRING,
2505         self->track_name, NULL);
2506 
2507   if (self->sequence) {
2508     GstStructure *s =
2509         mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->sequence));
2510 
2511     gst_structure_id_set (ret, MXF_QUARK (SEQUENCE), GST_TYPE_STRUCTURE, s,
2512         NULL);
2513     gst_structure_free (s);
2514   }
2515 
2516 
2517   return ret;
2518 }
2519 
2520 static GList *
mxf_metadata_track_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2521 mxf_metadata_track_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
2522 {
2523   MXFMetadataTrack *self = MXF_METADATA_TRACK (m);
2524   GList *ret =
2525       MXF_METADATA_BASE_CLASS (mxf_metadata_track_parent_class)->write_tags (m,
2526       primer);
2527   MXFLocalTag *t;
2528 
2529   t = g_slice_new0 (MXFLocalTag);
2530   memcpy (&t->ul, MXF_UL (TRACK_ID), 16);
2531   t->size = 4;
2532   t->data = g_slice_alloc (t->size);
2533   t->g_slice = TRUE;
2534   GST_WRITE_UINT32_BE (t->data, self->track_id);
2535   mxf_primer_pack_add_mapping (primer, 0x4801, &t->ul);
2536   ret = g_list_prepend (ret, t);
2537 
2538   t = g_slice_new0 (MXFLocalTag);
2539   memcpy (&t->ul, MXF_UL (TRACK_NUMBER), 16);
2540   t->size = 4;
2541   t->data = g_slice_alloc (t->size);
2542   t->g_slice = TRUE;
2543   GST_WRITE_UINT32_BE (t->data, self->track_number);
2544   mxf_primer_pack_add_mapping (primer, 0x4804, &t->ul);
2545   ret = g_list_prepend (ret, t);
2546 
2547   if (self->track_name) {
2548     t = g_slice_new0 (MXFLocalTag);
2549     memcpy (&t->ul, MXF_UL (TRACK_NAME), 16);
2550     t->data = mxf_utf8_to_utf16 (self->track_name, &t->size);
2551     mxf_primer_pack_add_mapping (primer, 0x4802, &t->ul);
2552     ret = g_list_prepend (ret, t);
2553   }
2554 
2555   t = g_slice_new0 (MXFLocalTag);
2556   memcpy (&t->ul, MXF_UL (SEQUENCE), 16);
2557   t->size = 16;
2558   t->data = g_slice_alloc (t->size);
2559   t->g_slice = TRUE;
2560   memcpy (t->data, &MXF_METADATA_BASE (self->sequence)->instance_uid, 16);
2561   mxf_primer_pack_add_mapping (primer, 0x4803, &t->ul);
2562   ret = g_list_prepend (ret, t);
2563 
2564   return ret;
2565 }
2566 
2567 static void
mxf_metadata_track_init(MXFMetadataTrack * self)2568 mxf_metadata_track_init (MXFMetadataTrack * self)
2569 {
2570 
2571 }
2572 
2573 static void
mxf_metadata_track_class_init(MXFMetadataTrackClass * klass)2574 mxf_metadata_track_class_init (MXFMetadataTrackClass * klass)
2575 {
2576   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2577   GObjectClass *object_class = (GObjectClass *) klass;
2578 
2579   object_class->finalize = mxf_metadata_track_finalize;
2580   metadata_base_class->handle_tag = mxf_metadata_track_handle_tag;
2581   metadata_base_class->resolve = mxf_metadata_track_resolve;
2582   metadata_base_class->to_structure = mxf_metadata_track_to_structure;
2583   metadata_base_class->write_tags = mxf_metadata_track_write_tags;
2584 }
2585 
2586 /* SMPTE RP224 */
2587 static const struct
2588 {
2589   const MXFUL *ul;
2590   const MXFMetadataTrackType type;
2591 } mxf_metadata_track_identifier[] = {
2592   {
2593   MXF_UL (TRACK_TIMECODE_12M_INACTIVE),
2594         MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE}, {
2595   MXF_UL (TRACK_TIMECODE_12M_ACTIVE), MXF_METADATA_TRACK_TIMECODE_12M_ACTIVE}, {
2596   MXF_UL (TRACK_TIMECODE_309M), MXF_METADATA_TRACK_TIMECODE_309M}, {
2597   MXF_UL (TRACK_METADATA), MXF_METADATA_TRACK_METADATA}, {
2598   MXF_UL (TRACK_PICTURE_ESSENCE), MXF_METADATA_TRACK_PICTURE_ESSENCE}, {
2599   MXF_UL (TRACK_SOUND_ESSENCE), MXF_METADATA_TRACK_SOUND_ESSENCE}, {
2600   MXF_UL (TRACK_DATA_ESSENCE), MXF_METADATA_TRACK_DATA_ESSENCE}, {
2601   MXF_UL (TRACK_AUXILIARY_DATA), MXF_METADATA_TRACK_AUXILIARY_DATA}, {
2602   MXF_UL (TRACK_PARSED_TEXT), MXF_METADATA_TRACK_PARSED_TEXT},
2603       /* Avid video? */
2604   {
2605   MXF_UL (TRACK_AVID_PICTURE_ESSENCE), MXF_METADATA_TRACK_PICTURE_ESSENCE}
2606 };
2607 
2608 MXFMetadataTrackType
mxf_metadata_track_identifier_parse(const MXFUL * track_identifier)2609 mxf_metadata_track_identifier_parse (const MXFUL * track_identifier)
2610 {
2611   guint i;
2612 
2613   for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
2614     if (mxf_ul_is_equal (mxf_metadata_track_identifier[i].ul, track_identifier))
2615       return mxf_metadata_track_identifier[i].type;
2616 
2617   return MXF_METADATA_TRACK_UNKNOWN;
2618 }
2619 
2620 const MXFUL *
mxf_metadata_track_identifier_get(MXFMetadataTrackType type)2621 mxf_metadata_track_identifier_get (MXFMetadataTrackType type)
2622 {
2623   guint i;
2624 
2625   for (i = 0; i < G_N_ELEMENTS (mxf_metadata_track_identifier); i++)
2626     if (mxf_metadata_track_identifier[i].type == type)
2627       return mxf_metadata_track_identifier[i].ul;
2628 
2629   return NULL;
2630 }
2631 
2632 G_DEFINE_TYPE (MXFMetadataTimelineTrack, mxf_metadata_timeline_track,
2633     MXF_TYPE_METADATA_TRACK);
2634 
2635 static gboolean
mxf_metadata_timeline_track_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2636 mxf_metadata_timeline_track_handle_tag (MXFMetadataBase * metadata,
2637     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2638     guint tag_size)
2639 {
2640   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (metadata);
2641   gboolean ret = TRUE;
2642 
2643   switch (tag) {
2644     case 0x4b01:
2645       if (!mxf_fraction_parse (&self->edit_rate, tag_data, tag_size))
2646         goto error;
2647       GST_DEBUG ("  edit rate = %d/%d", self->edit_rate.n, self->edit_rate.d);
2648       break;
2649     case 0x4b02:
2650       if (tag_size != 8)
2651         goto error;
2652       self->origin = GST_READ_UINT64_BE (tag_data);
2653       GST_DEBUG ("  origin = %" G_GINT64_FORMAT, self->origin);
2654       break;
2655     default:
2656       ret =
2657           MXF_METADATA_BASE_CLASS
2658           (mxf_metadata_timeline_track_parent_class)->handle_tag (metadata,
2659           primer, tag, tag_data, tag_size);
2660       break;
2661   }
2662 
2663   return ret;
2664 
2665 error:
2666 
2667   GST_ERROR ("Invalid timeline track local tag 0x%04x of size %u", tag,
2668       tag_size);
2669 
2670   return FALSE;
2671 }
2672 
2673 static GstStructure *
mxf_metadata_timeline_track_to_structure(MXFMetadataBase * m)2674 mxf_metadata_timeline_track_to_structure (MXFMetadataBase * m)
2675 {
2676   GstStructure *ret =
2677       MXF_METADATA_BASE_CLASS
2678       (mxf_metadata_timeline_track_parent_class)->to_structure (m);
2679   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (m);
2680 
2681   gst_structure_id_set (ret, MXF_QUARK (EDIT_RATE), GST_TYPE_FRACTION,
2682       self->edit_rate.n, self->edit_rate.d, MXF_QUARK (ORIGIN), G_TYPE_INT64,
2683       self->origin, NULL);
2684 
2685   return ret;
2686 }
2687 
2688 static GList *
mxf_metadata_timeline_track_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2689 mxf_metadata_timeline_track_write_tags (MXFMetadataBase * m,
2690     MXFPrimerPack * primer)
2691 {
2692   MXFMetadataTimelineTrack *self = MXF_METADATA_TIMELINE_TRACK (m);
2693   GList *ret =
2694       MXF_METADATA_BASE_CLASS
2695       (mxf_metadata_timeline_track_parent_class)->write_tags (m, primer);
2696   MXFLocalTag *t;
2697 
2698   t = g_slice_new0 (MXFLocalTag);
2699   memcpy (&t->ul, MXF_UL (EDIT_RATE), 16);
2700   t->size = 8;
2701   t->data = g_slice_alloc (t->size);
2702   t->g_slice = TRUE;
2703   GST_WRITE_UINT32_BE (t->data, self->edit_rate.n);
2704   GST_WRITE_UINT32_BE (t->data + 4, self->edit_rate.d);
2705   mxf_primer_pack_add_mapping (primer, 0x4b01, &t->ul);
2706   ret = g_list_prepend (ret, t);
2707 
2708   t = g_slice_new0 (MXFLocalTag);
2709   memcpy (&t->ul, MXF_UL (ORIGIN), 16);
2710   t->size = 8;
2711   t->data = g_slice_alloc (t->size);
2712   t->g_slice = TRUE;
2713   GST_WRITE_UINT64_BE (t->data, self->origin);
2714   mxf_primer_pack_add_mapping (primer, 0x4b02, &t->ul);
2715   ret = g_list_prepend (ret, t);
2716 
2717   return ret;
2718 }
2719 
2720 static void
mxf_metadata_timeline_track_init(MXFMetadataTimelineTrack * self)2721 mxf_metadata_timeline_track_init (MXFMetadataTimelineTrack * self)
2722 {
2723 
2724 }
2725 
2726 static void
mxf_metadata_timeline_track_class_init(MXFMetadataTimelineTrackClass * klass)2727 mxf_metadata_timeline_track_class_init (MXFMetadataTimelineTrackClass * klass)
2728 {
2729   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2730   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2731 
2732   metadata_base_class->handle_tag = mxf_metadata_timeline_track_handle_tag;
2733   metadata_base_class->name_quark = MXF_QUARK (TIMELINE_TRACK);
2734   metadata_base_class->to_structure = mxf_metadata_timeline_track_to_structure;
2735   metadata_base_class->write_tags = mxf_metadata_timeline_track_write_tags;
2736   metadata_class->type = 0x013b;
2737 }
2738 
2739 G_DEFINE_TYPE (MXFMetadataEventTrack, mxf_metadata_event_track,
2740     MXF_TYPE_METADATA_TRACK);
2741 
2742 static gboolean
mxf_metadata_event_track_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2743 mxf_metadata_event_track_handle_tag (MXFMetadataBase * metadata,
2744     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2745     guint tag_size)
2746 {
2747   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (metadata);
2748   gboolean ret = TRUE;
2749 
2750   switch (tag) {
2751     case 0x4901:
2752       if (!mxf_fraction_parse (&self->event_edit_rate, tag_data, tag_size))
2753         goto error;
2754       GST_DEBUG ("  event edit rate = %d/%d", self->event_edit_rate.n,
2755           self->event_edit_rate.d);
2756       break;
2757     case 0x4902:
2758       if (tag_size != 8)
2759         goto error;
2760       self->event_origin = GST_READ_UINT64_BE (tag_data);
2761       GST_DEBUG ("  event origin = %" G_GINT64_FORMAT, self->event_origin);
2762       break;
2763     default:
2764       ret =
2765           MXF_METADATA_BASE_CLASS
2766           (mxf_metadata_event_track_parent_class)->handle_tag (metadata, primer,
2767           tag, tag_data, tag_size);
2768       break;
2769   }
2770 
2771   return ret;
2772 
2773 error:
2774 
2775   GST_ERROR ("Invalid event track local tag 0x%04x of size %u", tag, tag_size);
2776 
2777   return FALSE;
2778 }
2779 
2780 static GstStructure *
mxf_metadata_event_track_to_structure(MXFMetadataBase * m)2781 mxf_metadata_event_track_to_structure (MXFMetadataBase * m)
2782 {
2783   GstStructure *ret =
2784       MXF_METADATA_BASE_CLASS
2785       (mxf_metadata_event_track_parent_class)->to_structure (m);
2786   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (m);
2787 
2788   gst_structure_id_set (ret, MXF_QUARK (EVENT_EDIT_RATE), GST_TYPE_FRACTION,
2789       self->event_edit_rate.n, self->event_edit_rate.d,
2790       MXF_QUARK (EVENT_ORIGIN), G_TYPE_INT64, self->event_origin, NULL);
2791 
2792   return ret;
2793 }
2794 
2795 static GList *
mxf_metadata_event_track_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)2796 mxf_metadata_event_track_write_tags (MXFMetadataBase * m,
2797     MXFPrimerPack * primer)
2798 {
2799   MXFMetadataEventTrack *self = MXF_METADATA_EVENT_TRACK (m);
2800   GList *ret =
2801       MXF_METADATA_BASE_CLASS
2802       (mxf_metadata_event_track_parent_class)->write_tags (m, primer);
2803   MXFLocalTag *t;
2804 
2805   t = g_slice_new0 (MXFLocalTag);
2806   memcpy (&t->ul, MXF_UL (EVENT_EDIT_RATE), 16);
2807   t->size = 8;
2808   t->data = g_slice_alloc (t->size);
2809   t->g_slice = TRUE;
2810   GST_WRITE_UINT32_BE (t->data, self->event_edit_rate.n);
2811   GST_WRITE_UINT32_BE (t->data + 4, self->event_edit_rate.d);
2812   mxf_primer_pack_add_mapping (primer, 0x4901, &t->ul);
2813   ret = g_list_prepend (ret, t);
2814 
2815   t = g_slice_new0 (MXFLocalTag);
2816   memcpy (&t->ul, MXF_UL (EVENT_ORIGIN), 16);
2817   t->size = 8;
2818   t->data = g_slice_alloc (t->size);
2819   t->g_slice = TRUE;
2820   GST_WRITE_UINT64_BE (t->data, self->event_origin);
2821   mxf_primer_pack_add_mapping (primer, 0x4902, &t->ul);
2822   ret = g_list_prepend (ret, t);
2823 
2824   return ret;
2825 }
2826 
2827 static void
mxf_metadata_event_track_init(MXFMetadataEventTrack * self)2828 mxf_metadata_event_track_init (MXFMetadataEventTrack * self)
2829 {
2830 
2831 }
2832 
2833 static void
mxf_metadata_event_track_class_init(MXFMetadataEventTrackClass * klass)2834 mxf_metadata_event_track_class_init (MXFMetadataEventTrackClass * klass)
2835 {
2836   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2837   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2838 
2839   metadata_base_class->handle_tag = mxf_metadata_event_track_handle_tag;
2840   metadata_base_class->name_quark = MXF_QUARK (EVENT_TRACK);
2841   metadata_base_class->to_structure = mxf_metadata_event_track_to_structure;
2842   metadata_base_class->write_tags = mxf_metadata_event_track_write_tags;
2843   metadata_class->type = 0x0139;
2844 }
2845 
2846 G_DEFINE_TYPE (MXFMetadataStaticTrack, mxf_metadata_static_track,
2847     MXF_TYPE_METADATA_TRACK);
2848 
2849 static void
mxf_metadata_static_track_init(MXFMetadataStaticTrack * self)2850 mxf_metadata_static_track_init (MXFMetadataStaticTrack * self)
2851 {
2852 }
2853 
2854 static void
mxf_metadata_static_track_class_init(MXFMetadataStaticTrackClass * klass)2855 mxf_metadata_static_track_class_init (MXFMetadataStaticTrackClass * klass)
2856 {
2857   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
2858   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
2859 
2860   metadata_base_class->name_quark = MXF_QUARK (STATIC_TRACK);
2861   metadata_class->type = 0x013a;
2862 }
2863 
2864 G_DEFINE_TYPE (MXFMetadataSequence, mxf_metadata_sequence, MXF_TYPE_METADATA);
2865 
2866 static void
mxf_metadata_sequence_finalize(GObject * object)2867 mxf_metadata_sequence_finalize (GObject * object)
2868 {
2869   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (object);
2870 
2871   g_free (self->structural_components_uids);
2872   self->structural_components_uids = NULL;
2873   g_free (self->structural_components);
2874   self->structural_components = NULL;
2875 
2876   G_OBJECT_CLASS (mxf_metadata_sequence_parent_class)->finalize (object);
2877 }
2878 
2879 static gboolean
mxf_metadata_sequence_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)2880 mxf_metadata_sequence_handle_tag (MXFMetadataBase * metadata,
2881     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
2882     guint tag_size)
2883 {
2884   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (metadata);
2885   gboolean ret = TRUE;
2886 #ifndef GST_DISABLE_GST_DEBUG
2887   gchar str[48];
2888 #endif
2889 
2890   switch (tag) {
2891     case 0x0201:
2892       if (tag_size != 16)
2893         goto error;
2894       memcpy (&self->data_definition, tag_data, 16);
2895       GST_DEBUG ("  data definition = %s",
2896           mxf_ul_to_string (&self->data_definition, str));
2897       break;
2898     case 0x0202:
2899       if (tag_size != 8)
2900         goto error;
2901       self->duration = GST_READ_UINT64_BE (tag_data);
2902       GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
2903       break;
2904     case 0x1001:
2905       if (!mxf_uuid_array_parse (&self->structural_components_uids,
2906               &self->n_structural_components, tag_data, tag_size))
2907         goto error;
2908 
2909       GST_DEBUG ("  number of structural components = %u",
2910           self->n_structural_components);
2911 #ifndef GST_DISABLE_GST_DEBUG
2912       {
2913         guint i;
2914         for (i = 0; i < self->n_structural_components; i++) {
2915           GST_DEBUG ("  structural component %u = %s", i,
2916               mxf_uuid_to_string (&self->structural_components_uids[i], str));
2917         }
2918       }
2919 #endif
2920       break;
2921     default:
2922       ret =
2923           MXF_METADATA_BASE_CLASS
2924           (mxf_metadata_sequence_parent_class)->handle_tag (metadata, primer,
2925           tag, tag_data, tag_size);
2926       break;
2927   }
2928 
2929   return ret;
2930 
2931 error:
2932 
2933   GST_ERROR ("Invalid sequence local tag 0x%04x of size %u", tag, tag_size);
2934 
2935   return FALSE;
2936 }
2937 
2938 static gboolean
mxf_metadata_sequence_resolve(MXFMetadataBase * m,GHashTable * metadata)2939 mxf_metadata_sequence_resolve (MXFMetadataBase * m, GHashTable * metadata)
2940 {
2941   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2942   MXFMetadataBase *current = NULL;
2943   guint i;
2944 #ifndef GST_DISABLE_GST_DEBUG
2945   gchar str[48];
2946 #endif
2947 
2948   if (self->structural_components)
2949     memset (self->structural_components, 0,
2950         sizeof (gpointer) * self->n_structural_components);
2951   else
2952     self->structural_components =
2953         g_new0 (MXFMetadataStructuralComponent *,
2954         self->n_structural_components);
2955   for (i = 0; i < self->n_structural_components; i++) {
2956     current =
2957         g_hash_table_lookup (metadata, &self->structural_components_uids[i]);
2958     if (current && MXF_IS_METADATA_STRUCTURAL_COMPONENT (current)) {
2959       if (mxf_metadata_base_resolve (current, metadata)) {
2960         self->structural_components[i] =
2961             MXF_METADATA_STRUCTURAL_COMPONENT (current);
2962       } else {
2963         GST_ERROR ("Couldn't resolve structural component %s",
2964             mxf_uuid_to_string (&self->structural_components_uids[i], str));
2965         return FALSE;
2966       }
2967     } else {
2968       GST_ERROR ("Structural component %s not found",
2969           mxf_uuid_to_string (&self->structural_components_uids[i], str));
2970       return FALSE;
2971     }
2972   }
2973 
2974   return
2975       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->resolve (m,
2976       metadata);
2977 
2978 }
2979 
2980 static GstStructure *
mxf_metadata_sequence_to_structure(MXFMetadataBase * m)2981 mxf_metadata_sequence_to_structure (MXFMetadataBase * m)
2982 {
2983   GstStructure *ret =
2984       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->to_structure
2985       (m);
2986   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
2987   guint i;
2988   gchar str[48];
2989 
2990   mxf_ul_to_string (&self->data_definition, str);
2991   gst_structure_id_set (ret, MXF_QUARK (DATA_DEFINITION), G_TYPE_STRING, str,
2992       MXF_QUARK (DURATION), G_TYPE_INT64, self->duration, NULL);
2993 
2994   if (self->n_structural_components > 0) {
2995     GValue arr = { 0, }
2996     , val = {
2997     0,};
2998 
2999     g_value_init (&arr, GST_TYPE_ARRAY);
3000 
3001     for (i = 0; i < self->n_structural_components; i++) {
3002       GstStructure *s;
3003 
3004       if (self->structural_components[i] == NULL)
3005         continue;
3006 
3007       g_value_init (&val, GST_TYPE_STRUCTURE);
3008 
3009       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
3010           (self->structural_components[i]));
3011       gst_value_set_structure (&val, s);
3012       gst_structure_free (s);
3013       gst_value_array_append_value (&arr, &val);
3014       g_value_unset (&val);
3015     }
3016 
3017     if (gst_value_array_get_size (&arr) > 0)
3018       gst_structure_id_set_value (ret, MXF_QUARK (STRUCTURAL_COMPONENTS), &arr);
3019 
3020     g_value_unset (&arr);
3021   }
3022 
3023   return ret;
3024 }
3025 
3026 static GList *
mxf_metadata_sequence_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3027 mxf_metadata_sequence_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
3028 {
3029   MXFMetadataSequence *self = MXF_METADATA_SEQUENCE (m);
3030   GList *ret =
3031       MXF_METADATA_BASE_CLASS (mxf_metadata_sequence_parent_class)->write_tags
3032       (m, primer);
3033   MXFLocalTag *t;
3034 
3035   t = g_slice_new0 (MXFLocalTag);
3036   memcpy (&t->ul, MXF_UL (DATA_DEFINITION), 16);
3037   t->size = 16;
3038   t->data = g_slice_alloc (t->size);
3039   t->g_slice = TRUE;
3040   memcpy (t->data, &self->data_definition, 16);
3041   mxf_primer_pack_add_mapping (primer, 0x0201, &t->ul);
3042   ret = g_list_prepend (ret, t);
3043 
3044   t = g_slice_new0 (MXFLocalTag);
3045   memcpy (&t->ul, MXF_UL (DURATION), 16);
3046   t->size = 8;
3047   t->data = g_slice_alloc (t->size);
3048   t->g_slice = TRUE;
3049   GST_WRITE_UINT64_BE (t->data, self->duration);
3050   mxf_primer_pack_add_mapping (primer, 0x0202, &t->ul);
3051   ret = g_list_prepend (ret, t);
3052 
3053   if (self->structural_components) {
3054     guint i;
3055     t = g_slice_new0 (MXFLocalTag);
3056     memcpy (&t->ul, MXF_UL (STRUCTURAL_COMPONENTS), 16);
3057     t->size = 8 + 16 * self->n_structural_components;
3058     t->data = g_slice_alloc0 (t->size);
3059     t->g_slice = TRUE;
3060 
3061     GST_WRITE_UINT32_BE (t->data, self->n_structural_components);
3062     GST_WRITE_UINT32_BE (t->data + 4, 16);
3063     for (i = 0; i < self->n_structural_components; i++) {
3064       if (!self->structural_components[i])
3065         continue;
3066 
3067       memcpy (t->data + 8 + i * 16,
3068           &MXF_METADATA_BASE (self->structural_components[i])->instance_uid,
3069           16);
3070     }
3071 
3072     mxf_primer_pack_add_mapping (primer, 0x1001, &t->ul);
3073     ret = g_list_prepend (ret, t);
3074   }
3075 
3076   return ret;
3077 }
3078 
3079 static void
mxf_metadata_sequence_init(MXFMetadataSequence * self)3080 mxf_metadata_sequence_init (MXFMetadataSequence * self)
3081 {
3082   self->duration = -1;
3083 }
3084 
3085 static void
mxf_metadata_sequence_class_init(MXFMetadataSequenceClass * klass)3086 mxf_metadata_sequence_class_init (MXFMetadataSequenceClass * klass)
3087 {
3088   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3089   GObjectClass *object_class = (GObjectClass *) klass;
3090   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3091 
3092   object_class->finalize = mxf_metadata_sequence_finalize;
3093   metadata_base_class->handle_tag = mxf_metadata_sequence_handle_tag;
3094   metadata_base_class->resolve = mxf_metadata_sequence_resolve;
3095   metadata_base_class->name_quark = MXF_QUARK (SEQUENCE);
3096   metadata_base_class->to_structure = mxf_metadata_sequence_to_structure;
3097   metadata_base_class->write_tags = mxf_metadata_sequence_write_tags;
3098   metadata_class->type = 0x010f;
3099 }
3100 
3101 G_DEFINE_TYPE (MXFMetadataStructuralComponent,
3102     mxf_metadata_structural_component, MXF_TYPE_METADATA);
3103 
3104 static gboolean
mxf_metadata_structural_component_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3105 mxf_metadata_structural_component_handle_tag (MXFMetadataBase * metadata,
3106     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3107     guint tag_size)
3108 {
3109   MXFMetadataStructuralComponent *self =
3110       MXF_METADATA_STRUCTURAL_COMPONENT (metadata);
3111   gboolean ret = TRUE;
3112 #ifndef GST_DISABLE_GST_DEBUG
3113   gchar str[48];
3114 #endif
3115 
3116   switch (tag) {
3117     case 0x0201:
3118       if (tag_size != 16)
3119         goto error;
3120       memcpy (&self->data_definition, tag_data, 16);
3121       GST_DEBUG ("  data definition = %s",
3122           mxf_ul_to_string (&self->data_definition, str));
3123       break;
3124     case 0x0202:
3125       if (tag_size != 8)
3126         goto error;
3127       self->duration = GST_READ_UINT64_BE (tag_data);
3128       GST_DEBUG ("  duration = %" G_GINT64_FORMAT, self->duration);
3129       break;
3130     default:
3131       ret =
3132           MXF_METADATA_BASE_CLASS
3133           (mxf_metadata_structural_component_parent_class)->handle_tag
3134           (metadata, primer, tag, tag_data, tag_size);
3135       break;
3136   }
3137 
3138   return ret;
3139 
3140 error:
3141 
3142   GST_ERROR ("Invalid structural component local tag 0x%04x of size %u", tag,
3143       tag_size);
3144 
3145   return FALSE;
3146 }
3147 
3148 static GstStructure *
mxf_metadata_structural_component_to_structure(MXFMetadataBase * m)3149 mxf_metadata_structural_component_to_structure (MXFMetadataBase * m)
3150 {
3151   GstStructure *ret =
3152       MXF_METADATA_BASE_CLASS
3153       (mxf_metadata_structural_component_parent_class)->to_structure (m);
3154   MXFMetadataStructuralComponent *self = MXF_METADATA_STRUCTURAL_COMPONENT (m);
3155   gchar str[48];
3156 
3157   mxf_ul_to_string (&self->data_definition, str);
3158   gst_structure_id_set (ret, MXF_QUARK (DATA_DEFINITION), G_TYPE_STRING, str,
3159       MXF_QUARK (DURATION), G_TYPE_INT64, self->duration, NULL);
3160 
3161   return ret;
3162 }
3163 
3164 static GList *
mxf_metadata_structural_component_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3165 mxf_metadata_structural_component_write_tags (MXFMetadataBase * m,
3166     MXFPrimerPack * primer)
3167 {
3168   MXFMetadataStructuralComponent *self = MXF_METADATA_STRUCTURAL_COMPONENT (m);
3169   GList *ret =
3170       MXF_METADATA_BASE_CLASS
3171       (mxf_metadata_structural_component_parent_class)->write_tags (m, primer);
3172   MXFLocalTag *t;
3173 
3174   t = g_slice_new0 (MXFLocalTag);
3175   memcpy (&t->ul, MXF_UL (DATA_DEFINITION), 16);
3176   t->size = 16;
3177   t->data = g_slice_alloc (t->size);
3178   t->g_slice = TRUE;
3179   memcpy (t->data, &self->data_definition, 16);
3180   mxf_primer_pack_add_mapping (primer, 0x0201, &t->ul);
3181   ret = g_list_prepend (ret, t);
3182 
3183   t = g_slice_new0 (MXFLocalTag);
3184   memcpy (&t->ul, MXF_UL (DURATION), 16);
3185   t->size = 8;
3186   t->data = g_slice_alloc (t->size);
3187   t->g_slice = TRUE;
3188   GST_WRITE_UINT64_BE (t->data, self->duration);
3189   mxf_primer_pack_add_mapping (primer, 0x0202, &t->ul);
3190   ret = g_list_prepend (ret, t);
3191 
3192   return ret;
3193 }
3194 
3195 static void
mxf_metadata_structural_component_init(MXFMetadataStructuralComponent * self)3196 mxf_metadata_structural_component_init (MXFMetadataStructuralComponent * self)
3197 {
3198   self->duration = -1;
3199 }
3200 
3201 static void
mxf_metadata_structural_component_class_init(MXFMetadataStructuralComponentClass * klass)3202     mxf_metadata_structural_component_class_init
3203     (MXFMetadataStructuralComponentClass * klass)
3204 {
3205   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3206 
3207   metadata_base_class->handle_tag =
3208       mxf_metadata_structural_component_handle_tag;
3209   metadata_base_class->to_structure =
3210       mxf_metadata_structural_component_to_structure;
3211   metadata_base_class->write_tags =
3212       mxf_metadata_structural_component_write_tags;
3213 }
3214 
3215 G_DEFINE_TYPE (MXFMetadataTimecodeComponent, mxf_metadata_timecode_component,
3216     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3217 
3218 static gboolean
mxf_metadata_timecode_component_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3219 mxf_metadata_timecode_component_handle_tag (MXFMetadataBase * metadata,
3220     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3221     guint tag_size)
3222 {
3223   MXFMetadataTimecodeComponent *self =
3224       MXF_METADATA_TIMECODE_COMPONENT (metadata);
3225   gboolean ret = TRUE;
3226 
3227   switch (tag) {
3228     case 0x1502:
3229       if (tag_size != 2)
3230         goto error;
3231       self->rounded_timecode_base = GST_READ_UINT16_BE (tag_data);
3232       GST_DEBUG ("  rounded timecode base = %u", self->rounded_timecode_base);
3233       break;
3234     case 0x1501:
3235       if (tag_size != 8)
3236         goto error;
3237       self->start_timecode = GST_READ_UINT64_BE (tag_data);
3238       GST_DEBUG ("  start timecode = %" G_GINT64_FORMAT, self->start_timecode);
3239       break;
3240     case 0x1503:
3241       if (tag_size != 1)
3242         goto error;
3243       self->drop_frame = (GST_READ_UINT8 (tag_data) != 0);
3244       GST_DEBUG ("  drop frame = %s", (self->drop_frame) ? "yes" : "no");
3245       break;
3246     default:
3247       ret =
3248           MXF_METADATA_BASE_CLASS
3249           (mxf_metadata_timecode_component_parent_class)->handle_tag (metadata,
3250           primer, tag, tag_data, tag_size);
3251       break;
3252   }
3253 
3254   return ret;
3255 
3256 error:
3257 
3258   GST_ERROR ("Invalid timecode component local tag 0x%04x of size %u", tag,
3259       tag_size);
3260 
3261   return FALSE;
3262 }
3263 
3264 static GstStructure *
mxf_metadata_timecode_component_to_structure(MXFMetadataBase * m)3265 mxf_metadata_timecode_component_to_structure (MXFMetadataBase * m)
3266 {
3267   GstStructure *ret =
3268       MXF_METADATA_BASE_CLASS
3269       (mxf_metadata_timecode_component_parent_class)->to_structure (m);
3270   MXFMetadataTimecodeComponent *self = MXF_METADATA_TIMECODE_COMPONENT (m);
3271 
3272   gst_structure_id_set (ret, MXF_QUARK (START_TIMECODE), G_TYPE_INT64,
3273       self->start_timecode, MXF_QUARK (ROUNDED_TIMECODE_BASE), G_TYPE_UINT,
3274       self->rounded_timecode_base, MXF_QUARK (DROP_FRAME), G_TYPE_BOOLEAN,
3275       self->drop_frame, NULL);
3276 
3277   return ret;
3278 }
3279 
3280 static GList *
mxf_metadata_timecode_component_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3281 mxf_metadata_timecode_component_write_tags (MXFMetadataBase * m,
3282     MXFPrimerPack * primer)
3283 {
3284   MXFMetadataTimecodeComponent *self = MXF_METADATA_TIMECODE_COMPONENT (m);
3285   GList *ret =
3286       MXF_METADATA_BASE_CLASS
3287       (mxf_metadata_timecode_component_parent_class)->write_tags (m, primer);
3288   MXFLocalTag *t;
3289 
3290   t = g_slice_new0 (MXFLocalTag);
3291   memcpy (&t->ul, MXF_UL (ROUNDED_TIMECODE_BASE), 16);
3292   t->size = 2;
3293   t->data = g_slice_alloc (t->size);
3294   t->g_slice = TRUE;
3295   GST_WRITE_UINT16_BE (t->data, self->rounded_timecode_base);
3296   mxf_primer_pack_add_mapping (primer, 0x1502, &t->ul);
3297   ret = g_list_prepend (ret, t);
3298 
3299   t = g_slice_new0 (MXFLocalTag);
3300   memcpy (&t->ul, MXF_UL (START_TIMECODE), 16);
3301   t->size = 8;
3302   t->data = g_slice_alloc (t->size);
3303   t->g_slice = TRUE;
3304   GST_WRITE_UINT64_BE (t->data, self->start_timecode);
3305   mxf_primer_pack_add_mapping (primer, 0x1501, &t->ul);
3306   ret = g_list_prepend (ret, t);
3307 
3308   t = g_slice_new0 (MXFLocalTag);
3309   memcpy (&t->ul, MXF_UL (DROP_FRAME), 16);
3310   t->size = 1;
3311   t->data = g_slice_alloc (t->size);
3312   t->g_slice = TRUE;
3313   GST_WRITE_UINT8 (t->data, (self->drop_frame) ? 1 : 0);
3314   mxf_primer_pack_add_mapping (primer, 0x1503, &t->ul);
3315   ret = g_list_prepend (ret, t);
3316 
3317   return ret;
3318 }
3319 
3320 static void
mxf_metadata_timecode_component_init(MXFMetadataTimecodeComponent * self)3321 mxf_metadata_timecode_component_init (MXFMetadataTimecodeComponent * self)
3322 {
3323 
3324 }
3325 
3326 static void
mxf_metadata_timecode_component_class_init(MXFMetadataTimecodeComponentClass * klass)3327 mxf_metadata_timecode_component_class_init (MXFMetadataTimecodeComponentClass *
3328     klass)
3329 {
3330   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3331   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3332 
3333   metadata_base_class->handle_tag = mxf_metadata_timecode_component_handle_tag;
3334   metadata_base_class->name_quark = MXF_QUARK (TIMECODE_COMPONENT);
3335   metadata_base_class->to_structure =
3336       mxf_metadata_timecode_component_to_structure;
3337   metadata_base_class->write_tags = mxf_metadata_timecode_component_write_tags;
3338   metadata_class->type = 0x0114;
3339 }
3340 
3341 G_DEFINE_TYPE (MXFMetadataSourceClip, mxf_metadata_source_clip,
3342     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3343 
3344 static gboolean
mxf_metadata_source_clip_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3345 mxf_metadata_source_clip_handle_tag (MXFMetadataBase * metadata,
3346     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3347     guint tag_size)
3348 {
3349   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (metadata);
3350   gboolean ret = TRUE;
3351 #ifndef GST_DISABLE_GST_DEBUG
3352   gchar str[96];
3353 #endif
3354 
3355   switch (tag) {
3356     case 0x1201:
3357       if (tag_size != 8)
3358         goto error;
3359 
3360       self->start_position = GST_READ_UINT64_BE (tag_data);
3361       GST_DEBUG ("  start position = %" G_GINT64_FORMAT, self->start_position);
3362       break;
3363     case 0x1101:
3364       if (tag_size != 32)
3365         goto error;
3366 
3367       memcpy (&self->source_package_id, tag_data, 32);
3368       GST_DEBUG ("  source package id = %s",
3369           mxf_umid_to_string (&self->source_package_id, str));
3370       break;
3371     case 0x1102:
3372       if (tag_size != 4)
3373         goto error;
3374 
3375       self->source_track_id = GST_READ_UINT32_BE (tag_data);
3376       GST_DEBUG ("  source track id = %u", self->source_track_id);
3377       break;
3378     default:
3379       ret =
3380           MXF_METADATA_BASE_CLASS
3381           (mxf_metadata_source_clip_parent_class)->handle_tag (metadata, primer,
3382           tag, tag_data, tag_size);
3383       break;
3384   }
3385 
3386   return ret;
3387 
3388 error:
3389 
3390   GST_ERROR ("Invalid source clip local tag 0x%04x of size %u", tag, tag_size);
3391 
3392   return FALSE;
3393 }
3394 
3395 static gboolean
mxf_metadata_source_clip_resolve(MXFMetadataBase * m,GHashTable * metadata)3396 mxf_metadata_source_clip_resolve (MXFMetadataBase * m, GHashTable * metadata)
3397 {
3398   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3399   MXFMetadataBase *current = NULL;
3400   GHashTableIter iter;
3401 #ifndef GST_DISABLE_GST_DEBUG
3402   gchar str[96];
3403 #endif
3404 
3405   if (mxf_umid_is_zero (&self->source_package_id)) {
3406     /* S377-1:2019 B.10 Source Clip.
3407      *
3408      * SourcePackageID: The value shall be 32 zero valued bytes to terminate the
3409      * source reference chain.  */
3410     GST_LOG ("Skipping termination source package for source clip %s",
3411         mxf_uuid_to_string (&MXF_METADATA_BASE (self)->instance_uid, str));
3412     goto chain_up;
3413   }
3414 
3415   g_hash_table_iter_init (&iter, metadata);
3416 
3417   while (g_hash_table_iter_next (&iter, NULL, (gpointer) & current)) {
3418     if (MXF_IS_METADATA_SOURCE_PACKAGE (current)) {
3419       MXFMetadataGenericPackage *p = MXF_METADATA_GENERIC_PACKAGE (current);
3420 
3421       if (mxf_umid_is_equal (&p->package_uid, &self->source_package_id)) {
3422         self->source_package = MXF_METADATA_SOURCE_PACKAGE (current);
3423         break;
3424       }
3425     }
3426   }
3427 
3428   if (!self->source_package) {
3429     GST_ERROR ("Couldn't find source package %s",
3430         mxf_umid_to_string (&self->source_package_id, str));
3431   }
3432 
3433 chain_up:
3434   return
3435       MXF_METADATA_BASE_CLASS (mxf_metadata_source_clip_parent_class)->resolve
3436       (m, metadata);
3437 }
3438 
3439 static GstStructure *
mxf_metadata_source_clip_to_structure(MXFMetadataBase * m)3440 mxf_metadata_source_clip_to_structure (MXFMetadataBase * m)
3441 {
3442   GstStructure *ret =
3443       MXF_METADATA_BASE_CLASS
3444       (mxf_metadata_source_clip_parent_class)->to_structure (m);
3445   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3446   gchar str[96];
3447 
3448   mxf_umid_to_string (&self->source_package_id, str);
3449   gst_structure_id_set (ret, MXF_QUARK (START_POSITION), G_TYPE_INT64,
3450       self->start_position, MXF_QUARK (SOURCE_PACKAGE), G_TYPE_STRING, str,
3451       MXF_QUARK (SOURCE_TRACK_ID), G_TYPE_UINT, self->source_track_id, NULL);
3452 
3453   return ret;
3454 }
3455 
3456 static GList *
mxf_metadata_source_clip_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3457 mxf_metadata_source_clip_write_tags (MXFMetadataBase * m,
3458     MXFPrimerPack * primer)
3459 {
3460   MXFMetadataSourceClip *self = MXF_METADATA_SOURCE_CLIP (m);
3461   GList *ret =
3462       MXF_METADATA_BASE_CLASS
3463       (mxf_metadata_source_clip_parent_class)->write_tags (m, primer);
3464   MXFLocalTag *t;
3465 
3466   t = g_slice_new0 (MXFLocalTag);
3467   memcpy (&t->ul, MXF_UL (START_POSITION), 16);
3468   t->size = 8;
3469   t->data = g_slice_alloc (t->size);
3470   t->g_slice = TRUE;
3471   GST_WRITE_UINT64_BE (t->data, self->start_position);
3472   mxf_primer_pack_add_mapping (primer, 0x1201, &t->ul);
3473   ret = g_list_prepend (ret, t);
3474 
3475   t = g_slice_new0 (MXFLocalTag);
3476   memcpy (&t->ul, MXF_UL (SOURCE_PACKAGE_ID), 16);
3477   t->size = 32;
3478   t->data = g_slice_alloc (t->size);
3479   t->g_slice = TRUE;
3480   memcpy (t->data, &self->source_package_id, 32);
3481   mxf_primer_pack_add_mapping (primer, 0x1101, &t->ul);
3482   ret = g_list_prepend (ret, t);
3483 
3484   t = g_slice_new0 (MXFLocalTag);
3485   memcpy (&t->ul, MXF_UL (SOURCE_TRACK_ID), 16);
3486   t->size = 4;
3487   t->data = g_slice_alloc (t->size);
3488   t->g_slice = TRUE;
3489   GST_WRITE_UINT32_BE (t->data, self->source_track_id);
3490   mxf_primer_pack_add_mapping (primer, 0x1102, &t->ul);
3491   ret = g_list_prepend (ret, t);
3492 
3493   return ret;
3494 }
3495 
3496 static void
mxf_metadata_source_clip_init(MXFMetadataSourceClip * self)3497 mxf_metadata_source_clip_init (MXFMetadataSourceClip * self)
3498 {
3499 
3500 }
3501 
3502 static void
mxf_metadata_source_clip_class_init(MXFMetadataSourceClipClass * klass)3503 mxf_metadata_source_clip_class_init (MXFMetadataSourceClipClass * klass)
3504 {
3505   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3506   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3507 
3508   metadata_base_class->handle_tag = mxf_metadata_source_clip_handle_tag;
3509   metadata_base_class->resolve = mxf_metadata_source_clip_resolve;
3510   metadata_base_class->name_quark = MXF_QUARK (SOURCE_CLIP);
3511   metadata_base_class->to_structure = mxf_metadata_source_clip_to_structure;
3512   metadata_base_class->write_tags = mxf_metadata_source_clip_write_tags;
3513   metadata_class->type = 0x0111;
3514 }
3515 
3516 
3517 G_DEFINE_TYPE (MXFMetadataFiller, mxf_metadata_filler,
3518     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3519 
3520 static void
mxf_metadata_filler_init(MXFMetadataFiller * self)3521 mxf_metadata_filler_init (MXFMetadataFiller * self)
3522 {
3523 
3524 }
3525 
3526 static void
mxf_metadata_filler_class_init(MXFMetadataFillerClass * klass)3527 mxf_metadata_filler_class_init (MXFMetadataFillerClass * klass)
3528 {
3529   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3530   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3531 
3532   metadata_base_class->name_quark = MXF_QUARK (FILLER);
3533   metadata_class->type = 0x0109;
3534 }
3535 
3536 G_DEFINE_TYPE (MXFMetadataDMSourceClip, mxf_metadata_dm_source_clip,
3537     MXF_TYPE_METADATA_SOURCE_CLIP);
3538 
3539 static void
mxf_metadata_dm_source_clip_finalize(GObject * object)3540 mxf_metadata_dm_source_clip_finalize (GObject * object)
3541 {
3542   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (object);
3543 
3544   g_free (self->track_ids);
3545   self->track_ids = NULL;
3546 
3547   G_OBJECT_CLASS (mxf_metadata_dm_source_clip_parent_class)->finalize (object);
3548 }
3549 
3550 static gboolean
mxf_metadata_dm_source_clip_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3551 mxf_metadata_dm_source_clip_handle_tag (MXFMetadataBase * metadata,
3552     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3553     guint tag_size)
3554 {
3555   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (metadata);
3556   gboolean ret = TRUE;
3557 
3558   switch (tag) {
3559     case 0x6103:
3560     {
3561       guint32 len;
3562       guint i;
3563 
3564       if (tag_size < 8)
3565         goto error;
3566 
3567       len = GST_READ_UINT32_BE (tag_data);
3568       GST_DEBUG ("  number of track ids = %u", len);
3569       if (len == 0)
3570         return TRUE;
3571 
3572       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
3573         goto error;
3574 
3575       tag_data += 8;
3576       tag_size -= 8;
3577 
3578       if (tag_size / 4 < len)
3579         goto error;
3580 
3581       self->n_track_ids = len;
3582       self->track_ids = g_new0 (guint32, len);
3583 
3584       for (i = 0; i < len; i++) {
3585         self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
3586         GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
3587         tag_data += 4;
3588         tag_size -= 4;
3589       }
3590       break;
3591     }
3592     default:
3593       ret =
3594           MXF_METADATA_BASE_CLASS
3595           (mxf_metadata_dm_source_clip_parent_class)->handle_tag (metadata,
3596           primer, tag, tag_data, tag_size);
3597       break;
3598   }
3599 
3600   return ret;
3601 
3602 error:
3603 
3604   GST_ERROR ("Invalid DM source clip local tag 0x%04x of size %u", tag,
3605       tag_size);
3606 
3607   return FALSE;
3608 }
3609 
3610 static GstStructure *
mxf_metadata_dm_source_clip_to_structure(MXFMetadataBase * m)3611 mxf_metadata_dm_source_clip_to_structure (MXFMetadataBase * m)
3612 {
3613   GstStructure *ret =
3614       MXF_METADATA_BASE_CLASS
3615       (mxf_metadata_dm_source_clip_parent_class)->to_structure (m);
3616   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (m);
3617   guint i;
3618 
3619   if (self->n_track_ids > 0) {
3620     GValue arr = { 0, }
3621     , val = {
3622     0,};
3623 
3624     g_value_init (&arr, GST_TYPE_ARRAY);
3625 
3626     for (i = 0; i < self->n_track_ids; i++) {
3627       g_value_init (&val, G_TYPE_UINT);
3628 
3629       g_value_set_uint (&val, self->track_ids[i]);
3630       gst_value_array_append_value (&arr, &val);
3631       g_value_unset (&val);
3632     }
3633 
3634     if (gst_value_array_get_size (&arr) > 0)
3635       gst_structure_id_set_value (ret, MXF_QUARK (TRACK_IDS), &arr);
3636 
3637     g_value_unset (&arr);
3638   }
3639 
3640   return ret;
3641 }
3642 
3643 static GList *
mxf_metadata_dm_source_clip_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3644 mxf_metadata_dm_source_clip_write_tags (MXFMetadataBase * m,
3645     MXFPrimerPack * primer)
3646 {
3647   MXFMetadataDMSourceClip *self = MXF_METADATA_DM_SOURCE_CLIP (m);
3648   GList *ret =
3649       MXF_METADATA_BASE_CLASS
3650       (mxf_metadata_dm_source_clip_parent_class)->write_tags (m, primer);
3651   MXFLocalTag *t;
3652 
3653   if (self->track_ids) {
3654     guint i;
3655 
3656     t = g_slice_new0 (MXFLocalTag);
3657     memcpy (&t->ul, MXF_UL (DM_SOURCECLIP_TRACK_IDS), 16);
3658     t->size = 8 + 4 * self->n_track_ids;
3659     t->data = g_slice_alloc (t->size);
3660     t->g_slice = TRUE;
3661     GST_WRITE_UINT32_BE (t->data, self->n_track_ids);
3662     GST_WRITE_UINT32_BE (t->data + 4, 4);
3663     for (i = 0; i < self->n_track_ids; i++)
3664       GST_WRITE_UINT32_BE (t->data + 8 + i * 4, self->track_ids[i]);
3665     mxf_primer_pack_add_mapping (primer, 0x6103, &t->ul);
3666     ret = g_list_prepend (ret, t);
3667   }
3668 
3669   return ret;
3670 }
3671 
3672 static void
mxf_metadata_dm_source_clip_init(MXFMetadataDMSourceClip * self)3673 mxf_metadata_dm_source_clip_init (MXFMetadataDMSourceClip * self)
3674 {
3675 
3676 }
3677 
3678 static void
mxf_metadata_dm_source_clip_class_init(MXFMetadataDMSourceClipClass * klass)3679 mxf_metadata_dm_source_clip_class_init (MXFMetadataDMSourceClipClass * klass)
3680 {
3681   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3682   GObjectClass *object_class = (GObjectClass *) klass;
3683   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3684 
3685   object_class->finalize = mxf_metadata_dm_source_clip_finalize;
3686   metadata_base_class->handle_tag = mxf_metadata_dm_source_clip_handle_tag;
3687   metadata_base_class->name_quark = MXF_QUARK (DM_SOURCE_CLIP);
3688   metadata_base_class->to_structure = mxf_metadata_dm_source_clip_to_structure;
3689   metadata_base_class->write_tags = mxf_metadata_dm_source_clip_write_tags;
3690   metadata_class->type = 0x0145;
3691 }
3692 
3693 G_DEFINE_TYPE (MXFMetadataDMSegment, mxf_metadata_dm_segment,
3694     MXF_TYPE_METADATA_STRUCTURAL_COMPONENT);
3695 
3696 static void
mxf_metadata_dm_segment_finalize(GObject * object)3697 mxf_metadata_dm_segment_finalize (GObject * object)
3698 {
3699   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (object);
3700 
3701   g_free (self->track_ids);
3702   self->track_ids = NULL;
3703 
3704   g_free (self->event_comment);
3705   self->event_comment = NULL;
3706 
3707   G_OBJECT_CLASS (mxf_metadata_dm_segment_parent_class)->finalize (object);
3708 }
3709 
3710 static gboolean
mxf_metadata_dm_segment_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3711 mxf_metadata_dm_segment_handle_tag (MXFMetadataBase * metadata,
3712     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3713     guint tag_size)
3714 {
3715   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (metadata);
3716   gboolean ret = TRUE;
3717 #ifndef GST_DISABLE_GST_DEBUG
3718   gchar str[48];
3719 #endif
3720 
3721   switch (tag) {
3722     case 0x0601:
3723       if (tag_size != 8)
3724         goto error;
3725       self->event_start_position = GST_READ_UINT64_BE (tag_data);
3726       GST_DEBUG ("  event start position = %" G_GINT64_FORMAT,
3727           self->event_start_position);
3728       break;
3729     case 0x0602:
3730       self->event_comment = mxf_utf16_to_utf8 (tag_data, tag_size);
3731       GST_DEBUG ("  event comment = %s", GST_STR_NULL (self->event_comment));
3732       break;
3733     case 0x6102:
3734     {
3735       guint32 len;
3736       guint i;
3737 
3738       if (tag_size < 8)
3739         goto error;
3740       len = GST_READ_UINT32_BE (tag_data);
3741       GST_DEBUG ("  number of track ids = %u", len);
3742       if (len == 0)
3743         return TRUE;
3744 
3745       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
3746         goto error;
3747 
3748       tag_data += 8;
3749       tag_size -= 8;
3750 
3751       if (len < tag_size / 4)
3752         goto error;
3753 
3754       self->n_track_ids = len;
3755       self->track_ids = g_new0 (guint32, len);
3756 
3757       tag_data += 8;
3758       tag_size -= 8;
3759 
3760       for (i = 0; i < len; i++) {
3761         self->track_ids[i] = GST_READ_UINT32_BE (tag_data);
3762         GST_DEBUG ("    track id %u = %u", i, self->track_ids[i]);
3763         tag_data += 4;
3764         tag_size -= 4;
3765       }
3766       break;
3767     }
3768     case 0x6101:
3769       if (tag_size != 16)
3770         goto error;
3771 
3772       memcpy (&self->dm_framework_uid, tag_data, 16);
3773       GST_DEBUG ("  DM framework = %s",
3774           mxf_uuid_to_string (&self->dm_framework_uid, str));
3775       break;
3776     default:
3777       ret =
3778           MXF_METADATA_BASE_CLASS
3779           (mxf_metadata_dm_segment_parent_class)->handle_tag (metadata, primer,
3780           tag, tag_data, tag_size);
3781       break;
3782   }
3783 
3784   return ret;
3785 
3786 error:
3787 
3788   GST_ERROR ("Invalid DM segment local tag 0x%04x of size %u", tag, tag_size);
3789 
3790   return FALSE;
3791 }
3792 
3793 static gboolean
mxf_metadata_dm_segment_resolve(MXFMetadataBase * m,GHashTable * metadata)3794 mxf_metadata_dm_segment_resolve (MXFMetadataBase * m, GHashTable * metadata)
3795 {
3796   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3797   MXFMetadataBase *current = NULL;
3798 #ifndef GST_DISABLE_GST_DEBUG
3799   gchar str[48];
3800 #endif
3801 
3802   current = g_hash_table_lookup (metadata, &self->dm_framework_uid);
3803   if (current && MXF_IS_DESCRIPTIVE_METADATA_FRAMEWORK (current)) {
3804     if (mxf_metadata_base_resolve (current, metadata)) {
3805       self->dm_framework = MXF_DESCRIPTIVE_METADATA_FRAMEWORK (current);
3806     } else {
3807       GST_ERROR ("Couldn't resolve DM framework %s",
3808           mxf_uuid_to_string (&self->dm_framework_uid, str));
3809       return FALSE;
3810     }
3811   } else {
3812     GST_ERROR ("Couldn't find DM framework %s",
3813         mxf_uuid_to_string (&self->dm_framework_uid, str));
3814     return FALSE;
3815   }
3816 
3817 
3818   return
3819       MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->resolve
3820       (m, metadata);
3821 }
3822 
3823 static GstStructure *
mxf_metadata_dm_segment_to_structure(MXFMetadataBase * m)3824 mxf_metadata_dm_segment_to_structure (MXFMetadataBase * m)
3825 {
3826   GstStructure *ret =
3827       MXF_METADATA_BASE_CLASS
3828       (mxf_metadata_dm_segment_parent_class)->to_structure (m);
3829   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3830   guint i;
3831 
3832   gst_structure_id_set (ret, MXF_QUARK (EVENT_START_POSITION), G_TYPE_INT64,
3833       self->event_start_position, NULL);
3834 
3835   if (self->event_comment)
3836     gst_structure_id_set (ret, MXF_QUARK (EVENT_COMMENT), G_TYPE_STRING,
3837         self->event_comment, NULL);
3838   /* FIXME: DMS1 doesn't support serializing to a structure yet */
3839 #if 0
3840   if (self->dm_framework) {
3841     GstStructure *s =
3842         mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->dm_framework));
3843 
3844     gst_structure_id_set (ret, MXF_QUARK (DM_FRAMEWORK), GST_TYPE_STRUCTURE,
3845         s, NULL);
3846     gst_structure_free (s);
3847   }
3848 #endif
3849 
3850   if (self->n_track_ids > 0) {
3851     GValue arr = { 0, }
3852     , val = {
3853     0,};
3854 
3855     g_value_init (&arr, GST_TYPE_ARRAY);
3856 
3857     for (i = 0; i < self->n_track_ids; i++) {
3858       g_value_init (&val, G_TYPE_UINT);
3859 
3860       g_value_set_uint (&val, self->track_ids[i]);
3861       gst_value_array_append_value (&arr, &val);
3862       g_value_unset (&val);
3863     }
3864 
3865     if (gst_value_array_get_size (&arr) > 0)
3866       gst_structure_id_set_value (ret, MXF_QUARK (TRACK_IDS), &arr);
3867 
3868     g_value_unset (&arr);
3869   }
3870 
3871   return ret;
3872 }
3873 
3874 static GList *
mxf_metadata_dm_segment_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)3875 mxf_metadata_dm_segment_write_tags (MXFMetadataBase * m, MXFPrimerPack * primer)
3876 {
3877   MXFMetadataDMSegment *self = MXF_METADATA_DM_SEGMENT (m);
3878   GList *ret =
3879       MXF_METADATA_BASE_CLASS (mxf_metadata_dm_segment_parent_class)->write_tags
3880       (m, primer);
3881   MXFLocalTag *t;
3882 
3883   if (self->event_start_position != -1) {
3884     t = g_slice_new0 (MXFLocalTag);
3885     memcpy (&t->ul, MXF_UL (EVENT_START_POSITION), 16);
3886     t->size = 8;
3887     t->data = g_slice_alloc (t->size);
3888     t->g_slice = TRUE;
3889     GST_WRITE_UINT64_BE (t->data, self->event_start_position);
3890     mxf_primer_pack_add_mapping (primer, 0x0601, &t->ul);
3891     ret = g_list_prepend (ret, t);
3892   }
3893 
3894   if (self->event_comment) {
3895     t = g_slice_new0 (MXFLocalTag);
3896     memcpy (&t->ul, MXF_UL (EVENT_COMMENT), 16);
3897     t->data = mxf_utf8_to_utf16 (self->event_comment, &t->size);
3898     mxf_primer_pack_add_mapping (primer, 0x0602, &t->ul);
3899     ret = g_list_prepend (ret, t);
3900   }
3901 
3902   if (self->track_ids) {
3903     guint i;
3904 
3905     t = g_slice_new0 (MXFLocalTag);
3906     memcpy (&t->ul, MXF_UL (DM_SEGMENT_TRACK_IDS), 16);
3907     t->size = 8 + 4 * self->n_track_ids;
3908     t->data = g_slice_alloc (t->size);
3909     t->g_slice = TRUE;
3910     GST_WRITE_UINT32_BE (t->data, self->n_track_ids);
3911     GST_WRITE_UINT32_BE (t->data + 4, 4);
3912     for (i = 0; i < self->n_track_ids; i++)
3913       GST_WRITE_UINT32_BE (t->data + 8 + i * 4, self->track_ids[i]);
3914     mxf_primer_pack_add_mapping (primer, 0x6102, &t->ul);
3915     ret = g_list_prepend (ret, t);
3916   }
3917 
3918   if (self->dm_framework) {
3919     t = g_slice_new0 (MXFLocalTag);
3920     memcpy (&t->ul, MXF_UL (DM_FRAMEWORK), 16);
3921     t->size = 16;
3922     t->data = g_slice_alloc (t->size);
3923     t->g_slice = TRUE;
3924     memcpy (t->data, &MXF_METADATA_BASE (self->dm_framework)->instance_uid, 16);
3925     mxf_primer_pack_add_mapping (primer, 0x6101, &t->ul);
3926     ret = g_list_prepend (ret, t);
3927   }
3928 
3929   return ret;
3930 }
3931 
3932 static void
mxf_metadata_dm_segment_init(MXFMetadataDMSegment * self)3933 mxf_metadata_dm_segment_init (MXFMetadataDMSegment * self)
3934 {
3935   self->event_start_position = -1;
3936 }
3937 
3938 static void
mxf_metadata_dm_segment_class_init(MXFMetadataDMSegmentClass * klass)3939 mxf_metadata_dm_segment_class_init (MXFMetadataDMSegmentClass * klass)
3940 {
3941   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
3942   GObjectClass *object_class = (GObjectClass *) klass;
3943   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
3944 
3945   object_class->finalize = mxf_metadata_dm_segment_finalize;
3946   metadata_base_class->handle_tag = mxf_metadata_dm_segment_handle_tag;
3947   metadata_base_class->resolve = mxf_metadata_dm_segment_resolve;
3948   metadata_base_class->name_quark = MXF_QUARK (DM_SEGMENT);
3949   metadata_base_class->to_structure = mxf_metadata_dm_segment_to_structure;
3950   metadata_base_class->write_tags = mxf_metadata_dm_segment_write_tags;
3951   metadata_class->type = 0x0141;
3952 }
3953 
3954 G_DEFINE_ABSTRACT_TYPE (MXFMetadataGenericDescriptor,
3955     mxf_metadata_generic_descriptor, MXF_TYPE_METADATA);
3956 
3957 static void
mxf_metadata_generic_descriptor_finalize(GObject * object)3958 mxf_metadata_generic_descriptor_finalize (GObject * object)
3959 {
3960   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (object);
3961 
3962   g_free (self->locators_uids);
3963   self->locators_uids = NULL;
3964 
3965   g_free (self->locators);
3966   self->locators = NULL;
3967 
3968   G_OBJECT_CLASS (mxf_metadata_generic_descriptor_parent_class)->finalize
3969       (object);
3970 }
3971 
3972 static gboolean
mxf_metadata_generic_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)3973 mxf_metadata_generic_descriptor_handle_tag (MXFMetadataBase * metadata,
3974     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
3975     guint tag_size)
3976 {
3977   MXFMetadataGenericDescriptor *self =
3978       MXF_METADATA_GENERIC_DESCRIPTOR (metadata);
3979   gboolean ret = TRUE;
3980 #ifndef GST_DISABLE_GST_DEBUG
3981   gchar str[48];
3982 #endif
3983 
3984   switch (tag) {
3985     case 0x2f01:
3986       if (!mxf_uuid_array_parse (&self->locators_uids, &self->n_locators,
3987               tag_data, tag_size))
3988         goto error;
3989 
3990       GST_DEBUG ("  number of locators = %u", self->n_locators);
3991 #ifndef GST_DISABLE_GST_DEBUG
3992       {
3993         guint i;
3994         for (i = 0; i < self->n_locators; i++) {
3995           GST_DEBUG ("  locator %u = %s", i,
3996               mxf_uuid_to_string (&self->locators_uids[i], str));
3997         }
3998       }
3999 #endif
4000       break;
4001     default:
4002       ret =
4003           MXF_METADATA_BASE_CLASS
4004           (mxf_metadata_generic_descriptor_parent_class)->handle_tag (metadata,
4005           primer, tag, tag_data, tag_size);
4006       break;
4007   }
4008 
4009   return ret;
4010 
4011 error:
4012 
4013   GST_ERROR ("Invalid generic descriptor local tag 0x%04x of size %u", tag,
4014       tag_size);
4015 
4016   return FALSE;
4017 }
4018 
4019 static gboolean
mxf_metadata_generic_descriptor_resolve(MXFMetadataBase * m,GHashTable * metadata)4020 mxf_metadata_generic_descriptor_resolve (MXFMetadataBase * m,
4021     GHashTable * metadata)
4022 {
4023   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
4024   MXFMetadataBase *current = NULL;
4025   guint i;
4026   gboolean have_locator = FALSE;
4027 #ifndef GST_DISABLE_GST_DEBUG
4028   gchar str[48];
4029 #endif
4030 
4031   if (self->locators)
4032     memset (self->locators, 0, sizeof (gpointer) * self->n_locators);
4033   else
4034     self->locators = g_new0 (MXFMetadataLocator *, self->n_locators);
4035   for (i = 0; i < self->n_locators; i++) {
4036     current = g_hash_table_lookup (metadata, &self->locators_uids[i]);
4037     if (current && MXF_IS_METADATA_LOCATOR (current)) {
4038       if (mxf_metadata_base_resolve (current, metadata)) {
4039         self->locators[i] = MXF_METADATA_LOCATOR (current);
4040         have_locator = TRUE;
4041       } else {
4042         GST_ERROR ("Couldn't resolve locator %s",
4043             mxf_uuid_to_string (&self->locators_uids[i], str));
4044       }
4045     } else {
4046       GST_ERROR ("Locator %s not found",
4047           mxf_uuid_to_string (&self->locators_uids[i], str));
4048     }
4049   }
4050 
4051   if (!have_locator && self->n_locators > 0) {
4052     GST_ERROR ("Couldn't resolve a locator");
4053     return FALSE;
4054   }
4055 
4056   return
4057       MXF_METADATA_BASE_CLASS
4058       (mxf_metadata_generic_descriptor_parent_class)->resolve (m, metadata);
4059 }
4060 
4061 static GstStructure *
mxf_metadata_generic_descriptor_to_structure(MXFMetadataBase * m)4062 mxf_metadata_generic_descriptor_to_structure (MXFMetadataBase * m)
4063 {
4064   GstStructure *ret =
4065       MXF_METADATA_BASE_CLASS
4066       (mxf_metadata_generic_descriptor_parent_class)->to_structure (m);
4067   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
4068   guint i;
4069 
4070   if (self->n_locators > 0) {
4071     GValue arr = { 0, }
4072     , val = {
4073     0,};
4074 
4075     g_value_init (&arr, GST_TYPE_ARRAY);
4076 
4077     for (i = 0; i < self->n_locators; i++) {
4078       GstStructure *s;
4079 
4080       if (self->locators[i] == NULL)
4081         continue;
4082 
4083       g_value_init (&val, GST_TYPE_STRUCTURE);
4084 
4085       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE (self->locators
4086               [i]));
4087       gst_value_set_structure (&val, s);
4088       gst_structure_free (s);
4089       gst_value_array_append_value (&arr, &val);
4090       g_value_unset (&val);
4091     }
4092 
4093     if (gst_value_array_get_size (&arr) > 0)
4094       gst_structure_id_set_value (ret, MXF_QUARK (LOCATORS), &arr);
4095 
4096     g_value_unset (&arr);
4097   }
4098 
4099   return ret;
4100 }
4101 
4102 static GList *
mxf_metadata_generic_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)4103 mxf_metadata_generic_descriptor_write_tags (MXFMetadataBase * m,
4104     MXFPrimerPack * primer)
4105 {
4106   MXFMetadataGenericDescriptor *self = MXF_METADATA_GENERIC_DESCRIPTOR (m);
4107   GList *ret =
4108       MXF_METADATA_BASE_CLASS
4109       (mxf_metadata_generic_descriptor_parent_class)->write_tags (m, primer);
4110   MXFLocalTag *t;
4111 
4112   if (self->locators) {
4113     guint i;
4114 
4115     t = g_slice_new0 (MXFLocalTag);
4116     memcpy (&t->ul, MXF_UL (LOCATORS), 16);
4117     t->size = 8 + 16 * self->n_locators;
4118     t->data = g_slice_alloc0 (t->size);
4119     t->g_slice = TRUE;
4120     GST_WRITE_UINT32_BE (t->data, self->n_locators);
4121     GST_WRITE_UINT32_BE (t->data + 4, 16);
4122     for (i = 0; i < self->n_locators; i++) {
4123       if (!self->locators[i])
4124         continue;
4125       memcpy (t->data + 8 + 16 * i,
4126           &MXF_METADATA_BASE (self->locators[i])->instance_uid, 16);
4127     }
4128     mxf_primer_pack_add_mapping (primer, 0x2f01, &t->ul);
4129     ret = g_list_prepend (ret, t);
4130   }
4131 
4132   return ret;
4133 }
4134 
4135 static void
mxf_metadata_generic_descriptor_init(MXFMetadataGenericDescriptor * self)4136 mxf_metadata_generic_descriptor_init (MXFMetadataGenericDescriptor * self)
4137 {
4138 
4139 }
4140 
4141 static void
mxf_metadata_generic_descriptor_class_init(MXFMetadataGenericDescriptorClass * klass)4142 mxf_metadata_generic_descriptor_class_init (MXFMetadataGenericDescriptorClass *
4143     klass)
4144 {
4145   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4146   GObjectClass *object_class = (GObjectClass *) klass;
4147 
4148   object_class->finalize = mxf_metadata_generic_descriptor_finalize;
4149   metadata_base_class->handle_tag = mxf_metadata_generic_descriptor_handle_tag;
4150   metadata_base_class->resolve = mxf_metadata_generic_descriptor_resolve;
4151   metadata_base_class->to_structure =
4152       mxf_metadata_generic_descriptor_to_structure;
4153   metadata_base_class->write_tags = mxf_metadata_generic_descriptor_write_tags;
4154 }
4155 
4156 G_DEFINE_TYPE (MXFMetadataFileDescriptor, mxf_metadata_file_descriptor,
4157     MXF_TYPE_METADATA_GENERIC_DESCRIPTOR);
4158 
4159 static gboolean
mxf_metadata_file_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)4160 mxf_metadata_file_descriptor_handle_tag (MXFMetadataBase * metadata,
4161     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4162     guint tag_size)
4163 {
4164   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (metadata);
4165   gboolean ret = TRUE;
4166 #ifndef GST_DISABLE_GST_DEBUG
4167   gchar str[48];
4168 #endif
4169 
4170   switch (tag) {
4171     case 0x3006:
4172       if (tag_size != 4)
4173         goto error;
4174       self->linked_track_id = GST_READ_UINT32_BE (tag_data);
4175       GST_DEBUG ("  linked track id = %u", self->linked_track_id);
4176       break;
4177     case 0x3001:
4178       if (!mxf_fraction_parse (&self->sample_rate, tag_data, tag_size))
4179         goto error;
4180       GST_DEBUG ("  sample rate = %d/%d", self->sample_rate.n,
4181           self->sample_rate.d);
4182       break;
4183     case 0x3002:
4184       if (tag_size != 8)
4185         goto error;
4186       self->container_duration = GST_READ_UINT64_BE (tag_data);
4187       GST_DEBUG ("  container duration = %" G_GINT64_FORMAT,
4188           self->container_duration);
4189       break;
4190     case 0x3004:
4191       if (tag_size != 16)
4192         goto error;
4193       memcpy (&self->essence_container, tag_data, 16);
4194       GST_DEBUG ("  essence container = %s",
4195           mxf_ul_to_string (&self->essence_container, str));
4196       break;
4197     case 0x3005:
4198       if (tag_size != 16)
4199         goto error;
4200       memcpy (&self->codec, tag_data, 16);
4201       GST_DEBUG ("  codec = %s", mxf_ul_to_string (&self->codec, str));
4202       break;
4203     default:
4204       ret =
4205           MXF_METADATA_BASE_CLASS
4206           (mxf_metadata_file_descriptor_parent_class)->handle_tag (metadata,
4207           primer, tag, tag_data, tag_size);
4208       break;
4209   }
4210 
4211   return ret;
4212 
4213 error:
4214 
4215   GST_ERROR ("Invalid file descriptor local tag 0x%04x of size %u", tag,
4216       tag_size);
4217 
4218   return FALSE;
4219 }
4220 
4221 static GstStructure *
mxf_metadata_file_descriptor_to_structure(MXFMetadataBase * m)4222 mxf_metadata_file_descriptor_to_structure (MXFMetadataBase * m)
4223 {
4224   GstStructure *ret =
4225       MXF_METADATA_BASE_CLASS
4226       (mxf_metadata_file_descriptor_parent_class)->to_structure (m);
4227   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (m);
4228   gchar str[48];
4229 
4230   if (self->linked_track_id)
4231     gst_structure_id_set (ret, MXF_QUARK (LINKED_TRACK_ID), G_TYPE_UINT,
4232         self->linked_track_id, NULL);
4233 
4234   if (self->sample_rate.n && self->sample_rate.d)
4235     gst_structure_id_set (ret, MXF_QUARK (SAMPLE_RATE), GST_TYPE_FRACTION,
4236         self->sample_rate.n, self->sample_rate.d, NULL);
4237 
4238   if (self->container_duration)
4239     gst_structure_id_set (ret, MXF_QUARK (CONTAINER_DURATION), G_TYPE_INT64,
4240         self->container_duration, NULL);
4241 
4242   mxf_ul_to_string (&self->essence_container, str);
4243   gst_structure_id_set (ret, MXF_QUARK (ESSENCE_CONTAINER), G_TYPE_STRING, str,
4244       NULL);
4245 
4246   if (!mxf_ul_is_zero (&self->codec)) {
4247     mxf_ul_to_string (&self->codec, str);
4248     gst_structure_id_set (ret, MXF_QUARK (CODEC), G_TYPE_STRING, str, NULL);
4249   }
4250 
4251   return ret;
4252 }
4253 
4254 static GList *
mxf_metadata_file_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)4255 mxf_metadata_file_descriptor_write_tags (MXFMetadataBase * m,
4256     MXFPrimerPack * primer)
4257 {
4258   MXFMetadataFileDescriptor *self = MXF_METADATA_FILE_DESCRIPTOR (m);
4259   GList *ret =
4260       MXF_METADATA_BASE_CLASS
4261       (mxf_metadata_file_descriptor_parent_class)->write_tags (m, primer);
4262   MXFLocalTag *t;
4263 
4264   if (self->linked_track_id) {
4265     t = g_slice_new0 (MXFLocalTag);
4266     memcpy (&t->ul, MXF_UL (LINKED_TRACK_ID), 16);
4267     t->size = 4;
4268     t->data = g_slice_alloc (t->size);
4269     t->g_slice = TRUE;
4270     GST_WRITE_UINT32_BE (t->data, self->linked_track_id);
4271     mxf_primer_pack_add_mapping (primer, 0x3006, &t->ul);
4272     ret = g_list_prepend (ret, t);
4273   }
4274 
4275   t = g_slice_new0 (MXFLocalTag);
4276   memcpy (&t->ul, MXF_UL (SAMPLE_RATE), 16);
4277   t->size = 8;
4278   t->data = g_slice_alloc (t->size);
4279   t->g_slice = TRUE;
4280   GST_WRITE_UINT32_BE (t->data, self->sample_rate.n);
4281   GST_WRITE_UINT32_BE (t->data + 4, self->sample_rate.d);
4282   mxf_primer_pack_add_mapping (primer, 0x3001, &t->ul);
4283   ret = g_list_prepend (ret, t);
4284 
4285   if (self->container_duration > 0) {
4286     t = g_slice_new0 (MXFLocalTag);
4287     memcpy (&t->ul, MXF_UL (CONTAINER_DURATION), 16);
4288     t->size = 8;
4289     t->data = g_slice_alloc (t->size);
4290     t->g_slice = TRUE;
4291     GST_WRITE_UINT64_BE (t->data, self->container_duration);
4292     mxf_primer_pack_add_mapping (primer, 0x3002, &t->ul);
4293     ret = g_list_prepend (ret, t);
4294   }
4295 
4296   t = g_slice_new0 (MXFLocalTag);
4297   memcpy (&t->ul, MXF_UL (ESSENCE_CONTAINER), 16);
4298   t->size = 16;
4299   t->data = g_slice_alloc (t->size);
4300   t->g_slice = TRUE;
4301   memcpy (t->data, &self->essence_container, 16);
4302   mxf_primer_pack_add_mapping (primer, 0x3004, &t->ul);
4303   ret = g_list_prepend (ret, t);
4304 
4305   if (!mxf_ul_is_zero (&self->codec)) {
4306     t = g_slice_new0 (MXFLocalTag);
4307     memcpy (&t->ul, MXF_UL (CODEC), 16);
4308     t->size = 16;
4309     t->data = g_slice_alloc (t->size);
4310     t->g_slice = TRUE;
4311     memcpy (t->data, &self->codec, 16);
4312     mxf_primer_pack_add_mapping (primer, 0x3005, &t->ul);
4313     ret = g_list_prepend (ret, t);
4314   }
4315 
4316   return ret;
4317 }
4318 
4319 static void
mxf_metadata_file_descriptor_init(MXFMetadataFileDescriptor * self)4320 mxf_metadata_file_descriptor_init (MXFMetadataFileDescriptor * self)
4321 {
4322 
4323 }
4324 
4325 static void
mxf_metadata_file_descriptor_class_init(MXFMetadataFileDescriptorClass * klass)4326 mxf_metadata_file_descriptor_class_init (MXFMetadataFileDescriptorClass * klass)
4327 {
4328   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4329   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
4330 
4331   metadata_base_class->handle_tag = mxf_metadata_file_descriptor_handle_tag;
4332   metadata_base_class->name_quark = MXF_QUARK (FILE_DESCRIPTOR);
4333   metadata_base_class->to_structure = mxf_metadata_file_descriptor_to_structure;
4334   metadata_base_class->write_tags = mxf_metadata_file_descriptor_write_tags;
4335   metadata_class->type = 0x0125;
4336 }
4337 
4338 G_DEFINE_TYPE (MXFMetadataGenericPictureEssenceDescriptor,
4339     mxf_metadata_generic_picture_essence_descriptor,
4340     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
4341 
4342 static gboolean
mxf_metadata_generic_picture_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)4343 mxf_metadata_generic_picture_essence_descriptor_handle_tag (MXFMetadataBase *
4344     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
4345     guint tag_size)
4346 {
4347   MXFMetadataGenericPictureEssenceDescriptor *self =
4348       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (metadata);
4349   gboolean ret = TRUE;
4350 #ifndef GST_DISABLE_GST_DEBUG
4351   gchar str[48];
4352 #endif
4353 
4354   switch (tag) {
4355     case 0x3215:
4356       if (tag_size != 1)
4357         goto error;
4358       self->signal_standard = GST_READ_UINT8 (tag_data);
4359       GST_DEBUG ("  signal standard = %u", self->signal_standard);
4360       break;
4361     case 0x320c:
4362       if (tag_size != 1)
4363         goto error;
4364       self->frame_layout = GST_READ_UINT8 (tag_data);
4365       GST_DEBUG ("  frame layout = %u", self->frame_layout);
4366       break;
4367     case 0x3203:
4368       if (tag_size != 4)
4369         goto error;
4370       self->stored_width = GST_READ_UINT32_BE (tag_data);
4371       GST_DEBUG ("  stored width = %u", self->stored_width);
4372       break;
4373     case 0x3202:
4374       if (tag_size != 4)
4375         goto error;
4376       self->stored_height = GST_READ_UINT32_BE (tag_data);
4377       GST_DEBUG ("  stored height = %u", self->stored_height);
4378       break;
4379     case 0x3216:
4380       if (tag_size != 4)
4381         goto error;
4382       self->stored_f2_offset = GST_READ_UINT32_BE (tag_data);
4383       GST_DEBUG ("  stored f2 offset = %d", self->stored_f2_offset);
4384       break;
4385     case 0x3205:
4386       if (tag_size != 4)
4387         goto error;
4388       self->sampled_width = GST_READ_UINT32_BE (tag_data);
4389       GST_DEBUG ("  sampled width = %u", self->sampled_width);
4390       break;
4391     case 0x3204:
4392       if (tag_size != 4)
4393         goto error;
4394       self->sampled_height = GST_READ_UINT32_BE (tag_data);
4395       GST_DEBUG ("  sampled height = %u", self->sampled_height);
4396       break;
4397     case 0x3206:
4398       if (tag_size != 4)
4399         goto error;
4400       self->sampled_x_offset = GST_READ_UINT32_BE (tag_data);
4401       GST_DEBUG ("  sampled x offset = %d", self->sampled_x_offset);
4402       break;
4403     case 0x3207:
4404       if (tag_size != 4)
4405         goto error;
4406       self->sampled_y_offset = GST_READ_UINT32_BE (tag_data);
4407       GST_DEBUG ("  sampled y offset = %d", self->sampled_y_offset);
4408       break;
4409     case 0x3208:
4410       if (tag_size != 4)
4411         goto error;
4412       self->display_height = GST_READ_UINT32_BE (tag_data);
4413       GST_DEBUG ("  display height = %u", self->display_height);
4414       break;
4415     case 0x3209:
4416       if (tag_size != 4)
4417         goto error;
4418       self->display_width = GST_READ_UINT32_BE (tag_data);
4419       GST_DEBUG ("  display width = %u", self->display_width);
4420       break;
4421     case 0x320a:
4422       if (tag_size != 4)
4423         goto error;
4424       self->display_x_offset = GST_READ_UINT32_BE (tag_data);
4425       GST_DEBUG ("  display x offset = %d", self->display_x_offset);
4426       break;
4427     case 0x320b:
4428       if (tag_size != 4)
4429         goto error;
4430       self->display_y_offset = GST_READ_UINT32_BE (tag_data);
4431       GST_DEBUG ("  display y offset = %d", self->display_y_offset);
4432       break;
4433     case 0x3217:
4434       if (tag_size != 4)
4435         goto error;
4436       self->display_f2_offset = GST_READ_UINT32_BE (tag_data);
4437       GST_DEBUG ("  display f2 offset = %d", self->display_f2_offset);
4438       break;
4439     case 0x320e:
4440       if (!mxf_fraction_parse (&self->aspect_ratio, tag_data, tag_size))
4441         goto error;
4442       GST_DEBUG ("  aspect ratio = %d/%d", self->aspect_ratio.n,
4443           self->aspect_ratio.d);
4444       break;
4445     case 0x3218:
4446       if (tag_size != 1)
4447         goto error;
4448       self->active_format_descriptor = GST_READ_UINT8 (tag_data);
4449       GST_DEBUG ("  active format descriptor = %u",
4450           self->active_format_descriptor);
4451       break;
4452     case 0x320d:
4453       if (tag_size < 8)
4454         goto error;
4455 
4456       if (GST_READ_UINT32_BE (tag_data) == 0)
4457         return TRUE;
4458 
4459       if (GST_READ_UINT32_BE (tag_data + 4) != 4)
4460         goto error;
4461 
4462       if (GST_READ_UINT32_BE (tag_data) != 1 &&
4463           GST_READ_UINT32_BE (tag_data) != 2)
4464         goto error;
4465 
4466       if ((GST_READ_UINT32_BE (tag_data) == 1 && tag_size != 12) ||
4467           (GST_READ_UINT32_BE (tag_data) == 2 && tag_size != 16))
4468         goto error;
4469 
4470       self->video_line_map[0] = GST_READ_UINT32_BE (tag_data + 8);
4471 
4472       /* Workaround for files created by ffmpeg */
4473       if (GST_READ_UINT32_BE (tag_data) == 1)
4474         self->video_line_map[0] = 0;
4475       else
4476         self->video_line_map[1] = GST_READ_UINT32_BE (tag_data + 12);
4477 
4478       GST_DEBUG ("  video line map = {%i, %i}", self->video_line_map[0],
4479           self->video_line_map[1]);
4480       break;
4481     case 0x320f:
4482       if (tag_size != 1)
4483         goto error;
4484       self->alpha_transparency = GST_READ_UINT8 (tag_data);
4485       GST_DEBUG ("  alpha transparency = %u", self->alpha_transparency);
4486       break;
4487     case 0x3210:
4488       if (tag_size != 16)
4489         goto error;
4490       memcpy (&self->capture_gamma, tag_data, 16);
4491       GST_DEBUG ("  capture gamma = %s",
4492           mxf_ul_to_string (&self->capture_gamma, str));
4493       break;
4494     case 0x3211:
4495       if (tag_size != 4)
4496         goto error;
4497       self->image_alignment_offset = GST_READ_UINT32_BE (tag_data);
4498       GST_DEBUG ("  image alignment offset = %u", self->image_alignment_offset);
4499       break;
4500     case 0x3213:
4501       if (tag_size != 4)
4502         goto error;
4503       self->image_start_offset = GST_READ_UINT32_BE (tag_data);
4504       GST_DEBUG ("  image start offset = %u", self->image_start_offset);
4505       break;
4506     case 0x3214:
4507       if (tag_size != 4)
4508         goto error;
4509       self->image_end_offset = GST_READ_UINT32_BE (tag_data);
4510       GST_DEBUG ("  image end offset = %u", self->image_end_offset);
4511       break;
4512     case 0x3212:
4513       if (tag_size != 1)
4514         goto error;
4515       self->field_dominance = GST_READ_UINT8 (tag_data);
4516       GST_DEBUG ("  field dominance = %u", self->field_dominance);
4517       break;
4518     case 0x3201:
4519       if (tag_size != 16)
4520         goto error;
4521       memcpy (&self->picture_essence_coding, tag_data, 16);
4522       GST_DEBUG ("  picture essence coding = %s",
4523           mxf_ul_to_string (&self->picture_essence_coding, str));
4524       break;
4525     default:
4526       ret =
4527           MXF_METADATA_BASE_CLASS
4528           (mxf_metadata_generic_picture_essence_descriptor_parent_class)->handle_tag
4529           (metadata, primer, tag, tag_data, tag_size);
4530       break;
4531   }
4532 
4533   return ret;
4534 
4535 error:
4536 
4537   GST_ERROR
4538       ("Invalid generic picture essence descriptor local tag 0x%04x of size %u",
4539       tag, tag_size);
4540 
4541   return FALSE;
4542 }
4543 
4544 static GstStructure *
mxf_metadata_generic_picture_essence_descriptor_to_structure(MXFMetadataBase * m)4545 mxf_metadata_generic_picture_essence_descriptor_to_structure (MXFMetadataBase *
4546     m)
4547 {
4548   GstStructure *ret =
4549       MXF_METADATA_BASE_CLASS
4550       (mxf_metadata_generic_picture_essence_descriptor_parent_class)->to_structure
4551       (m);
4552   MXFMetadataGenericPictureEssenceDescriptor *self =
4553       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (m);
4554   gchar str[48];
4555 
4556   gst_structure_id_set (ret, MXF_QUARK (SIGNAL_STANDARD), G_TYPE_UCHAR,
4557       self->signal_standard, NULL);
4558 
4559   gst_structure_id_set (ret, MXF_QUARK (FRAME_LAYOUT), G_TYPE_UCHAR,
4560       self->frame_layout, NULL);
4561 
4562   gst_structure_id_set (ret, MXF_QUARK (STORED_WIDTH), G_TYPE_UINT,
4563       self->stored_width, MXF_QUARK (STORED_HEIGHT), G_TYPE_UINT,
4564       self->stored_height, NULL);
4565 
4566   if (self->stored_f2_offset != 0)
4567     gst_structure_id_set (ret, MXF_QUARK (STORED_F2_OFFSET), G_TYPE_INT,
4568         self->stored_f2_offset, NULL);
4569 
4570   if (self->sampled_width != 0 && self->sampled_height != 0)
4571     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_WIDTH), G_TYPE_UINT,
4572         self->sampled_width, MXF_QUARK (SAMPLED_HEIGHT), G_TYPE_UINT,
4573         self->sampled_height, NULL);
4574 
4575   if (self->sampled_x_offset != 0)
4576     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_X_OFFSET), G_TYPE_INT,
4577         self->sampled_x_offset, NULL);
4578 
4579   if (self->sampled_y_offset != 0)
4580     gst_structure_id_set (ret, MXF_QUARK (SAMPLED_Y_OFFSET), G_TYPE_INT,
4581         self->sampled_y_offset, NULL);
4582 
4583   if (self->display_width != 0 && self->display_height != 0)
4584     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_WIDTH), G_TYPE_UINT,
4585         self->display_width, MXF_QUARK (DISPLAY_HEIGHT), G_TYPE_UINT,
4586         self->display_height, NULL);
4587 
4588   if (self->display_x_offset != 0)
4589     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_X_OFFSET), G_TYPE_INT,
4590         self->display_x_offset, NULL);
4591 
4592   if (self->display_y_offset != 0)
4593     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_Y_OFFSET), G_TYPE_INT,
4594         self->display_y_offset, NULL);
4595 
4596   if (self->display_f2_offset != 0)
4597     gst_structure_id_set (ret, MXF_QUARK (DISPLAY_F2_OFFSET), G_TYPE_INT,
4598         self->display_f2_offset, NULL);
4599 
4600   if (self->aspect_ratio.n != 0 && self->aspect_ratio.d != 0)
4601     gst_structure_id_set (ret, MXF_QUARK (ASPECT_RATIO), GST_TYPE_FRACTION,
4602         self->aspect_ratio.n, self->aspect_ratio.d, NULL);
4603 
4604   if (self->active_format_descriptor)
4605     gst_structure_id_set (ret, MXF_QUARK (ACTIVE_FORMAT_DESCRIPTOR),
4606         G_TYPE_UCHAR, self->active_format_descriptor, NULL);
4607 
4608   gst_structure_id_set (ret, MXF_QUARK (VIDEO_LINE_MAP_0), G_TYPE_UINT,
4609       self->video_line_map[0], MXF_QUARK (VIDEO_LINE_MAP_1), G_TYPE_UINT,
4610       self->video_line_map[1], NULL);
4611 
4612   if (self->alpha_transparency != 0)
4613     gst_structure_id_set (ret, MXF_QUARK (ALPHA_TRANSPARENCY), G_TYPE_UCHAR,
4614         self->alpha_transparency, NULL);
4615 
4616   if (!mxf_ul_is_zero (&self->capture_gamma)) {
4617     mxf_ul_to_string (&self->capture_gamma, str);
4618     gst_structure_id_set (ret, MXF_QUARK (CAPTURE_GAMMA), G_TYPE_STRING, str,
4619         NULL);
4620   }
4621 
4622   if (self->image_alignment_offset != 0)
4623     gst_structure_id_set (ret, MXF_QUARK (IMAGE_ALIGNMENT_OFFSET), G_TYPE_UINT,
4624         self->image_alignment_offset, NULL);
4625 
4626   if (self->image_start_offset != 0)
4627     gst_structure_id_set (ret, MXF_QUARK (IMAGE_START_OFFSET), G_TYPE_UINT,
4628         self->image_start_offset, NULL);
4629 
4630   if (self->image_end_offset != 0)
4631     gst_structure_id_set (ret, MXF_QUARK (IMAGE_END_OFFSET), G_TYPE_UINT,
4632         self->image_end_offset, NULL);
4633 
4634   if (self->field_dominance != 0)
4635     gst_structure_id_set (ret, MXF_QUARK (FIELD_DOMINANCE), G_TYPE_UCHAR,
4636         self->field_dominance, NULL);
4637 
4638   if (!mxf_ul_is_zero (&self->picture_essence_coding)) {
4639     mxf_ul_to_string (&self->picture_essence_coding, str);
4640     gst_structure_id_set (ret, MXF_QUARK (PICTURE_ESSENCE_CODING),
4641         G_TYPE_STRING, str, NULL);
4642   }
4643 
4644   return ret;
4645 }
4646 
4647 static GList *
mxf_metadata_generic_picture_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)4648 mxf_metadata_generic_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
4649     MXFPrimerPack * primer)
4650 {
4651   MXFMetadataGenericPictureEssenceDescriptor *self =
4652       MXF_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (m);
4653   GList *ret =
4654       MXF_METADATA_BASE_CLASS
4655       (mxf_metadata_generic_picture_essence_descriptor_parent_class)->write_tags
4656       (m, primer);
4657   MXFLocalTag *t;
4658 
4659   if (self->signal_standard != 1) {
4660     t = g_slice_new0 (MXFLocalTag);
4661     memcpy (&t->ul, MXF_UL (SIGNAL_STANDARD), 16);
4662     t->size = 1;
4663     t->data = g_slice_alloc (t->size);
4664     t->g_slice = TRUE;
4665     GST_WRITE_UINT8 (t->data, self->signal_standard);
4666     mxf_primer_pack_add_mapping (primer, 0x3215, &t->ul);
4667     ret = g_list_prepend (ret, t);
4668   }
4669 
4670   t = g_slice_new0 (MXFLocalTag);
4671   memcpy (&t->ul, MXF_UL (FRAME_LAYOUT), 16);
4672   t->size = 1;
4673   t->data = g_slice_alloc (t->size);
4674   t->g_slice = TRUE;
4675   GST_WRITE_UINT8 (t->data, self->frame_layout);
4676   mxf_primer_pack_add_mapping (primer, 0x320c, &t->ul);
4677   ret = g_list_prepend (ret, t);
4678 
4679   t = g_slice_new0 (MXFLocalTag);
4680   memcpy (&t->ul, MXF_UL (STORED_WIDTH), 16);
4681   t->size = 4;
4682   t->data = g_slice_alloc (t->size);
4683   t->g_slice = TRUE;
4684   GST_WRITE_UINT32_BE (t->data, self->stored_width);
4685   mxf_primer_pack_add_mapping (primer, 0x3203, &t->ul);
4686   ret = g_list_prepend (ret, t);
4687 
4688   t = g_slice_new0 (MXFLocalTag);
4689   memcpy (&t->ul, MXF_UL (STORED_HEIGHT), 16);
4690   t->size = 4;
4691   t->data = g_slice_alloc (t->size);
4692   t->g_slice = TRUE;
4693   GST_WRITE_UINT32_BE (t->data, self->stored_height);
4694   mxf_primer_pack_add_mapping (primer, 0x3202, &t->ul);
4695   ret = g_list_prepend (ret, t);
4696 
4697   if (self->stored_f2_offset != 0) {
4698     t = g_slice_new0 (MXFLocalTag);
4699     memcpy (&t->ul, MXF_UL (STORED_F2_OFFSET), 16);
4700     t->size = 4;
4701     t->data = g_slice_alloc (t->size);
4702     t->g_slice = TRUE;
4703     GST_WRITE_UINT32_BE (t->data, self->stored_f2_offset);
4704     mxf_primer_pack_add_mapping (primer, 0x3216, &t->ul);
4705     ret = g_list_prepend (ret, t);
4706   }
4707 
4708   if (self->sampled_width != 0) {
4709     t = g_slice_new0 (MXFLocalTag);
4710     memcpy (&t->ul, MXF_UL (SAMPLED_WIDTH), 16);
4711     t->size = 4;
4712     t->data = g_slice_alloc (t->size);
4713     t->g_slice = TRUE;
4714     GST_WRITE_UINT32_BE (t->data, self->sampled_width);
4715     mxf_primer_pack_add_mapping (primer, 0x3205, &t->ul);
4716     ret = g_list_prepend (ret, t);
4717   }
4718 
4719   if (self->sampled_height != 0) {
4720     t = g_slice_new0 (MXFLocalTag);
4721     memcpy (&t->ul, MXF_UL (SAMPLED_HEIGHT), 16);
4722     t->size = 4;
4723     t->data = g_slice_alloc (t->size);
4724     t->g_slice = TRUE;
4725     GST_WRITE_UINT32_BE (t->data, self->sampled_height);
4726     mxf_primer_pack_add_mapping (primer, 0x3204, &t->ul);
4727     ret = g_list_prepend (ret, t);
4728   }
4729 
4730   if (self->sampled_x_offset != 0) {
4731     t = g_slice_new0 (MXFLocalTag);
4732     memcpy (&t->ul, MXF_UL (SAMPLED_X_OFFSET), 16);
4733     t->size = 4;
4734     t->data = g_slice_alloc (t->size);
4735     t->g_slice = TRUE;
4736     GST_WRITE_UINT32_BE (t->data, self->sampled_x_offset);
4737     mxf_primer_pack_add_mapping (primer, 0x3206, &t->ul);
4738     ret = g_list_prepend (ret, t);
4739   }
4740 
4741   if (self->sampled_y_offset != 0) {
4742     t = g_slice_new0 (MXFLocalTag);
4743     memcpy (&t->ul, MXF_UL (SAMPLED_Y_OFFSET), 16);
4744     t->size = 4;
4745     t->data = g_slice_alloc (t->size);
4746     t->g_slice = TRUE;
4747     GST_WRITE_UINT32_BE (t->data, self->sampled_y_offset);
4748     mxf_primer_pack_add_mapping (primer, 0x3207, &t->ul);
4749     ret = g_list_prepend (ret, t);
4750   }
4751 
4752   if (self->display_height != 0) {
4753     t = g_slice_new0 (MXFLocalTag);
4754     memcpy (&t->ul, MXF_UL (DISPLAY_HEIGHT), 16);
4755     t->size = 4;
4756     t->data = g_slice_alloc (t->size);
4757     t->g_slice = TRUE;
4758     GST_WRITE_UINT32_BE (t->data, self->display_height);
4759     mxf_primer_pack_add_mapping (primer, 0x3208, &t->ul);
4760     ret = g_list_prepend (ret, t);
4761   }
4762 
4763   if (self->display_width != 0) {
4764     t = g_slice_new0 (MXFLocalTag);
4765     memcpy (&t->ul, MXF_UL (DISPLAY_WIDTH), 16);
4766     t->size = 4;
4767     t->data = g_slice_alloc (t->size);
4768     t->g_slice = TRUE;
4769     GST_WRITE_UINT32_BE (t->data, self->display_width);
4770     mxf_primer_pack_add_mapping (primer, 0x3209, &t->ul);
4771     ret = g_list_prepend (ret, t);
4772   }
4773 
4774   if (self->display_x_offset != 0) {
4775     t = g_slice_new0 (MXFLocalTag);
4776     memcpy (&t->ul, MXF_UL (DISPLAY_X_OFFSET), 16);
4777     t->size = 4;
4778     t->data = g_slice_alloc (t->size);
4779     t->g_slice = TRUE;
4780     GST_WRITE_UINT32_BE (t->data, self->display_x_offset);
4781     mxf_primer_pack_add_mapping (primer, 0x320a, &t->ul);
4782     ret = g_list_prepend (ret, t);
4783   }
4784 
4785   if (self->display_y_offset != 0) {
4786     t = g_slice_new0 (MXFLocalTag);
4787     memcpy (&t->ul, MXF_UL (DISPLAY_Y_OFFSET), 16);
4788     t->size = 4;
4789     t->data = g_slice_alloc (t->size);
4790     t->g_slice = TRUE;
4791     GST_WRITE_UINT32_BE (t->data, self->display_y_offset);
4792     mxf_primer_pack_add_mapping (primer, 0x320b, &t->ul);
4793     ret = g_list_prepend (ret, t);
4794   }
4795 
4796   if (self->display_f2_offset != 0) {
4797     t = g_slice_new0 (MXFLocalTag);
4798     memcpy (&t->ul, MXF_UL (DISPLAY_F2_OFFSET), 16);
4799     t->size = 4;
4800     t->data = g_slice_alloc (t->size);
4801     t->g_slice = TRUE;
4802     GST_WRITE_UINT32_BE (t->data, self->display_f2_offset);
4803     mxf_primer_pack_add_mapping (primer, 0x3217, &t->ul);
4804     ret = g_list_prepend (ret, t);
4805   }
4806 
4807   t = g_slice_new0 (MXFLocalTag);
4808   memcpy (&t->ul, MXF_UL (ASPECT_RATIO), 16);
4809   t->size = 8;
4810   t->data = g_slice_alloc (t->size);
4811   t->g_slice = TRUE;
4812   GST_WRITE_UINT32_BE (t->data, self->aspect_ratio.n);
4813   GST_WRITE_UINT32_BE (t->data + 4, self->aspect_ratio.d);
4814   mxf_primer_pack_add_mapping (primer, 0x320e, &t->ul);
4815   ret = g_list_prepend (ret, t);
4816 
4817   if (self->active_format_descriptor != 0) {
4818     t = g_slice_new0 (MXFLocalTag);
4819     memcpy (&t->ul, MXF_UL (ACTIVE_FORMAT_DESCRIPTOR), 16);
4820     t->size = 1;
4821     t->data = g_slice_alloc (t->size);
4822     t->g_slice = TRUE;
4823     GST_WRITE_UINT8 (t->data, self->active_format_descriptor);
4824     mxf_primer_pack_add_mapping (primer, 0x3218, &t->ul);
4825     ret = g_list_prepend (ret, t);
4826   }
4827 
4828   t = g_slice_new0 (MXFLocalTag);
4829   memcpy (&t->ul, MXF_UL (VIDEO_LINE_MAP), 16);
4830   t->size = 16;
4831   t->data = g_slice_alloc (t->size);
4832   t->g_slice = TRUE;
4833   GST_WRITE_UINT32_BE (t->data, 2);
4834   GST_WRITE_UINT32_BE (t->data + 4, 4);
4835   GST_WRITE_UINT32_BE (t->data + 8, self->video_line_map[0]);
4836   GST_WRITE_UINT32_BE (t->data + 12, self->video_line_map[1]);
4837   mxf_primer_pack_add_mapping (primer, 0x320d, &t->ul);
4838   ret = g_list_prepend (ret, t);
4839 
4840   if (self->alpha_transparency != 0) {
4841     t = g_slice_new0 (MXFLocalTag);
4842     memcpy (&t->ul, MXF_UL (ALPHA_TRANSPARENCY), 16);
4843     t->size = 1;
4844     t->data = g_slice_alloc (t->size);
4845     t->g_slice = TRUE;
4846     GST_WRITE_UINT8 (t->data, self->alpha_transparency);
4847     mxf_primer_pack_add_mapping (primer, 0x320f, &t->ul);
4848     ret = g_list_prepend (ret, t);
4849   }
4850 
4851   if (!mxf_ul_is_zero (&self->capture_gamma)) {
4852     t = g_slice_new0 (MXFLocalTag);
4853     memcpy (&t->ul, MXF_UL (CAPTURE_GAMMA), 16);
4854     t->size = 16;
4855     t->data = g_slice_alloc (t->size);
4856     t->g_slice = TRUE;
4857     memcpy (t->data, &self->capture_gamma, 16);
4858     mxf_primer_pack_add_mapping (primer, 0x3210, &t->ul);
4859     ret = g_list_prepend (ret, t);
4860   }
4861 
4862   if (self->image_alignment_offset != 0) {
4863     t = g_slice_new0 (MXFLocalTag);
4864     memcpy (&t->ul, MXF_UL (IMAGE_ALIGNMENT_OFFSET), 16);
4865     t->size = 4;
4866     t->data = g_slice_alloc (t->size);
4867     t->g_slice = TRUE;
4868     GST_WRITE_UINT32_BE (t->data, self->image_alignment_offset);
4869     mxf_primer_pack_add_mapping (primer, 0x3211, &t->ul);
4870     ret = g_list_prepend (ret, t);
4871   }
4872 
4873   if (self->image_start_offset != 0) {
4874     t = g_slice_new0 (MXFLocalTag);
4875     memcpy (&t->ul, MXF_UL (IMAGE_START_OFFSET), 16);
4876     t->size = 4;
4877     t->data = g_slice_alloc (t->size);
4878     t->g_slice = TRUE;
4879     GST_WRITE_UINT32_BE (t->data, self->image_start_offset);
4880     mxf_primer_pack_add_mapping (primer, 0x3213, &t->ul);
4881     ret = g_list_prepend (ret, t);
4882   }
4883 
4884   if (self->image_end_offset != 0) {
4885     t = g_slice_new0 (MXFLocalTag);
4886     memcpy (&t->ul, MXF_UL (IMAGE_END_OFFSET), 16);
4887     t->size = 4;
4888     t->data = g_slice_alloc (t->size);
4889     t->g_slice = TRUE;
4890     GST_WRITE_UINT32_BE (t->data, self->image_end_offset);
4891     mxf_primer_pack_add_mapping (primer, 0x3214, &t->ul);
4892     ret = g_list_prepend (ret, t);
4893   }
4894 
4895   if (self->field_dominance != 0) {
4896     t = g_slice_new0 (MXFLocalTag);
4897     memcpy (&t->ul, MXF_UL (FIELD_DOMINANCE), 16);
4898     t->size = 1;
4899     t->data = g_slice_alloc (t->size);
4900     t->g_slice = TRUE;
4901     GST_WRITE_UINT8 (t->data, self->field_dominance);
4902     mxf_primer_pack_add_mapping (primer, 0x3212, &t->ul);
4903     ret = g_list_prepend (ret, t);
4904   }
4905 
4906   if (!mxf_ul_is_zero (&self->picture_essence_coding)) {
4907     t = g_slice_new0 (MXFLocalTag);
4908     memcpy (&t->ul, MXF_UL (PICTURE_ESSENCE_CODING), 16);
4909     t->size = 16;
4910     t->data = g_slice_alloc (t->size);
4911     t->g_slice = TRUE;
4912     memcpy (t->data, &self->picture_essence_coding, 16);
4913     mxf_primer_pack_add_mapping (primer, 0x3201, &t->ul);
4914     ret = g_list_prepend (ret, t);
4915   }
4916 
4917   return ret;
4918 }
4919 
4920 static void
mxf_metadata_generic_picture_essence_descriptor_init(MXFMetadataGenericPictureEssenceDescriptor * self)4921     mxf_metadata_generic_picture_essence_descriptor_init
4922     (MXFMetadataGenericPictureEssenceDescriptor * self)
4923 {
4924   self->signal_standard = 1;
4925   self->frame_layout = 255;
4926 }
4927 
4928 static void
mxf_metadata_generic_picture_essence_descriptor_class_init(MXFMetadataGenericPictureEssenceDescriptorClass * klass)4929     mxf_metadata_generic_picture_essence_descriptor_class_init
4930     (MXFMetadataGenericPictureEssenceDescriptorClass * klass)
4931 {
4932   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
4933   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
4934 
4935   metadata_base_class->handle_tag =
4936       mxf_metadata_generic_picture_essence_descriptor_handle_tag;
4937   metadata_base_class->name_quark =
4938       MXF_QUARK (GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
4939   metadata_base_class->to_structure =
4940       mxf_metadata_generic_picture_essence_descriptor_to_structure;
4941   metadata_base_class->write_tags =
4942       mxf_metadata_generic_picture_essence_descriptor_write_tags;
4943   metadata_class->type = 0x0127;
4944 }
4945 
mxf_metadata_generic_picture_essence_descriptor_set_caps(MXFMetadataGenericPictureEssenceDescriptor * self,GstCaps * caps)4946 void mxf_metadata_generic_picture_essence_descriptor_set_caps
4947     (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps)
4948 {
4949   guint par_n, par_d;
4950   guint width, height;
4951   MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
4952 
4953   g_return_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (self));
4954   g_return_if_fail (GST_IS_CAPS (caps));
4955 
4956   if (f->sample_rate.d == 0) {
4957     GST_ERROR ("Invalid framerate");
4958   } else {
4959     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, f->sample_rate.n,
4960         f->sample_rate.d, NULL);
4961   }
4962 
4963   width = self->stored_width;
4964   height = self->stored_height;
4965   if (self->sampled_width && self->sampled_height) {
4966     width = self->sampled_width;
4967     height = self->sampled_height;
4968   }
4969   if (self->display_width && self->display_height) {
4970     width = self->display_width;
4971     height = self->display_height;
4972   }
4973 
4974   /* If the video is stored as separate fields the
4975    * height is only the height of one field, i.e.
4976    * half the height of the frame.
4977    *
4978    * See SMPTE 377M E2.2 and E1.2
4979    */
4980   if (self->frame_layout == 1 || self->frame_layout == 2
4981       || self->frame_layout == 4) {
4982     height *= 2;
4983     gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
4984 
4985     if (self->field_dominance == 2) {
4986       gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
4987           "bottom-field-first", NULL);
4988     } else {
4989       gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
4990           "top-field-first", NULL);
4991     }
4992   }
4993 
4994   if (width == 0 || height == 0) {
4995     GST_ERROR ("Invalid width/height");
4996     return;
4997   }
4998 
4999   gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", G_TYPE_INT,
5000       height, NULL);
5001 
5002   if (self->aspect_ratio.n == 0 && self->aspect_ratio.d == 0) {
5003     gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
5004         1, 1, NULL);
5005   } else if (self->aspect_ratio.n == 0 || self->aspect_ratio.d == 0) {
5006     GST_ERROR ("Invalid aspect ratio");
5007   } else {
5008     par_n = height * self->aspect_ratio.n;
5009     par_d = width * self->aspect_ratio.d;
5010 
5011     gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
5012         par_n, par_d, NULL);
5013   }
5014 }
5015 
5016 static gint
gst_greatest_common_divisor(gint a,gint b)5017 gst_greatest_common_divisor (gint a, gint b)
5018 {
5019   while (b != 0) {
5020     int temp = a;
5021 
5022     a = b;
5023     b = temp % b;
5024   }
5025 
5026   return ABS (a);
5027 }
5028 
5029 gboolean
mxf_metadata_generic_picture_essence_descriptor_from_caps(MXFMetadataGenericPictureEssenceDescriptor * self,GstCaps * caps)5030     mxf_metadata_generic_picture_essence_descriptor_from_caps
5031     (MXFMetadataGenericPictureEssenceDescriptor * self, GstCaps * caps) {
5032   gint par_n, par_d, gcd;
5033   gint width, height;
5034   gint fps_n, fps_d;
5035   MXFMetadataFileDescriptor *f = (MXFMetadataFileDescriptor *) self;
5036   GstStructure *s;
5037   gboolean interlaced = FALSE;
5038   const gchar *field_order = NULL;
5039 
5040   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR
5041       (self), FALSE);
5042   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
5043 
5044   s = gst_caps_get_structure (caps, 0);
5045 
5046   if (!gst_structure_get_boolean (s, "interlaced", &interlaced) || !interlaced) {
5047     self->frame_layout = 0;
5048   } else {
5049     self->frame_layout = 3;
5050     field_order = gst_structure_get_string (s, "field-order");
5051     if (!field_order || strcmp (field_order, "top-field-first") == 0)
5052       self->field_dominance = 1;
5053     else
5054       self->field_dominance = 2;
5055   }
5056 
5057   if (!gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
5058     GST_ERROR ("Invalid framerate");
5059     return FALSE;
5060   }
5061   f->sample_rate.n = fps_n;
5062   f->sample_rate.d = fps_d;
5063 
5064   if (!gst_structure_get_int (s, "width", &width) ||
5065       !gst_structure_get_int (s, "height", &height)) {
5066     GST_ERROR ("Invalid width/height");
5067     return FALSE;
5068   }
5069 
5070   self->stored_width = width;
5071   self->stored_height = height;
5072 
5073   if (!gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d)) {
5074     par_n = 1;
5075     par_d = 1;
5076   }
5077 
5078   self->aspect_ratio.n = par_n * width;
5079   self->aspect_ratio.d = par_d * height;
5080   gcd =
5081       gst_greatest_common_divisor (self->aspect_ratio.n, self->aspect_ratio.d);
5082   self->aspect_ratio.n /= gcd;
5083   self->aspect_ratio.d /= gcd;
5084 
5085   return TRUE;
5086 }
5087 
5088 
5089 G_DEFINE_TYPE (MXFMetadataGenericSoundEssenceDescriptor,
5090     mxf_metadata_generic_sound_essence_descriptor,
5091     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
5092 
5093 static gboolean
mxf_metadata_generic_sound_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5094 mxf_metadata_generic_sound_essence_descriptor_handle_tag (MXFMetadataBase *
5095     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5096     guint tag_size)
5097 {
5098   MXFMetadataGenericSoundEssenceDescriptor *self =
5099       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (metadata);
5100   gboolean ret = TRUE;
5101 #ifndef GST_DISABLE_GST_DEBUG
5102   gchar str[48];
5103 #endif
5104 
5105   switch (tag) {
5106     case 0x3d03:
5107       if (!mxf_fraction_parse (&self->audio_sampling_rate, tag_data, tag_size))
5108         goto error;
5109       GST_DEBUG ("  audio sampling rate = %d/%d",
5110           self->audio_sampling_rate.n, self->audio_sampling_rate.d);
5111       break;
5112     case 0x3d02:
5113       if (tag_size != 1)
5114         goto error;
5115       self->locked = (GST_READ_UINT8 (tag_data) != 0);
5116       GST_DEBUG ("  locked = %s", (self->locked) ? "yes" : "no");
5117       break;
5118     case 0x3d04:
5119       if (tag_size != 1)
5120         goto error;
5121       self->audio_ref_level = GST_READ_UINT8 (tag_data);
5122       GST_DEBUG ("  audio ref level = %d", self->audio_ref_level);
5123       break;
5124     case 0x3d05:
5125       if (tag_size != 1)
5126         goto error;
5127       self->electro_spatial_formulation = GST_READ_UINT8 (tag_data);
5128       GST_DEBUG ("  electro spatial formulation = %u",
5129           self->electro_spatial_formulation);
5130       break;
5131     case 0x3d07:
5132       if (tag_size != 4)
5133         goto error;
5134       self->channel_count = GST_READ_UINT32_BE (tag_data);
5135       GST_DEBUG ("  channel count = %u", self->channel_count);
5136       break;
5137     case 0x3d01:
5138       if (tag_size != 4)
5139         goto error;
5140       self->quantization_bits = GST_READ_UINT32_BE (tag_data);
5141       GST_DEBUG ("  quantization bits = %u", self->quantization_bits);
5142       break;
5143     case 0x3d0c:
5144       if (tag_size != 1)
5145         goto error;
5146       self->dial_norm = GST_READ_UINT8 (tag_data);
5147       GST_DEBUG ("  dial norm = %d", self->dial_norm);
5148       break;
5149     case 0x3d06:
5150       if (tag_size != 16)
5151         goto error;
5152       memcpy (&self->sound_essence_compression, tag_data, 16);
5153       GST_DEBUG ("  sound essence compression = %s",
5154           mxf_ul_to_string (&self->sound_essence_compression, str));
5155       break;
5156     default:
5157       ret =
5158           MXF_METADATA_BASE_CLASS
5159           (mxf_metadata_generic_sound_essence_descriptor_parent_class)->handle_tag
5160           (metadata, primer, tag, tag_data, tag_size);
5161       break;
5162   }
5163 
5164   return ret;
5165 
5166 error:
5167 
5168   GST_ERROR
5169       ("Invalid generic sound essence descriptor local tag 0x%04x of size %u",
5170       tag, tag_size);
5171 
5172   return FALSE;
5173 }
5174 
5175 static GstStructure *
mxf_metadata_generic_sound_essence_descriptor_to_structure(MXFMetadataBase * m)5176 mxf_metadata_generic_sound_essence_descriptor_to_structure (MXFMetadataBase * m)
5177 {
5178   GstStructure *ret =
5179       MXF_METADATA_BASE_CLASS
5180       (mxf_metadata_generic_sound_essence_descriptor_parent_class)->to_structure
5181       (m);
5182   MXFMetadataGenericSoundEssenceDescriptor *self =
5183       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (m);
5184 
5185   gst_structure_id_set (ret, MXF_QUARK (AUDIO_SAMPLING_RATE), GST_TYPE_FRACTION,
5186       self->audio_sampling_rate.n, self->audio_sampling_rate.d, NULL);
5187 
5188   gst_structure_id_set (ret, MXF_QUARK (LOCKED), G_TYPE_BOOLEAN, self->locked,
5189       NULL);
5190 
5191   if (self->electro_spatial_formulation != 0)
5192     gst_structure_id_set (ret, MXF_QUARK (ELECTRO_SPATIAL_FORMULATION),
5193         G_TYPE_UCHAR, self->electro_spatial_formulation, NULL);
5194 
5195   gst_structure_id_set (ret, MXF_QUARK (CHANNEL_COUNT), G_TYPE_UINT,
5196       self->channel_count, NULL);
5197 
5198   gst_structure_id_set (ret, MXF_QUARK (QUANTIZATION_BITS), G_TYPE_UINT,
5199       self->quantization_bits, NULL);
5200 
5201   if (self->dial_norm != 0)
5202     gst_structure_id_set (ret, MXF_QUARK (DIAL_NORM), G_TYPE_CHAR,
5203         self->dial_norm, NULL);
5204 
5205   if (!mxf_ul_is_zero (&self->sound_essence_compression)) {
5206     gchar str[48];
5207 
5208     mxf_ul_to_string (&self->sound_essence_compression, str);
5209     gst_structure_id_set (ret, MXF_QUARK (SOUND_ESSENCE_COMPRESSION),
5210         G_TYPE_STRING, str, NULL);
5211   }
5212 
5213   return ret;
5214 }
5215 
5216 static GList *
mxf_metadata_generic_sound_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)5217 mxf_metadata_generic_sound_essence_descriptor_write_tags (MXFMetadataBase * m,
5218     MXFPrimerPack * primer)
5219 {
5220   MXFMetadataGenericSoundEssenceDescriptor *self =
5221       MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (m);
5222   GList *ret =
5223       MXF_METADATA_BASE_CLASS
5224       (mxf_metadata_generic_sound_essence_descriptor_parent_class)->write_tags
5225       (m, primer);
5226   MXFLocalTag *t;
5227 
5228   t = g_slice_new0 (MXFLocalTag);
5229   memcpy (&t->ul, MXF_UL (AUDIO_SAMPLING_RATE), 16);
5230   t->size = 8;
5231   t->data = g_slice_alloc (t->size);
5232   t->g_slice = TRUE;
5233   GST_WRITE_UINT32_BE (t->data, self->audio_sampling_rate.n);
5234   GST_WRITE_UINT32_BE (t->data + 4, self->audio_sampling_rate.d);
5235   mxf_primer_pack_add_mapping (primer, 0x3d03, &t->ul);
5236   ret = g_list_prepend (ret, t);
5237 
5238   t = g_slice_new0 (MXFLocalTag);
5239   memcpy (&t->ul, MXF_UL (LOCKED), 16);
5240   t->size = 1;
5241   t->data = g_slice_alloc (t->size);
5242   t->g_slice = TRUE;
5243   GST_WRITE_UINT8 (t->data, (self->locked) ? 1 : 0);
5244   mxf_primer_pack_add_mapping (primer, 0x3d02, &t->ul);
5245   ret = g_list_prepend (ret, t);
5246 
5247   if (self->audio_ref_level) {
5248     t = g_slice_new0 (MXFLocalTag);
5249     memcpy (&t->ul, MXF_UL (AUDIO_REF_LEVEL), 16);
5250     t->size = 1;
5251     t->data = g_slice_alloc (t->size);
5252     t->g_slice = TRUE;
5253     GST_WRITE_UINT8 (t->data, self->audio_ref_level);
5254     mxf_primer_pack_add_mapping (primer, 0x3d04, &t->ul);
5255     ret = g_list_prepend (ret, t);
5256   }
5257 
5258   if (self->electro_spatial_formulation != 255) {
5259     t = g_slice_new0 (MXFLocalTag);
5260     memcpy (&t->ul, MXF_UL (ELECTRO_SPATIAL_FORMULATION), 16);
5261     t->size = 1;
5262     t->data = g_slice_alloc (t->size);
5263     t->g_slice = TRUE;
5264     GST_WRITE_UINT8 (t->data, self->electro_spatial_formulation);
5265     mxf_primer_pack_add_mapping (primer, 0x3d05, &t->ul);
5266     ret = g_list_prepend (ret, t);
5267   }
5268 
5269   t = g_slice_new0 (MXFLocalTag);
5270   memcpy (&t->ul, MXF_UL (CHANNEL_COUNT), 16);
5271   t->size = 4;
5272   t->data = g_slice_alloc (t->size);
5273   t->g_slice = TRUE;
5274   GST_WRITE_UINT32_BE (t->data, self->channel_count);
5275   mxf_primer_pack_add_mapping (primer, 0x3d07, &t->ul);
5276   ret = g_list_prepend (ret, t);
5277 
5278   t = g_slice_new0 (MXFLocalTag);
5279   memcpy (&t->ul, MXF_UL (QUANTIZATION_BITS), 16);
5280   t->size = 4;
5281   t->data = g_slice_alloc (t->size);
5282   t->g_slice = TRUE;
5283   GST_WRITE_UINT32_BE (t->data, self->quantization_bits);
5284   mxf_primer_pack_add_mapping (primer, 0x3d01, &t->ul);
5285   ret = g_list_prepend (ret, t);
5286 
5287   if (self->dial_norm != 0) {
5288     t = g_slice_new0 (MXFLocalTag);
5289     memcpy (&t->ul, MXF_UL (DIAL_NORM), 16);
5290     t->size = 1;
5291     t->data = g_slice_alloc (t->size);
5292     t->g_slice = TRUE;
5293     GST_WRITE_UINT8 (t->data, self->dial_norm);
5294     mxf_primer_pack_add_mapping (primer, 0x3d0c, &t->ul);
5295     ret = g_list_prepend (ret, t);
5296   }
5297 
5298   if (!mxf_ul_is_zero (&self->sound_essence_compression)) {
5299     t = g_slice_new0 (MXFLocalTag);
5300     memcpy (&t->ul, MXF_UL (SOUND_ESSENCE_COMPRESSION), 16);
5301     t->size = 16;
5302     t->data = g_slice_alloc (t->size);
5303     t->g_slice = TRUE;
5304     memcpy (t->data, &self->sound_essence_compression, 16);
5305     mxf_primer_pack_add_mapping (primer, 0x3d06, &t->ul);
5306     ret = g_list_prepend (ret, t);
5307   }
5308 
5309   return ret;
5310 }
5311 
5312 static void
mxf_metadata_generic_sound_essence_descriptor_init(MXFMetadataGenericSoundEssenceDescriptor * self)5313     mxf_metadata_generic_sound_essence_descriptor_init
5314     (MXFMetadataGenericSoundEssenceDescriptor * self)
5315 {
5316   self->audio_sampling_rate.n = 0;
5317   self->audio_sampling_rate.d = 1;
5318   self->electro_spatial_formulation = 255;
5319 }
5320 
5321 static void
mxf_metadata_generic_sound_essence_descriptor_class_init(MXFMetadataGenericSoundEssenceDescriptorClass * klass)5322     mxf_metadata_generic_sound_essence_descriptor_class_init
5323     (MXFMetadataGenericSoundEssenceDescriptorClass * klass)
5324 {
5325   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5326   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5327 
5328   metadata_base_class->handle_tag =
5329       mxf_metadata_generic_sound_essence_descriptor_handle_tag;
5330   metadata_base_class->name_quark =
5331       MXF_QUARK (GENERIC_SOUND_ESSENCE_DESCRIPTOR);
5332   metadata_base_class->to_structure =
5333       mxf_metadata_generic_sound_essence_descriptor_to_structure;
5334   metadata_base_class->write_tags =
5335       mxf_metadata_generic_sound_essence_descriptor_write_tags;
5336   metadata_class->type = 0x0142;
5337 }
5338 
mxf_metadata_generic_sound_essence_descriptor_set_caps(MXFMetadataGenericSoundEssenceDescriptor * self,GstCaps * caps)5339 void mxf_metadata_generic_sound_essence_descriptor_set_caps
5340     (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps)
5341 {
5342   g_return_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self));
5343   g_return_if_fail (GST_IS_CAPS (caps));
5344 
5345   if (self->audio_sampling_rate.n == 0 || self->audio_sampling_rate.d == 0) {
5346     GST_ERROR ("Invalid audio sampling rate");
5347   } else {
5348     gst_caps_set_simple (caps, "rate", G_TYPE_INT,
5349         (gint) (mxf_fraction_to_double (&self->audio_sampling_rate) + 0.5),
5350         NULL);
5351   }
5352 
5353   if (self->channel_count == 0) {
5354     GST_ERROR ("Invalid number of channels (0)");
5355   } else {
5356     gst_caps_set_simple (caps, "channels", G_TYPE_INT, self->channel_count,
5357         NULL);
5358   }
5359 }
5360 
mxf_metadata_generic_sound_essence_descriptor_create_caps(MXFMetadataGenericSoundEssenceDescriptor * self,GstAudioFormat * format)5361 GstCaps *mxf_metadata_generic_sound_essence_descriptor_create_caps
5362     (MXFMetadataGenericSoundEssenceDescriptor * self, GstAudioFormat * format)
5363 {
5364   GstAudioInfo info;
5365   gint rate = 0;
5366   gint channels = 0;
5367 
5368   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self),
5369       NULL);
5370 
5371   gst_audio_info_init (&info);
5372 
5373   if (self->audio_sampling_rate.n == 0 || self->audio_sampling_rate.d == 0) {
5374     GST_ERROR ("Invalid audio sampling rate");
5375   } else {
5376     rate = (gint) (mxf_fraction_to_double (&self->audio_sampling_rate)
5377         + 0.5);
5378   }
5379 
5380   if (self->channel_count == 0) {
5381     GST_ERROR ("Invalid number of channels (0)");
5382   } else {
5383     channels = self->channel_count;
5384   }
5385 
5386   gst_audio_info_set_format (&info, *format, rate, channels, NULL);
5387 
5388   return gst_audio_info_to_caps (&info);
5389 }
5390 
5391 gboolean
mxf_metadata_generic_sound_essence_descriptor_from_caps(MXFMetadataGenericSoundEssenceDescriptor * self,GstCaps * caps)5392     mxf_metadata_generic_sound_essence_descriptor_from_caps
5393     (MXFMetadataGenericSoundEssenceDescriptor * self, GstCaps * caps) {
5394   gint rate;
5395   gint channels;
5396   GstStructure *s;
5397 
5398   g_return_val_if_fail (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (self),
5399       FALSE);
5400   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
5401 
5402   s = gst_caps_get_structure (caps, 0);
5403 
5404   if (!gst_structure_get_int (s, "rate", &rate) || rate == 0) {
5405     GST_WARNING ("No samplerate");
5406     return FALSE;
5407   } else {
5408     self->audio_sampling_rate.n = rate;
5409     self->audio_sampling_rate.d = 1;
5410   }
5411 
5412   if (!gst_structure_get_int (s, "channels", &channels) || channels == 0) {
5413     GST_WARNING ("No channels");
5414     return FALSE;
5415   } else {
5416     self->channel_count = channels;
5417   }
5418 
5419   return TRUE;
5420 }
5421 
5422 
5423 G_DEFINE_TYPE (MXFMetadataCDCIPictureEssenceDescriptor,
5424     mxf_metadata_cdci_picture_essence_descriptor,
5425     MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
5426 
5427 static gboolean
mxf_metadata_cdci_picture_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5428 mxf_metadata_cdci_picture_essence_descriptor_handle_tag (MXFMetadataBase *
5429     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5430     guint tag_size)
5431 {
5432   MXFMetadataCDCIPictureEssenceDescriptor *self =
5433       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (metadata);
5434   gboolean ret = TRUE;
5435 
5436   switch (tag) {
5437     case 0x3301:
5438       if (tag_size != 4)
5439         goto error;
5440       self->component_depth = GST_READ_UINT32_BE (tag_data);
5441       GST_DEBUG ("  component depth = %u", self->component_depth);
5442       break;
5443     case 0x3302:
5444       if (tag_size != 4)
5445         goto error;
5446       self->horizontal_subsampling = GST_READ_UINT32_BE (tag_data);
5447       GST_DEBUG ("  horizontal subsampling = %u", self->horizontal_subsampling);
5448       break;
5449     case 0x3308:
5450       if (tag_size != 4)
5451         goto error;
5452       self->vertical_subsampling = GST_READ_UINT32_BE (tag_data);
5453       GST_DEBUG ("  vertical subsampling = %u", self->vertical_subsampling);
5454       break;
5455     case 0x3303:
5456       if (tag_size != 1)
5457         goto error;
5458       self->color_siting = GST_READ_UINT8 (tag_data);
5459       GST_DEBUG ("  color siting = %u", self->color_siting);
5460       break;
5461     case 0x330b:
5462       if (tag_size != 1)
5463         goto error;
5464       self->reversed_byte_order = GST_READ_UINT8 (tag_data);
5465       GST_DEBUG ("  reversed byte order = %s",
5466           (self->reversed_byte_order) ? "yes" : "no");
5467       break;
5468     case 0x3307:
5469       if (tag_size != 2)
5470         goto error;
5471       self->padding_bits = GST_READ_UINT16_BE (tag_data);
5472       GST_DEBUG ("  padding bits = %d", self->padding_bits);
5473       break;
5474     case 0x3309:
5475       if (tag_size != 4)
5476         goto error;
5477       self->alpha_sample_depth = GST_READ_UINT32_BE (tag_data);
5478       GST_DEBUG ("  alpha sample depth = %u", self->alpha_sample_depth);
5479       break;
5480     case 0x3304:
5481       if (tag_size != 4)
5482         goto error;
5483       self->black_ref_level = GST_READ_UINT32_BE (tag_data);
5484       GST_DEBUG ("  black ref level = %u", self->black_ref_level);
5485       break;
5486     case 0x3305:
5487       if (tag_size != 4)
5488         goto error;
5489       self->white_ref_level = GST_READ_UINT32_BE (tag_data);
5490       GST_DEBUG ("  white ref level = %u", self->white_ref_level);
5491       break;
5492     case 0x3306:
5493       if (tag_size != 4)
5494         goto error;
5495       self->color_range = GST_READ_UINT32_BE (tag_data);
5496       GST_DEBUG ("  color range = %u", self->color_range);
5497       break;
5498     default:
5499       ret =
5500           MXF_METADATA_BASE_CLASS
5501           (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->handle_tag
5502           (metadata, primer, tag, tag_data, tag_size);
5503       break;
5504   }
5505 
5506   return ret;
5507 
5508 error:
5509 
5510   GST_ERROR
5511       ("Invalid CDCI picture essence descriptor local tag 0x%04x of size %u",
5512       tag, tag_size);
5513 
5514   return FALSE;
5515 }
5516 
5517 static GstStructure *
mxf_metadata_cdci_picture_essence_descriptor_to_structure(MXFMetadataBase * m)5518 mxf_metadata_cdci_picture_essence_descriptor_to_structure (MXFMetadataBase * m)
5519 {
5520   GstStructure *ret =
5521       MXF_METADATA_BASE_CLASS
5522       (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->to_structure
5523       (m);
5524   MXFMetadataCDCIPictureEssenceDescriptor *self =
5525       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (m);
5526 
5527   gst_structure_id_set (ret, MXF_QUARK (COMPONENT_DEPTH), G_TYPE_UINT,
5528       self->component_depth, NULL);
5529 
5530   gst_structure_id_set (ret, MXF_QUARK (HORIZONTAL_SUBSAMPLING), G_TYPE_UINT,
5531       self->horizontal_subsampling, NULL);
5532 
5533   if (self->vertical_subsampling != 0)
5534     gst_structure_id_set (ret, MXF_QUARK (VERTICAL_SUBSAMPLING), G_TYPE_UINT,
5535         self->vertical_subsampling, NULL);
5536 
5537   if (self->color_siting != 255)
5538     gst_structure_id_set (ret, MXF_QUARK (COLOR_SITING), G_TYPE_UCHAR,
5539         self->color_siting, NULL);
5540 
5541   gst_structure_id_set (ret, MXF_QUARK (REVERSED_BYTE_ORDER), G_TYPE_BOOLEAN,
5542       self->reversed_byte_order, NULL);
5543 
5544   if (self->padding_bits != 0)
5545     gst_structure_id_set (ret, MXF_QUARK (PADDING_BITS), G_TYPE_INT,
5546         self->padding_bits, NULL);
5547 
5548   if (self->alpha_sample_depth != 0)
5549     gst_structure_id_set (ret, MXF_QUARK (ALPHA_SAMPLE_DEPTH), G_TYPE_UINT,
5550         self->alpha_sample_depth, NULL);
5551 
5552   if (self->black_ref_level != 0)
5553     gst_structure_id_set (ret, MXF_QUARK (BLACK_REF_LEVEL), G_TYPE_UINT,
5554         self->black_ref_level, NULL);
5555 
5556   if (self->white_ref_level != 0)
5557     gst_structure_id_set (ret, MXF_QUARK (WHITE_REF_LEVEL), G_TYPE_UINT,
5558         self->white_ref_level, NULL);
5559 
5560   if (self->color_range != 0)
5561     gst_structure_id_set (ret, MXF_QUARK (COLOR_RANGE), G_TYPE_UINT,
5562         self->color_range, NULL);
5563 
5564   return ret;
5565 }
5566 
5567 static GList *
mxf_metadata_cdci_picture_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)5568 mxf_metadata_cdci_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
5569     MXFPrimerPack * primer)
5570 {
5571   MXFMetadataCDCIPictureEssenceDescriptor *self =
5572       MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR (m);
5573   GList *ret =
5574       MXF_METADATA_BASE_CLASS
5575       (mxf_metadata_cdci_picture_essence_descriptor_parent_class)->write_tags
5576       (m, primer);
5577   MXFLocalTag *t;
5578 
5579   t = g_slice_new0 (MXFLocalTag);
5580   memcpy (&t->ul, MXF_UL (COMPONENT_DEPTH), 16);
5581   t->size = 4;
5582   t->data = g_slice_alloc (t->size);
5583   t->g_slice = TRUE;
5584   GST_WRITE_UINT32_BE (t->data, self->component_depth);
5585   mxf_primer_pack_add_mapping (primer, 0x3301, &t->ul);
5586   ret = g_list_prepend (ret, t);
5587 
5588   t = g_slice_new0 (MXFLocalTag);
5589   memcpy (&t->ul, MXF_UL (HORIZONTAL_SUBSAMPLING), 16);
5590   t->size = 4;
5591   t->data = g_slice_alloc (t->size);
5592   t->g_slice = TRUE;
5593   GST_WRITE_UINT32_BE (t->data, self->horizontal_subsampling);
5594   mxf_primer_pack_add_mapping (primer, 0x3302, &t->ul);
5595   ret = g_list_prepend (ret, t);
5596 
5597   if (self->vertical_subsampling) {
5598     t = g_slice_new0 (MXFLocalTag);
5599     memcpy (&t->ul, MXF_UL (VERTICAL_SUBSAMPLING), 16);
5600     t->size = 4;
5601     t->data = g_slice_alloc (t->size);
5602     t->g_slice = TRUE;
5603     GST_WRITE_UINT32_BE (t->data, self->vertical_subsampling);
5604     mxf_primer_pack_add_mapping (primer, 0x3308, &t->ul);
5605     ret = g_list_prepend (ret, t);
5606   }
5607 
5608   if (self->color_siting != 0xff) {
5609     t = g_slice_new0 (MXFLocalTag);
5610     memcpy (&t->ul, MXF_UL (COLOR_SITING), 16);
5611     t->size = 1;
5612     t->data = g_slice_alloc (t->size);
5613     t->g_slice = TRUE;
5614     GST_WRITE_UINT8 (t->data, self->color_siting);
5615     mxf_primer_pack_add_mapping (primer, 0x3303, &t->ul);
5616     ret = g_list_prepend (ret, t);
5617   }
5618 
5619   if (self->reversed_byte_order) {
5620     t = g_slice_new0 (MXFLocalTag);
5621     memcpy (&t->ul, MXF_UL (REVERSED_BYTE_ORDER), 16);
5622     t->size = 1;
5623     t->data = g_slice_alloc (t->size);
5624     t->g_slice = TRUE;
5625     GST_WRITE_UINT8 (t->data, (self->reversed_byte_order) ? 1 : 0);
5626     mxf_primer_pack_add_mapping (primer, 0x330b, &t->ul);
5627     ret = g_list_prepend (ret, t);
5628   }
5629 
5630   if (self->padding_bits) {
5631     t = g_slice_new0 (MXFLocalTag);
5632     memcpy (&t->ul, MXF_UL (PADDING_BITS), 16);
5633     t->size = 2;
5634     t->data = g_slice_alloc (t->size);
5635     t->g_slice = TRUE;
5636     GST_WRITE_UINT16_BE (t->data, self->padding_bits);
5637     mxf_primer_pack_add_mapping (primer, 0x3307, &t->ul);
5638     ret = g_list_prepend (ret, t);
5639   }
5640 
5641   if (self->alpha_sample_depth) {
5642     t = g_slice_new0 (MXFLocalTag);
5643     memcpy (&t->ul, MXF_UL (ALPHA_SAMPLE_DEPTH), 16);
5644     t->size = 4;
5645     t->data = g_slice_alloc (t->size);
5646     t->g_slice = TRUE;
5647     GST_WRITE_UINT32_BE (t->data, self->alpha_sample_depth);
5648     mxf_primer_pack_add_mapping (primer, 0x3309, &t->ul);
5649     ret = g_list_prepend (ret, t);
5650   }
5651 
5652   if (self->black_ref_level) {
5653     t = g_slice_new0 (MXFLocalTag);
5654     memcpy (&t->ul, MXF_UL (BLACK_REF_LEVEL), 16);
5655     t->size = 4;
5656     t->data = g_slice_alloc (t->size);
5657     t->g_slice = TRUE;
5658     GST_WRITE_UINT32_BE (t->data, self->black_ref_level);
5659     mxf_primer_pack_add_mapping (primer, 0x3304, &t->ul);
5660     ret = g_list_prepend (ret, t);
5661   }
5662 
5663   if (self->white_ref_level) {
5664     t = g_slice_new0 (MXFLocalTag);
5665     memcpy (&t->ul, MXF_UL (WHITE_REF_LEVEL), 16);
5666     t->size = 4;
5667     t->data = g_slice_alloc (t->size);
5668     t->g_slice = TRUE;
5669     GST_WRITE_UINT32_BE (t->data, self->white_ref_level);
5670     mxf_primer_pack_add_mapping (primer, 0x3305, &t->ul);
5671     ret = g_list_prepend (ret, t);
5672   }
5673 
5674   if (self->color_range) {
5675     t = g_slice_new0 (MXFLocalTag);
5676     memcpy (&t->ul, MXF_UL (COLOR_RANGE), 16);
5677     t->size = 4;
5678     t->data = g_slice_alloc (t->size);
5679     t->g_slice = TRUE;
5680     GST_WRITE_UINT32_BE (t->data, self->color_range);
5681     mxf_primer_pack_add_mapping (primer, 0x3306, &t->ul);
5682     ret = g_list_prepend (ret, t);
5683   }
5684 
5685   return ret;
5686 }
5687 
5688 static void
mxf_metadata_cdci_picture_essence_descriptor_init(MXFMetadataCDCIPictureEssenceDescriptor * self)5689     mxf_metadata_cdci_picture_essence_descriptor_init
5690     (MXFMetadataCDCIPictureEssenceDescriptor * self)
5691 {
5692   self->color_siting = 0xff;
5693 }
5694 
5695 static void
mxf_metadata_cdci_picture_essence_descriptor_class_init(MXFMetadataCDCIPictureEssenceDescriptorClass * klass)5696     mxf_metadata_cdci_picture_essence_descriptor_class_init
5697     (MXFMetadataCDCIPictureEssenceDescriptorClass * klass)
5698 {
5699   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5700   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5701 
5702   metadata_base_class->handle_tag =
5703       mxf_metadata_cdci_picture_essence_descriptor_handle_tag;
5704   metadata_base_class->name_quark = MXF_QUARK (CDCI_PICTURE_ESSENCE_DESCRIPTOR);
5705   metadata_base_class->to_structure =
5706       mxf_metadata_cdci_picture_essence_descriptor_to_structure;
5707   metadata_base_class->write_tags =
5708       mxf_metadata_cdci_picture_essence_descriptor_write_tags;
5709   metadata_class->type = 0x0128;
5710 }
5711 
5712 G_DEFINE_TYPE (MXFMetadataRGBAPictureEssenceDescriptor,
5713     mxf_metadata_rgba_picture_essence_descriptor,
5714     MXF_TYPE_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR);
5715 
5716 static void
mxf_metadata_rgba_picture_essence_descriptor_finalize(GObject * object)5717 mxf_metadata_rgba_picture_essence_descriptor_finalize (GObject * object)
5718 {
5719   MXFMetadataRGBAPictureEssenceDescriptor *self =
5720       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (object);
5721 
5722   g_free (self->pixel_layout);
5723   self->pixel_layout = NULL;
5724 
5725   G_OBJECT_CLASS
5726       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->finalize
5727       (object);
5728 }
5729 
5730 static gboolean
mxf_metadata_rgba_picture_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5731 mxf_metadata_rgba_picture_essence_descriptor_handle_tag (MXFMetadataBase *
5732     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5733     guint tag_size)
5734 {
5735   MXFMetadataRGBAPictureEssenceDescriptor *self =
5736       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (metadata);
5737   gboolean ret = TRUE;
5738 
5739   switch (tag) {
5740     case 0x3406:
5741       if (tag_size != 4)
5742         goto error;
5743       self->component_max_ref = GST_READ_UINT32_BE (tag_data);
5744       GST_DEBUG ("  component max ref = %u", self->component_max_ref);
5745       break;
5746     case 0x3407:
5747       if (tag_size != 4)
5748         goto error;
5749       self->component_min_ref = GST_READ_UINT32_BE (tag_data);
5750       GST_DEBUG ("  component min ref = %u", self->component_min_ref);
5751       break;
5752     case 0x3408:
5753       if (tag_size != 4)
5754         goto error;
5755       self->alpha_max_ref = GST_READ_UINT32_BE (tag_data);
5756       GST_DEBUG ("  alpha max ref = %u", self->alpha_max_ref);
5757       break;
5758     case 0x3409:
5759       if (tag_size != 4)
5760         goto error;
5761       self->alpha_min_ref = GST_READ_UINT32_BE (tag_data);
5762       GST_DEBUG ("  alpha min ref = %u", self->alpha_min_ref);
5763       break;
5764     case 0x3405:
5765       if (tag_size != 1)
5766         goto error;
5767       self->scanning_direction = GST_READ_UINT8 (tag_data);
5768       GST_DEBUG ("  scanning direction = %u", self->scanning_direction);
5769       break;
5770     case 0x3401:{
5771       guint i, len;
5772 
5773       if (tag_size % 2 != 0 || tag_size > 16)
5774         goto error;
5775 
5776       i = 0;
5777       while (tag_data[i] != 0 && tag_data[i + 1] != 0 && i + 2 <= tag_size)
5778         i += 2;
5779       len = i / 2;
5780 
5781       self->n_pixel_layout = len;
5782       GST_DEBUG ("  number of pixel layouts = %u", len);
5783       if (len == 0)
5784         return TRUE;
5785 
5786       self->pixel_layout = g_malloc0 (16);
5787 
5788       for (i = 0; i < len; i++) {
5789         self->pixel_layout[2 * i] = tag_data[2 * i];
5790         self->pixel_layout[2 * i + 1] = tag_data[2 * i + 1];
5791         GST_DEBUG ("    pixel layout %u = %c : %u", i,
5792             (gchar) self->pixel_layout[2 * i], self->pixel_layout[2 * i + 1]);
5793       }
5794 
5795       break;
5796     }
5797     case 0x3403:
5798     case 0x3404:
5799       /* TODO: handle this */
5800       GST_WARNING ("  tag 0x%04x not implemented yet", tag);
5801       break;
5802     default:
5803       ret =
5804           MXF_METADATA_BASE_CLASS
5805           (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->handle_tag
5806           (metadata, primer, tag, tag_data, tag_size);
5807       break;
5808   }
5809 
5810   return ret;
5811 
5812 error:
5813 
5814   GST_ERROR
5815       ("Invalid RGBA picture essence descriptor local tag 0x%04x of size %u",
5816       tag, tag_size);
5817 
5818   return FALSE;
5819 }
5820 
5821 static GstStructure *
mxf_metadata_rgba_picture_essence_descriptor_to_structure(MXFMetadataBase * m)5822 mxf_metadata_rgba_picture_essence_descriptor_to_structure (MXFMetadataBase * m)
5823 {
5824   GstStructure *ret =
5825       MXF_METADATA_BASE_CLASS
5826       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->to_structure
5827       (m);
5828   MXFMetadataRGBAPictureEssenceDescriptor *self =
5829       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (m);
5830 
5831   if (self->component_max_ref != 255)
5832     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_MAX_REF), G_TYPE_UINT,
5833         self->component_max_ref, NULL);
5834 
5835   if (self->component_min_ref != 0)
5836     gst_structure_id_set (ret, MXF_QUARK (COMPONENT_MIN_REF), G_TYPE_UINT,
5837         self->component_min_ref, NULL);
5838 
5839   if (self->alpha_max_ref != 255)
5840     gst_structure_id_set (ret, MXF_QUARK (ALPHA_MAX_REF), G_TYPE_UINT,
5841         self->alpha_max_ref, NULL);
5842 
5843   if (self->alpha_min_ref != 0)
5844     gst_structure_id_set (ret, MXF_QUARK (ALPHA_MIN_REF), G_TYPE_UINT,
5845         self->alpha_min_ref, NULL);
5846 
5847   if (self->scanning_direction != 0)
5848     gst_structure_id_set (ret, MXF_QUARK (SCANNING_DIRECTION), G_TYPE_UCHAR,
5849         self->scanning_direction, NULL);
5850 
5851   if (self->n_pixel_layout != 0) {
5852     gchar *pl = g_new0 (gchar, self->n_pixel_layout * 2 + 1);
5853 
5854     memcpy (pl, self->pixel_layout, self->n_pixel_layout * 2);
5855 
5856     gst_structure_id_set (ret, MXF_QUARK (PIXEL_LAYOUT), G_TYPE_STRING, pl,
5857         NULL);
5858 
5859     g_free (pl);
5860   }
5861 
5862   return ret;
5863 }
5864 
5865 static GList *
mxf_metadata_rgba_picture_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)5866 mxf_metadata_rgba_picture_essence_descriptor_write_tags (MXFMetadataBase * m,
5867     MXFPrimerPack * primer)
5868 {
5869   MXFMetadataRGBAPictureEssenceDescriptor *self =
5870       MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR (m);
5871   GList *ret =
5872       MXF_METADATA_BASE_CLASS
5873       (mxf_metadata_rgba_picture_essence_descriptor_parent_class)->write_tags
5874       (m, primer);
5875   MXFLocalTag *t;
5876 
5877   if (self->component_max_ref != 255) {
5878     t = g_slice_new0 (MXFLocalTag);
5879     memcpy (&t->ul, MXF_UL (COMPONENT_MAX_REF), 16);
5880     t->size = 4;
5881     t->data = g_slice_alloc (t->size);
5882     t->g_slice = TRUE;
5883     GST_WRITE_UINT32_BE (t->data, self->component_max_ref);
5884     mxf_primer_pack_add_mapping (primer, 0x3406, &t->ul);
5885     ret = g_list_prepend (ret, t);
5886   }
5887 
5888   if (self->component_min_ref) {
5889     t = g_slice_new0 (MXFLocalTag);
5890     memcpy (&t->ul, MXF_UL (COMPONENT_MIN_REF), 16);
5891     t->size = 4;
5892     t->data = g_slice_alloc (t->size);
5893     t->g_slice = TRUE;
5894     GST_WRITE_UINT32_BE (t->data, self->component_min_ref);
5895     mxf_primer_pack_add_mapping (primer, 0x3407, &t->ul);
5896     ret = g_list_prepend (ret, t);
5897   }
5898 
5899   if (self->alpha_max_ref != 255) {
5900     t = g_slice_new0 (MXFLocalTag);
5901     memcpy (&t->ul, MXF_UL (ALPHA_MAX_REF), 16);
5902     t->size = 4;
5903     t->data = g_slice_alloc (t->size);
5904     t->g_slice = TRUE;
5905     GST_WRITE_UINT32_BE (t->data, self->alpha_max_ref);
5906     mxf_primer_pack_add_mapping (primer, 0x3408, &t->ul);
5907     ret = g_list_prepend (ret, t);
5908   }
5909 
5910   if (self->alpha_min_ref) {
5911     t = g_slice_new0 (MXFLocalTag);
5912     memcpy (&t->ul, MXF_UL (ALPHA_MIN_REF), 16);
5913     t->size = 4;
5914     t->data = g_slice_alloc (t->size);
5915     t->g_slice = TRUE;
5916     GST_WRITE_UINT32_BE (t->data, self->alpha_min_ref);
5917     mxf_primer_pack_add_mapping (primer, 0x3409, &t->ul);
5918     ret = g_list_prepend (ret, t);
5919   }
5920 
5921   if (self->scanning_direction) {
5922     t = g_slice_new0 (MXFLocalTag);
5923     memcpy (&t->ul, MXF_UL (SCANNING_DIRECTION), 16);
5924     t->size = 1;
5925     t->data = g_slice_alloc (t->size);
5926     t->g_slice = TRUE;
5927     GST_WRITE_UINT8 (t->data, self->scanning_direction);
5928     mxf_primer_pack_add_mapping (primer, 0x3405, &t->ul);
5929     ret = g_list_prepend (ret, t);
5930   }
5931 
5932   t = g_slice_new0 (MXFLocalTag);
5933   memcpy (&t->ul, MXF_UL (PIXEL_LAYOUT), 16);
5934   t->size = 16;
5935   t->data = g_slice_alloc0 (t->size);
5936   t->g_slice = TRUE;
5937   if (self->pixel_layout)
5938     memcpy (t->data, self->pixel_layout, self->n_pixel_layout * 2);
5939   mxf_primer_pack_add_mapping (primer, 0x3401, &t->ul);
5940   ret = g_list_prepend (ret, t);
5941 
5942   return ret;
5943 }
5944 
5945 static void
mxf_metadata_rgba_picture_essence_descriptor_init(MXFMetadataRGBAPictureEssenceDescriptor * self)5946     mxf_metadata_rgba_picture_essence_descriptor_init
5947     (MXFMetadataRGBAPictureEssenceDescriptor * self)
5948 {
5949   self->component_max_ref = 255;
5950   self->alpha_max_ref = 255;
5951 }
5952 
5953 static void
mxf_metadata_rgba_picture_essence_descriptor_class_init(MXFMetadataRGBAPictureEssenceDescriptorClass * klass)5954     mxf_metadata_rgba_picture_essence_descriptor_class_init
5955     (MXFMetadataRGBAPictureEssenceDescriptorClass * klass)
5956 {
5957   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
5958   GObjectClass *object_class = (GObjectClass *) klass;
5959   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
5960 
5961   object_class->finalize =
5962       mxf_metadata_rgba_picture_essence_descriptor_finalize;
5963   metadata_base_class->handle_tag =
5964       mxf_metadata_rgba_picture_essence_descriptor_handle_tag;
5965   metadata_base_class->name_quark = MXF_QUARK (RGBA_PICTURE_ESSENCE_DESCRIPTOR);
5966   metadata_base_class->to_structure =
5967       mxf_metadata_rgba_picture_essence_descriptor_to_structure;
5968   metadata_base_class->write_tags =
5969       mxf_metadata_rgba_picture_essence_descriptor_write_tags;
5970   metadata_class->type = 0x0129;
5971 }
5972 
5973 G_DEFINE_TYPE (MXFMetadataGenericDataEssenceDescriptor,
5974     mxf_metadata_generic_data_essence_descriptor,
5975     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
5976 
5977 static gboolean
mxf_metadata_generic_data_essence_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)5978 mxf_metadata_generic_data_essence_descriptor_handle_tag (MXFMetadataBase *
5979     metadata, MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
5980     guint tag_size)
5981 {
5982   MXFMetadataGenericDataEssenceDescriptor *self =
5983       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (metadata);
5984   gboolean ret = TRUE;
5985 #ifndef GST_DISABLE_GST_DEBUG
5986   gchar str[48];
5987 #endif
5988 
5989   switch (tag) {
5990     case 0x3e01:
5991       if (tag_size != 16)
5992         goto error;
5993       memcpy (&self->data_essence_coding, tag_data, 16);
5994       GST_DEBUG ("  data essence coding = %s",
5995           mxf_ul_to_string (&self->data_essence_coding, str));
5996       break;
5997     default:
5998       ret =
5999           MXF_METADATA_BASE_CLASS
6000           (mxf_metadata_generic_data_essence_descriptor_parent_class)->handle_tag
6001           (metadata, primer, tag, tag_data, tag_size);
6002       break;
6003   }
6004 
6005   return ret;
6006 
6007 error:
6008 
6009   GST_ERROR
6010       ("Invalid generic data essence descriptor local tag 0x%04x of size %u",
6011       tag, tag_size);
6012 
6013   return FALSE;
6014 }
6015 
6016 static GstStructure *
mxf_metadata_generic_data_essence_descriptor_to_structure(MXFMetadataBase * m)6017 mxf_metadata_generic_data_essence_descriptor_to_structure (MXFMetadataBase * m)
6018 {
6019   GstStructure *ret =
6020       MXF_METADATA_BASE_CLASS
6021       (mxf_metadata_generic_data_essence_descriptor_parent_class)->to_structure
6022       (m);
6023   MXFMetadataGenericDataEssenceDescriptor *self =
6024       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (m);
6025   gchar str[48];
6026 
6027   if (!mxf_ul_is_zero (&self->data_essence_coding)) {
6028     mxf_ul_to_string (&self->data_essence_coding, str);
6029     gst_structure_id_set (ret, MXF_QUARK (DATA_ESSENCE_CODING), G_TYPE_STRING,
6030         str, NULL);
6031   }
6032 
6033   return ret;
6034 }
6035 
6036 static GList *
mxf_metadata_generic_data_essence_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6037 mxf_metadata_generic_data_essence_descriptor_write_tags (MXFMetadataBase * m,
6038     MXFPrimerPack * primer)
6039 {
6040   MXFMetadataGenericDataEssenceDescriptor *self =
6041       MXF_METADATA_GENERIC_DATA_ESSENCE_DESCRIPTOR (m);
6042   GList *ret =
6043       MXF_METADATA_BASE_CLASS
6044       (mxf_metadata_generic_data_essence_descriptor_parent_class)->write_tags
6045       (m, primer);
6046   MXFLocalTag *t;
6047 
6048   if (!mxf_ul_is_zero (&self->data_essence_coding)) {
6049     t = g_slice_new0 (MXFLocalTag);
6050     memcpy (&t->ul, MXF_UL (DATA_ESSENCE_CODING), 16);
6051     t->size = 16;
6052     t->data = g_slice_alloc (t->size);
6053     t->g_slice = TRUE;
6054     memcpy (t->data, &self->data_essence_coding, 16);
6055     mxf_primer_pack_add_mapping (primer, 0x3e01, &t->ul);
6056     ret = g_list_prepend (ret, t);
6057   }
6058 
6059   return ret;
6060 }
6061 
6062 static void
mxf_metadata_generic_data_essence_descriptor_init(MXFMetadataGenericDataEssenceDescriptor * self)6063     mxf_metadata_generic_data_essence_descriptor_init
6064     (MXFMetadataGenericDataEssenceDescriptor * self)
6065 {
6066 
6067 }
6068 
6069 static void
mxf_metadata_generic_data_essence_descriptor_class_init(MXFMetadataGenericDataEssenceDescriptorClass * klass)6070     mxf_metadata_generic_data_essence_descriptor_class_init
6071     (MXFMetadataGenericDataEssenceDescriptorClass * klass)
6072 {
6073   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6074   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6075 
6076   metadata_base_class->handle_tag =
6077       mxf_metadata_generic_data_essence_descriptor_handle_tag;
6078   metadata_base_class->name_quark = MXF_QUARK (GENERIC_DATA_ESSENCE_DESCRIPTOR);
6079   metadata_base_class->to_structure =
6080       mxf_metadata_generic_data_essence_descriptor_to_structure;
6081   metadata_base_class->write_tags =
6082       mxf_metadata_generic_data_essence_descriptor_write_tags;
6083   metadata_class->type = 0x0143;
6084 }
6085 
6086 G_DEFINE_TYPE (MXFMetadataMultipleDescriptor, mxf_metadata_multiple_descriptor,
6087     MXF_TYPE_METADATA_FILE_DESCRIPTOR);
6088 
6089 static void
mxf_metadata_multiple_descriptor_finalize(GObject * object)6090 mxf_metadata_multiple_descriptor_finalize (GObject * object)
6091 {
6092   MXFMetadataMultipleDescriptor *self =
6093       MXF_METADATA_MULTIPLE_DESCRIPTOR (object);
6094 
6095   g_free (self->sub_descriptors_uids);
6096   self->sub_descriptors_uids = NULL;
6097   g_free (self->sub_descriptors);
6098   self->sub_descriptors = NULL;
6099 
6100   G_OBJECT_CLASS
6101       (mxf_metadata_multiple_descriptor_parent_class)->finalize (object);
6102 }
6103 
6104 static gboolean
mxf_metadata_multiple_descriptor_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)6105 mxf_metadata_multiple_descriptor_handle_tag (MXFMetadataBase * metadata,
6106     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6107     guint tag_size)
6108 {
6109   MXFMetadataMultipleDescriptor *self =
6110       MXF_METADATA_MULTIPLE_DESCRIPTOR (metadata);
6111   gboolean ret = TRUE;
6112 #ifndef GST_DISABLE_GST_DEBUG
6113   gchar str[48];
6114 #endif
6115 
6116   switch (tag) {
6117     case 0x3f01:
6118       if (!mxf_uuid_array_parse (&self->sub_descriptors_uids,
6119               &self->n_sub_descriptors, tag_data, tag_size))
6120         goto error;
6121 
6122       GST_DEBUG ("  number of sub descriptors = %u", self->n_sub_descriptors);
6123 #ifndef GST_DISABLE_GST_DEBUG
6124       {
6125         guint i;
6126         for (i = 0; i < self->n_sub_descriptors; i++) {
6127           GST_DEBUG ("    sub descriptor %u = %s", i,
6128               mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
6129         }
6130       }
6131 #endif
6132 
6133       break;
6134     default:
6135       ret =
6136           MXF_METADATA_BASE_CLASS
6137           (mxf_metadata_multiple_descriptor_parent_class)->handle_tag (metadata,
6138           primer, tag, tag_data, tag_size);
6139       break;
6140   }
6141 
6142   return ret;
6143 
6144 error:
6145 
6146   GST_ERROR ("Invalid multiple descriptor local tag 0x%04x of size %u", tag,
6147       tag_size);
6148 
6149   return FALSE;
6150 }
6151 
6152 static gboolean
mxf_metadata_multiple_descriptor_resolve(MXFMetadataBase * m,GHashTable * metadata)6153 mxf_metadata_multiple_descriptor_resolve (MXFMetadataBase * m,
6154     GHashTable * metadata)
6155 {
6156   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6157   MXFMetadataBase *current = NULL;
6158   guint i, have_subdescriptors = 0;
6159 #ifndef GST_DISABLE_GST_DEBUG
6160   gchar str[48];
6161 #endif
6162 
6163   if (self->sub_descriptors)
6164     memset (self->sub_descriptors, 0,
6165         sizeof (gpointer) * self->n_sub_descriptors);
6166   else
6167     self->sub_descriptors =
6168         g_new0 (MXFMetadataGenericDescriptor *, self->n_sub_descriptors);
6169   for (i = 0; i < self->n_sub_descriptors; i++) {
6170     current = g_hash_table_lookup (metadata, &self->sub_descriptors_uids[i]);
6171     if (current && MXF_IS_METADATA_GENERIC_DESCRIPTOR (current)) {
6172       if (mxf_metadata_base_resolve (current, metadata)) {
6173         self->sub_descriptors[i] = MXF_METADATA_GENERIC_DESCRIPTOR (current);
6174         have_subdescriptors++;
6175       } else {
6176         GST_ERROR ("Couldn't resolve descriptor %s",
6177             mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
6178         return FALSE;
6179       }
6180     } else {
6181       GST_ERROR ("Descriptor %s not found",
6182           mxf_uuid_to_string (&self->sub_descriptors_uids[i], str));
6183     }
6184   }
6185 
6186   return
6187       MXF_METADATA_BASE_CLASS
6188       (mxf_metadata_multiple_descriptor_parent_class)->resolve (m, metadata);
6189 }
6190 
6191 static GstStructure *
mxf_metadata_multiple_descriptor_to_structure(MXFMetadataBase * m)6192 mxf_metadata_multiple_descriptor_to_structure (MXFMetadataBase * m)
6193 {
6194   GstStructure *ret =
6195       MXF_METADATA_BASE_CLASS
6196       (mxf_metadata_multiple_descriptor_parent_class)->to_structure (m);
6197   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6198   guint i;
6199 
6200   if (self->n_sub_descriptors > 0) {
6201     GValue arr = { 0, }
6202     , val = {
6203     0,};
6204 
6205     g_value_init (&arr, GST_TYPE_ARRAY);
6206 
6207     for (i = 0; i < self->n_sub_descriptors; i++) {
6208       GstStructure *s;
6209 
6210       if (self->sub_descriptors[i] == NULL)
6211         continue;
6212 
6213       g_value_init (&val, GST_TYPE_STRUCTURE);
6214 
6215       s = mxf_metadata_base_to_structure (MXF_METADATA_BASE
6216           (self->sub_descriptors[i]));
6217       gst_value_set_structure (&val, s);
6218       gst_structure_free (s);
6219       gst_value_array_append_value (&arr, &val);
6220       g_value_unset (&val);
6221     }
6222 
6223     if (gst_value_array_get_size (&arr) > 0)
6224       gst_structure_id_set_value (ret, MXF_QUARK (SUB_DESCRIPTORS), &arr);
6225 
6226     g_value_unset (&arr);
6227   }
6228 
6229   return ret;
6230 }
6231 
6232 static GList *
mxf_metadata_multiple_descriptor_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6233 mxf_metadata_multiple_descriptor_write_tags (MXFMetadataBase * m,
6234     MXFPrimerPack * primer)
6235 {
6236   MXFMetadataMultipleDescriptor *self = MXF_METADATA_MULTIPLE_DESCRIPTOR (m);
6237   GList *ret =
6238       MXF_METADATA_BASE_CLASS
6239       (mxf_metadata_multiple_descriptor_parent_class)->write_tags (m, primer);
6240   MXFLocalTag *t;
6241 
6242   if (self->sub_descriptors) {
6243     guint i;
6244 
6245     t = g_slice_new0 (MXFLocalTag);
6246     memcpy (&t->ul, MXF_UL (SUB_DESCRIPTORS), 16);
6247     t->size = 8 + 16 * self->n_sub_descriptors;
6248     t->data = g_slice_alloc0 (t->size);
6249     t->g_slice = TRUE;
6250     GST_WRITE_UINT32_BE (t->data, self->n_sub_descriptors);
6251     GST_WRITE_UINT32_BE (t->data + 4, 16);
6252     for (i = 0; i < self->n_sub_descriptors; i++) {
6253       if (!self->sub_descriptors[i])
6254         continue;
6255 
6256       memcpy (t->data + 8 + 16 * i,
6257           &MXF_METADATA_BASE (self->sub_descriptors[i])->instance_uid, 16);
6258     }
6259     mxf_primer_pack_add_mapping (primer, 0x3f01, &t->ul);
6260     ret = g_list_prepend (ret, t);
6261   }
6262 
6263   return ret;
6264 }
6265 
6266 static void
mxf_metadata_multiple_descriptor_init(MXFMetadataMultipleDescriptor * self)6267 mxf_metadata_multiple_descriptor_init (MXFMetadataMultipleDescriptor * self)
6268 {
6269 
6270 }
6271 
6272 static void
mxf_metadata_multiple_descriptor_class_init(MXFMetadataMultipleDescriptorClass * klass)6273 mxf_metadata_multiple_descriptor_class_init (MXFMetadataMultipleDescriptorClass
6274     * klass)
6275 {
6276   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6277   GObjectClass *object_class = (GObjectClass *) klass;
6278   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6279 
6280   object_class->finalize = mxf_metadata_multiple_descriptor_finalize;
6281   metadata_base_class->handle_tag = mxf_metadata_multiple_descriptor_handle_tag;
6282   metadata_base_class->resolve = mxf_metadata_multiple_descriptor_resolve;
6283   metadata_base_class->name_quark = MXF_QUARK (MULTIPLE_DESCRIPTOR);
6284   metadata_base_class->to_structure =
6285       mxf_metadata_multiple_descriptor_to_structure;
6286   metadata_base_class->write_tags = mxf_metadata_multiple_descriptor_write_tags;
6287   metadata_class->type = 0x0144;
6288 }
6289 
6290 G_DEFINE_ABSTRACT_TYPE (MXFMetadataLocator, mxf_metadata_locator,
6291     MXF_TYPE_METADATA);
6292 
6293 static void
mxf_metadata_locator_init(MXFMetadataLocator * self)6294 mxf_metadata_locator_init (MXFMetadataLocator * self)
6295 {
6296 }
6297 
6298 static void
mxf_metadata_locator_class_init(MXFMetadataLocatorClass * klass)6299 mxf_metadata_locator_class_init (MXFMetadataLocatorClass * klass)
6300 {
6301 }
6302 
6303 G_DEFINE_TYPE (MXFMetadataTextLocator, mxf_metadata_text_locator,
6304     MXF_TYPE_METADATA_LOCATOR);
6305 
6306 static void
mxf_metadata_text_locator_finalize(GObject * object)6307 mxf_metadata_text_locator_finalize (GObject * object)
6308 {
6309   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (object);
6310 
6311   g_free (self->locator_name);
6312   self->locator_name = NULL;
6313 
6314   G_OBJECT_CLASS (mxf_metadata_text_locator_parent_class)->finalize (object);
6315 }
6316 
6317 static gboolean
mxf_metadata_text_locator_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)6318 mxf_metadata_text_locator_handle_tag (MXFMetadataBase * metadata,
6319     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6320     guint tag_size)
6321 {
6322   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (metadata);
6323   gboolean ret = TRUE;
6324 
6325   switch (tag) {
6326     case 0x4101:
6327       self->locator_name = mxf_utf16_to_utf8 (tag_data, tag_size);
6328       GST_DEBUG ("  text locator = %s", GST_STR_NULL (self->locator_name));
6329       break;
6330     default:
6331       ret =
6332           MXF_METADATA_BASE_CLASS
6333           (mxf_metadata_text_locator_parent_class)->handle_tag (metadata,
6334           primer, tag, tag_data, tag_size);
6335       break;
6336   }
6337 
6338   return ret;
6339 }
6340 
6341 static GstStructure *
mxf_metadata_text_locator_to_structure(MXFMetadataBase * m)6342 mxf_metadata_text_locator_to_structure (MXFMetadataBase * m)
6343 {
6344   GstStructure *ret =
6345       MXF_METADATA_BASE_CLASS
6346       (mxf_metadata_text_locator_parent_class)->to_structure (m);
6347   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (m);
6348 
6349   gst_structure_id_set (ret, MXF_QUARK (LOCATOR_NAME), G_TYPE_STRING,
6350       self->locator_name, NULL);
6351 
6352   return ret;
6353 }
6354 
6355 static GList *
mxf_metadata_text_locator_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6356 mxf_metadata_text_locator_write_tags (MXFMetadataBase * m,
6357     MXFPrimerPack * primer)
6358 {
6359   MXFMetadataTextLocator *self = MXF_METADATA_TEXT_LOCATOR (m);
6360   GList *ret =
6361       MXF_METADATA_BASE_CLASS
6362       (mxf_metadata_text_locator_parent_class)->write_tags (m, primer);
6363   MXFLocalTag *t;
6364 
6365   if (self->locator_name) {
6366     t = g_slice_new0 (MXFLocalTag);
6367     memcpy (&t->ul, MXF_UL (LOCATOR_NAME), 16);
6368     t->data = mxf_utf8_to_utf16 (self->locator_name, &t->size);
6369     mxf_primer_pack_add_mapping (primer, 0x4101, &t->ul);
6370     ret = g_list_prepend (ret, t);
6371   }
6372 
6373   return ret;
6374 }
6375 
6376 static void
mxf_metadata_text_locator_init(MXFMetadataTextLocator * self)6377 mxf_metadata_text_locator_init (MXFMetadataTextLocator * self)
6378 {
6379 
6380 }
6381 
6382 static void
mxf_metadata_text_locator_class_init(MXFMetadataTextLocatorClass * klass)6383 mxf_metadata_text_locator_class_init (MXFMetadataTextLocatorClass * klass)
6384 {
6385   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6386   GObjectClass *object_class = (GObjectClass *) klass;
6387   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6388 
6389   object_class->finalize = mxf_metadata_text_locator_finalize;
6390   metadata_base_class->handle_tag = mxf_metadata_text_locator_handle_tag;
6391   metadata_base_class->name_quark = MXF_QUARK (TEXT_LOCATOR);
6392   metadata_base_class->to_structure = mxf_metadata_text_locator_to_structure;
6393   metadata_base_class->write_tags = mxf_metadata_text_locator_write_tags;
6394   metadata_class->type = 0x0133;
6395 }
6396 
6397 G_DEFINE_TYPE (MXFMetadataNetworkLocator, mxf_metadata_network_locator,
6398     MXF_TYPE_METADATA_LOCATOR);
6399 
6400 static void
mxf_metadata_network_locator_finalize(GObject * object)6401 mxf_metadata_network_locator_finalize (GObject * object)
6402 {
6403   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (object);
6404 
6405   g_free (self->url_string);
6406   self->url_string = NULL;
6407 
6408   G_OBJECT_CLASS (mxf_metadata_network_locator_parent_class)->finalize (object);
6409 }
6410 
6411 static gboolean
mxf_metadata_network_locator_handle_tag(MXFMetadataBase * metadata,MXFPrimerPack * primer,guint16 tag,const guint8 * tag_data,guint tag_size)6412 mxf_metadata_network_locator_handle_tag (MXFMetadataBase * metadata,
6413     MXFPrimerPack * primer, guint16 tag, const guint8 * tag_data,
6414     guint tag_size)
6415 {
6416   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (metadata);
6417   gboolean ret = TRUE;
6418 
6419   switch (tag) {
6420     case 0x4101:
6421       self->url_string = mxf_utf16_to_utf8 (tag_data, tag_size);
6422       GST_DEBUG ("  url string = %s", GST_STR_NULL (self->url_string));
6423       break;
6424     default:
6425       ret =
6426           MXF_METADATA_BASE_CLASS
6427           (mxf_metadata_network_locator_parent_class)->handle_tag (metadata,
6428           primer, tag, tag_data, tag_size);
6429       break;
6430   }
6431 
6432   return ret;
6433 }
6434 
6435 static GstStructure *
mxf_metadata_network_locator_to_structure(MXFMetadataBase * m)6436 mxf_metadata_network_locator_to_structure (MXFMetadataBase * m)
6437 {
6438   GstStructure *ret =
6439       MXF_METADATA_BASE_CLASS
6440       (mxf_metadata_network_locator_parent_class)->to_structure (m);
6441   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (m);
6442 
6443   gst_structure_id_set (ret, MXF_QUARK (URL_STRING), G_TYPE_STRING,
6444       self->url_string, NULL);
6445 
6446   return ret;
6447 }
6448 
6449 static GList *
mxf_metadata_network_locator_write_tags(MXFMetadataBase * m,MXFPrimerPack * primer)6450 mxf_metadata_network_locator_write_tags (MXFMetadataBase * m,
6451     MXFPrimerPack * primer)
6452 {
6453   MXFMetadataNetworkLocator *self = MXF_METADATA_NETWORK_LOCATOR (m);
6454   GList *ret =
6455       MXF_METADATA_BASE_CLASS
6456       (mxf_metadata_network_locator_parent_class)->write_tags (m, primer);
6457   MXFLocalTag *t;
6458 
6459   if (self->url_string) {
6460     t = g_slice_new0 (MXFLocalTag);
6461     memcpy (&t->ul, MXF_UL (URL_STRING), 16);
6462     t->data = mxf_utf8_to_utf16 (self->url_string, &t->size);
6463     mxf_primer_pack_add_mapping (primer, 0x4001, &t->ul);
6464     ret = g_list_prepend (ret, t);
6465   }
6466 
6467   return ret;
6468 }
6469 
6470 static void
mxf_metadata_network_locator_init(MXFMetadataNetworkLocator * self)6471 mxf_metadata_network_locator_init (MXFMetadataNetworkLocator * self)
6472 {
6473 }
6474 
6475 static void
mxf_metadata_network_locator_class_init(MXFMetadataNetworkLocatorClass * klass)6476 mxf_metadata_network_locator_class_init (MXFMetadataNetworkLocatorClass * klass)
6477 {
6478   MXFMetadataBaseClass *metadata_base_class = (MXFMetadataBaseClass *) klass;
6479   GObjectClass *object_class = (GObjectClass *) klass;
6480   MXFMetadataClass *metadata_class = (MXFMetadataClass *) klass;
6481 
6482   object_class->finalize = mxf_metadata_network_locator_finalize;
6483   metadata_base_class->handle_tag = mxf_metadata_network_locator_handle_tag;
6484   metadata_base_class->name_quark = MXF_QUARK (NETWORK_LOCATOR);
6485   metadata_base_class->to_structure = mxf_metadata_network_locator_to_structure;
6486   metadata_base_class->write_tags = mxf_metadata_network_locator_write_tags;
6487   metadata_class->type = 0x0133;
6488 }
6489 
6490 G_DEFINE_ABSTRACT_TYPE (MXFDescriptiveMetadata, mxf_descriptive_metadata,
6491     MXF_TYPE_METADATA_BASE);
6492 
6493 static void
mxf_descriptive_metadata_init(MXFDescriptiveMetadata * self)6494 mxf_descriptive_metadata_init (MXFDescriptiveMetadata * self)
6495 {
6496 }
6497 
6498 static void
mxf_descriptive_metadata_class_init(MXFDescriptiveMetadataClass * klass)6499 mxf_descriptive_metadata_class_init (MXFDescriptiveMetadataClass * klass)
6500 {
6501 }
6502 
6503 typedef struct
6504 {
6505   guint8 scheme;
6506   GType *types;
6507 } _MXFDescriptiveMetadataScheme;
6508 
6509 static GArray *_dm_schemes = NULL;
6510 
6511 void
mxf_descriptive_metadata_register(guint8 scheme,GType * types)6512 mxf_descriptive_metadata_register (guint8 scheme, GType * types)
6513 {
6514   _MXFDescriptiveMetadataScheme s;
6515 
6516   if (!_dm_schemes)
6517     _dm_schemes =
6518         g_array_new (FALSE, TRUE, sizeof (_MXFDescriptiveMetadataScheme));
6519 
6520   s.scheme = scheme;
6521   s.types = types;
6522 
6523   g_array_append_val (_dm_schemes, s);
6524 }
6525 
6526 MXFDescriptiveMetadata *
mxf_descriptive_metadata_new(guint8 scheme,guint32 type,MXFPrimerPack * primer,guint64 offset,const guint8 * data,guint size)6527 mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
6528     MXFPrimerPack * primer, guint64 offset, const guint8 * data, guint size)
6529 {
6530   guint i;
6531   GType t = G_TYPE_INVALID, *p;
6532   _MXFDescriptiveMetadataScheme *s = NULL;
6533   MXFDescriptiveMetadata *ret = NULL;
6534 
6535   g_return_val_if_fail (primer != NULL, NULL);
6536 
6537   if (G_UNLIKELY (type == 0)) {
6538     GST_WARNING ("Type 0 is invalid");
6539     return NULL;
6540   }
6541 
6542   for (i = 0; _dm_schemes && i < _dm_schemes->len; i++) {
6543     _MXFDescriptiveMetadataScheme *data =
6544         &g_array_index (_dm_schemes, _MXFDescriptiveMetadataScheme, i);
6545 
6546     if (data->scheme == scheme) {
6547       s = data;
6548       break;
6549     }
6550   }
6551 
6552   if (s == NULL) {
6553     GST_WARNING ("Descriptive metadata scheme 0x%02x not supported", scheme);
6554     return NULL;
6555   }
6556 
6557   p = s->types;
6558   while (*p) {
6559     GType tmp = *p;
6560     MXFDescriptiveMetadataClass *klass =
6561         MXF_DESCRIPTIVE_METADATA_CLASS (g_type_class_ref (tmp));
6562 
6563     if (klass->type == type) {
6564       g_type_class_unref (klass);
6565       t = tmp;
6566       break;
6567     }
6568     g_type_class_unref (klass);
6569     p++;
6570   }
6571 
6572   if (t == G_TYPE_INVALID) {
6573     GST_WARNING
6574         ("No handler for type 0x%06x of descriptive metadata scheme 0x%02x found",
6575         type, scheme);
6576     return NULL;
6577   }
6578 
6579   GST_DEBUG ("DM scheme 0x%02x type 0x%06x is handled by type %s", scheme, type,
6580       g_type_name (t));
6581 
6582   ret = (MXFDescriptiveMetadata *) g_type_create_instance (t);
6583   if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) {
6584     GST_ERROR ("Parsing metadata failed");
6585     g_object_unref (ret);
6586     return NULL;
6587   }
6588 
6589   ret->parent.offset = offset;
6590 
6591   return ret;
6592 }
6593 
6594 GType
mxf_descriptive_metadata_framework_get_type(void)6595 mxf_descriptive_metadata_framework_get_type (void)
6596 {
6597   static gsize type = 0;
6598   if (g_once_init_enter (&type)) {
6599     GType _type = 0;
6600     static const GTypeInfo info = {
6601       sizeof (MXFDescriptiveMetadataFrameworkInterface),
6602       NULL,                     /* base_init */
6603       NULL,                     /* base_finalize */
6604       NULL,                     /* class_init */
6605       NULL,                     /* class_finalize */
6606       NULL,                     /* class_data */
6607       0,                        /* instance_size */
6608       0,                        /* n_preallocs */
6609       NULL                      /* instance_init */
6610     };
6611     _type = g_type_register_static (G_TYPE_INTERFACE,
6612         "MXFDescriptiveMetadataFrameworkInterface", &info, 0);
6613 
6614     g_type_interface_add_prerequisite (_type, MXF_TYPE_DESCRIPTIVE_METADATA);
6615 
6616     g_once_init_leave (&type, (gsize) _type);
6617   }
6618 
6619   return (GType) type;
6620 }
6621 
6622 GHashTable *
mxf_metadata_hash_table_new(void)6623 mxf_metadata_hash_table_new (void)
6624 {
6625   return g_hash_table_new_full ((GHashFunc) mxf_uuid_hash,
6626       (GEqualFunc) mxf_uuid_is_equal, (GDestroyNotify) NULL,
6627       (GDestroyNotify) g_object_unref);
6628 }
6629