2
* Copyright (C) 2008-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
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.
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.
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., 59 Temple Place - Suite 330,
17
* Boston, MA 02111-1307, USA.
29
GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
30
#define GST_CAT_DEFAULT mxf_debug
33
mxf_is_mxf_packet (const MXFUL * ul)
35
return mxf_ul_is_subclass (MXF_UL (SMPTE), ul);
38
/* SMPTE 377M 6.1: Check if this is a valid partition pack */
40
mxf_is_partition_pack (const MXFUL * ul)
42
if (mxf_ul_is_subclass (MXF_UL (PARTITION_PACK), ul) &&
43
ul->u[13] >= 0x02 && ul->u[13] <= 0x04 &&
44
ul->u[14] < 0x05 && ul->u[15] == 0x00)
50
/* SMPTE 377M 6.2: header partition pack has byte 14 == 0x02 */
52
mxf_is_header_partition_pack (const MXFUL * ul)
54
if (mxf_is_partition_pack (ul) && ul->u[13] == 0x02)
60
/* SMPTE 377M 6.3: body partition pack has byte 14 == 0x03 */
62
mxf_is_body_partition_pack (const MXFUL * ul)
64
if (mxf_is_partition_pack (ul) && ul->u[13] == 0x03)
70
/* SMPTE 377M 6.4: footer partition pack has byte 14 == 0x04 */
72
mxf_is_footer_partition_pack (const MXFUL * ul)
74
if (mxf_is_partition_pack (ul) && ul->u[13] == 0x04)
81
mxf_is_fill (const MXFUL * ul)
83
return (mxf_ul_is_subclass (MXF_UL (FILL), ul));
87
mxf_is_primer_pack (const MXFUL * ul)
89
return (mxf_ul_is_subclass (MXF_UL (PRIMER_PACK), ul));
93
mxf_is_metadata (const MXFUL * ul)
95
return (mxf_ul_is_subclass (MXF_UL (METADATA), ul));
98
/* SMPTE 377M 8.7.3 */
100
mxf_is_descriptive_metadata (const MXFUL * ul)
102
return (mxf_ul_is_subclass (MXF_UL (DESCRIPTIVE_METADATA), ul));
106
mxf_is_random_index_pack (const MXFUL * ul)
108
return (mxf_ul_is_subclass (MXF_UL (RANDOM_INDEX_PACK), ul));
112
mxf_is_index_table_segment (const MXFUL * ul)
114
return (mxf_ul_is_subclass (MXF_UL (INDEX_TABLE_SEGMENT), ul));
117
/* SMPTE 379M 6.2.1 */
119
mxf_is_generic_container_system_item (const MXFUL * ul)
121
return (mxf_ul_is_subclass (MXF_UL (GENERIC_CONTAINER_SYSTEM_ITEM), ul) &&
122
(ul->u[12] == 0x04 || ul->u[12] == 0x14));
127
mxf_is_generic_container_essence_element (const MXFUL * ul)
129
return (mxf_ul_is_subclass (MXF_UL (GENERIC_CONTAINER_ESSENCE_ELEMENT), ul)
130
&& (ul->u[12] == 0x05 || ul->u[12] == 0x06
131
|| ul->u[12] == 0x07 || ul->u[12] == 0x15
132
|| ul->u[12] == 0x16 || ul->u[12] == 0x17 || ul->u[12] == 0x18));
137
mxf_is_generic_container_essence_container_label (const MXFUL * ul)
139
return (mxf_ul_is_subclass (MXF_UL
140
(GENERIC_CONTAINER_ESSENCE_CONTAINER_LABEL), ul) && (ul->u[12] == 0x01
141
|| ul->u[12] == 0x02));
144
/* Essence container label found in files generated by Avid */
146
mxf_is_avid_essence_container_label (const MXFUL * ul)
148
return (mxf_ul_is_subclass (MXF_UL (AVID_ESSENCE_CONTAINER_ESSENCE_LABEL),
152
/* Essence element key found in files generated by Avid */
154
mxf_is_avid_essence_container_essence_element (const MXFUL * ul)
156
return (mxf_ul_is_subclass (MXF_UL (AVID_ESSENCE_CONTAINER_ESSENCE_ELEMENT),
161
mxf_ber_encode_size (guint size, guint8 ber[9])
171
} else if (size > G_MAXUINT) {
177
tmp[slen] = size & 0xff;
182
ber[0] = 0x80 | slen;
183
for (i = 0; i < slen; i++) {
184
ber[i + 1] = tmp[slen - i - 1];
191
mxf_fill_to_buffer (guint size)
197
slen = mxf_ber_encode_size (size, ber);
199
ret = gst_buffer_new_and_alloc (16 + slen + size);
200
memcpy (GST_BUFFER_DATA (ret), MXF_UL (FILL), 16);
201
memcpy (GST_BUFFER_DATA (ret) + 16, &ber, slen);
202
memset (GST_BUFFER_DATA (ret) + slen, 0, size);
208
mxf_uuid_init (MXFUUID * uuid, GHashTable * hashtable)
213
for (i = 0; i < 4; i++)
214
GST_WRITE_UINT32_BE (&uuid->u[i * 4], g_random_int ());
216
} while (hashtable && (mxf_uuid_is_zero (uuid) ||
217
g_hash_table_lookup_extended (hashtable, uuid, NULL, NULL)));
221
mxf_uuid_is_equal (const MXFUUID * a, const MXFUUID * b)
223
g_return_val_if_fail (a != NULL, FALSE);
224
g_return_val_if_fail (b != NULL, FALSE);
226
return (memcmp (a, b, 16) == 0);
230
mxf_uuid_is_zero (const MXFUUID * a)
232
static const guint8 zero[16] = { 0x00, };
234
g_return_val_if_fail (a != NULL, FALSE);
236
return (memcmp (a, zero, 16) == 0);
240
mxf_uuid_hash (const MXFUUID * uuid)
245
g_return_val_if_fail (uuid != NULL, 0);
247
for (i = 0; i < 4; i++)
248
ret ^= (uuid->u[i * 4 + 0] << 24) |
249
(uuid->u[i * 4 + 1] << 16) |
250
(uuid->u[i * 4 + 2] << 8) | (uuid->u[i * 4 + 3] << 0);
256
mxf_uuid_to_string (const MXFUUID * uuid, gchar str[48])
260
g_return_val_if_fail (uuid != NULL, NULL);
266
"%02x.%02x.%02x.%02x."
267
"%02x.%02x.%02x.%02x."
268
"%02x.%02x.%02x.%02x."
269
"%02x.%02x.%02x.%02x",
270
uuid->u[0], uuid->u[1], uuid->u[2], uuid->u[3],
271
uuid->u[4], uuid->u[5], uuid->u[6], uuid->u[7],
272
uuid->u[8], uuid->u[9], uuid->u[10], uuid->u[11],
273
uuid->u[12], uuid->u[13], uuid->u[14], uuid->u[15]);
279
mxf_uuid_from_string (const gchar * str, MXFUUID * uuid)
285
g_return_val_if_fail (str != NULL, NULL);
289
GST_ERROR ("Invalid UUID string length %d, should be 47", len);
294
ret = g_new0 (MXFUUID, 1);
298
for (i = 0, j = 0; i < 16; i++) {
299
if (!g_ascii_isxdigit (str[j]) ||
300
!g_ascii_isxdigit (str[j + 1]) ||
301
(str[j + 2] != '.' && str[j + 2] != '\0')) {
302
GST_ERROR ("Invalid UL string '%s'", str);
308
ret->u[i] = (g_ascii_xdigit_value (str[j]) << 4) |
309
(g_ascii_xdigit_value (str[j + 1]));
316
mxf_uuid_array_parse (MXFUUID ** array, guint32 * count, const guint8 * data,
319
guint32 element_count, element_size;
322
g_return_val_if_fail (array != NULL, FALSE);
323
g_return_val_if_fail (count != NULL, FALSE);
324
g_return_val_if_fail (data != NULL, FALSE);
329
element_count = GST_READ_UINT32_BE (data);
333
if (element_count == 0) {
339
element_size = GST_READ_UINT32_BE (data);
343
if (element_size != 16) {
349
if (16 * element_count < size) {
355
*array = g_new (MXFUUID, element_count);
356
*count = element_count;
358
for (i = 0; i < element_count; i++) {
359
memcpy (&((*array)[i]), data, 16);
367
mxf_umid_is_equal (const MXFUMID * a, const MXFUMID * b)
369
return (memcmp (a, b, 32) == 0);
373
mxf_umid_is_zero (const MXFUMID * umid)
375
static const MXFUMID zero = { {0,} };
377
return (memcmp (umid, &zero, 32) == 0);
381
mxf_umid_to_string (const MXFUMID * umid, gchar str[96])
383
g_return_val_if_fail (umid != NULL, NULL);
384
g_return_val_if_fail (str != NULL, NULL);
387
"%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x."
388
"%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
389
umid->u[0], umid->u[1], umid->u[2], umid->u[3], umid->u[4], umid->u[5],
390
umid->u[6], umid->u[7], umid->u[8], umid->u[9], umid->u[10], umid->u[11],
391
umid->u[12], umid->u[13], umid->u[14], umid->u[15],
402
umid->u[26], umid->u[27], umid->u[28], umid->u[29], umid->u[30],
410
mxf_umid_from_string (const gchar * str, MXFUMID * umid)
415
g_return_val_if_fail (str != NULL, NULL);
418
memset (umid, 0, 32);
421
GST_ERROR ("Invalid UMID string length %d", len);
425
for (i = 0, j = 0; i < 32; i++) {
426
if (!g_ascii_isxdigit (str[j]) ||
427
!g_ascii_isxdigit (str[j + 1]) ||
428
(str[j + 2] != '.' && str[j + 2] != '\0')) {
429
GST_ERROR ("Invalid UMID string '%s'", str);
434
(g_ascii_xdigit_value (str[j]) << 4) | (g_ascii_xdigit_value (str[j +
442
mxf_umid_init (MXFUMID * umid)
447
/* SMPTE S330M 5.1.1:
457
umid->u[7] = 0x05; /* version, see RP210 */
460
umid->u[10] = 0x0d; /* mixed group of components in a single container */
462
/* - UUID/UL method for material number
463
* - 24 bit PRG for instance number
465
umid->u[11] = 0x20 | 0x02;
467
/* Length of remaining data */
470
/* Instance number */
471
tmp = g_random_int ();
472
umid->u[13] = (tmp >> 24) & 0xff;
473
umid->u[14] = (tmp >> 16) & 0xff;
474
umid->u[15] = (tmp >> 8) & 0xff;
476
/* Material number: ISO UUID Version 4 */
477
for (i = 16; i < 32; i += 4)
478
GST_WRITE_UINT32_BE (&umid->u[i], g_random_int ());
480
umid->u[16 + 6] &= 0x0f;
481
umid->u[16 + 6] |= 0x40;
483
umid->u[16 + 8] &= 0x3f;
484
umid->u[16 + 8] |= 0x80;
488
mxf_timestamp_parse (MXFTimestamp * timestamp, const guint8 * data, guint size)
490
g_return_val_if_fail (data != NULL, FALSE);
491
g_return_val_if_fail (timestamp != NULL, FALSE);
493
memset (timestamp, 0, sizeof (MXFTimestamp));
498
timestamp->year = GST_READ_UINT16_BE (data);
499
timestamp->month = GST_READ_UINT8 (data + 2);
500
timestamp->day = GST_READ_UINT8 (data + 3);
501
timestamp->hour = GST_READ_UINT8 (data + 4);
502
timestamp->minute = GST_READ_UINT8 (data + 5);
503
timestamp->second = GST_READ_UINT8 (data + 6);
504
timestamp->msecond = (GST_READ_UINT8 (data + 7) * 1000) / 256;
509
/* SMPTE 377M 3.3: A value of 0 for every field means unknown timestamp */
511
mxf_timestamp_is_unknown (const MXFTimestamp * a)
513
static const MXFTimestamp unknown = { 0, 0, 0, 0, 0, 0, 0 };
515
return (memcmp (a, &unknown, sizeof (MXFTimestamp)) == 0);
519
mxf_timestamp_compare (const MXFTimestamp * a, const MXFTimestamp * b)
523
if ((diff = a->year - b->year) != 0)
525
else if ((diff = a->month - b->month) != 0)
527
else if ((diff = a->day - b->day) != 0)
529
else if ((diff = a->hour - b->hour) != 0)
531
else if ((diff = a->minute - b->minute) != 0)
533
else if ((diff = a->second - b->second) != 0)
535
else if ((diff = a->msecond - b->msecond) != 0)
542
mxf_timestamp_to_string (const MXFTimestamp * t, gchar str[32])
545
"%04d-%02u-%02u %02u:%02u:%02u.%03u", t->year, t->month,
546
t->day, t->hour, t->minute, t->second, t->msecond);
551
mxf_timestamp_set_now (MXFTimestamp * timestamp)
561
g_get_current_time (&tv);
562
t = (time_t) tv.tv_sec;
565
tm = gmtime_r (&t, &tm_);
570
timestamp->year = tm->tm_year + 1900;
571
timestamp->month = tm->tm_mon;
572
timestamp->day = tm->tm_mday;
573
timestamp->hour = tm->tm_hour;
574
timestamp->minute = tm->tm_min;
575
timestamp->second = tm->tm_sec;
576
timestamp->msecond = tv.tv_usec / 1000;
580
mxf_timestamp_write (const MXFTimestamp * timestamp, guint8 * data)
582
GST_WRITE_UINT16_BE (data, timestamp->year);
583
GST_WRITE_UINT8 (data + 2, timestamp->month);
584
GST_WRITE_UINT8 (data + 3, timestamp->day);
585
GST_WRITE_UINT8 (data + 4, timestamp->hour);
586
GST_WRITE_UINT8 (data + 5, timestamp->minute);
587
GST_WRITE_UINT8 (data + 6, timestamp->second);
588
GST_WRITE_UINT8 (data + 7, (timestamp->msecond * 256) / 1000);
592
mxf_fraction_parse (MXFFraction * fraction, const guint8 * data, guint size)
594
g_return_val_if_fail (fraction != NULL, FALSE);
595
g_return_val_if_fail (data != NULL, FALSE);
597
memset (fraction, 0, sizeof (MXFFraction));
602
fraction->n = GST_READ_UINT32_BE (data);
603
fraction->d = GST_READ_UINT32_BE (data + 4);
609
mxf_fraction_to_double (const MXFFraction * fraction)
611
return ((gdouble) fraction->n) / ((gdouble) fraction->d);
615
mxf_utf16_to_utf8 (const guint8 * data, guint size)
618
GError *error = NULL;
621
g_convert ((const gchar *) data, size, "UTF-8", "UTF-16BE", NULL, NULL,
625
GST_WARNING ("UTF-16-BE to UTF-8 conversion failed: %s", error->message);
626
g_error_free (error);
634
mxf_utf8_to_utf16 (const gchar * str, guint16 * size)
637
GError *error = NULL;
640
g_return_val_if_fail (size != NULL, NULL);
648
g_convert_with_fallback (str, -1, "UTF-16BE", "UTF-8", "*", NULL, &s,
652
GST_WARNING ("UTF-16-BE to UTF-8 conversion failed: %s", error->message);
653
g_error_free (error);
659
return (guint8 *) ret;
663
mxf_product_version_parse (MXFProductVersion * product_version,
664
const guint8 * data, guint size)
666
g_return_val_if_fail (product_version != NULL, FALSE);
667
g_return_val_if_fail (data != NULL, FALSE);
669
memset (product_version, 0, sizeof (MXFProductVersion));
674
product_version->major = GST_READ_UINT16_BE (data);
675
product_version->minor = GST_READ_UINT16_BE (data + 2);
676
product_version->patch = GST_READ_UINT16_BE (data + 4);
677
product_version->build = GST_READ_UINT16_BE (data + 6);
679
/* Avid writes a 9 byte product version */
681
product_version->release = GST_READ_UINT8 (data + 8);
683
product_version->release = GST_READ_UINT16_BE (data + 8);
689
mxf_product_version_is_valid (const MXFProductVersion * version)
691
static const guint8 null[sizeof (MXFProductVersion)] = { 0, };
693
return (memcmp (version, &null, sizeof (MXFProductVersion)) == 0);
697
mxf_product_version_write (const MXFProductVersion * version, guint8 * data)
699
GST_WRITE_UINT16_BE (data, version->major);
700
GST_WRITE_UINT16_BE (data + 2, version->minor);
701
GST_WRITE_UINT16_BE (data + 4, version->patch);
702
GST_WRITE_UINT16_BE (data + 6, version->build);
703
GST_WRITE_UINT16_BE (data + 8, version->release);
707
mxf_op_set_atom (MXFUL * ul, gboolean single_sourceclip,
708
gboolean single_essence_track)
710
memcpy (&ul->u, MXF_UL (OPERATIONAL_PATTERN_IDENTIFICATION), 12);
714
if (!single_sourceclip)
717
if (!single_essence_track)
725
mxf_op_set_generalized (MXFUL * ul, MXFOperationalPattern pattern,
726
gboolean internal_essence, gboolean streamable, gboolean single_track)
728
g_return_if_fail (pattern >= MXF_OP_1a);
730
memcpy (&ul->u, MXF_UL (OPERATIONAL_PATTERN_IDENTIFICATION), 12);
732
if (pattern == MXF_OP_1a || pattern == MXF_OP_1b || pattern == MXF_OP_1c)
734
else if (pattern == MXF_OP_2a || pattern == MXF_OP_2b || pattern == MXF_OP_2c)
736
else if (pattern == MXF_OP_3a || pattern == MXF_OP_3b || pattern == MXF_OP_3c)
739
if (pattern == MXF_OP_1a || pattern == MXF_OP_2a || pattern == MXF_OP_3a)
741
else if (pattern == MXF_OP_1b || pattern == MXF_OP_2b || pattern == MXF_OP_3b)
743
else if (pattern == MXF_OP_1c || pattern == MXF_OP_2c || pattern == MXF_OP_3c)
747
if (!internal_essence)
757
/* SMPTE 377M 6.1, Table 2 */
759
mxf_partition_pack_parse (const MXFUL * ul, MXFPartitionPack * pack,
760
const guint8 * data, guint size)
762
#ifndef GST_DISABLE_GST_DEBUG
767
g_return_val_if_fail (data != NULL, FALSE);
768
g_return_val_if_fail (size >= 84, FALSE);
770
memset (pack, 0, sizeof (MXFPartitionPack));
772
GST_DEBUG ("Parsing partition pack:");
774
if (ul->u[13] == 0x02)
775
pack->type = MXF_PARTITION_PACK_HEADER;
776
else if (ul->u[13] == 0x03)
777
pack->type = MXF_PARTITION_PACK_BODY;
778
else if (ul->u[13] == 0x04)
779
pack->type = MXF_PARTITION_PACK_FOOTER;
781
GST_DEBUG (" type = %s",
782
(pack->type == MXF_PARTITION_PACK_HEADER) ? "header" : (pack->type ==
783
MXF_PARTITION_PACK_BODY) ? "body" : "footer");
785
pack->closed = (ul->u[14] == 0x02 || ul->u[14] == 0x04);
786
pack->complete = (ul->u[14] == 0x03 || ul->u[14] == 0x04);
788
GST_DEBUG (" closed = %s, complete = %s", (pack->closed) ? "yes" : "no",
789
(pack->complete) ? "yes" : "no");
791
pack->major_version = GST_READ_UINT16_BE (data);
792
if (pack->major_version != 1)
797
pack->minor_version = GST_READ_UINT16_BE (data);
801
GST_DEBUG (" MXF version = %u.%u", pack->major_version, pack->minor_version);
803
pack->kag_size = GST_READ_UINT32_BE (data);
807
GST_DEBUG (" KAG size = %u", pack->kag_size);
809
pack->this_partition = GST_READ_UINT64_BE (data);
813
GST_DEBUG (" this partition offset = %" G_GUINT64_FORMAT,
814
pack->this_partition);
816
pack->prev_partition = GST_READ_UINT64_BE (data);
820
GST_DEBUG (" previous partition offset = %" G_GUINT64_FORMAT,
821
pack->prev_partition);
823
pack->footer_partition = GST_READ_UINT64_BE (data);
827
GST_DEBUG (" footer partition offset = %" G_GUINT64_FORMAT,
828
pack->footer_partition);
830
pack->header_byte_count = GST_READ_UINT64_BE (data);
834
GST_DEBUG (" header byte count = %" G_GUINT64_FORMAT,
835
pack->header_byte_count);
837
pack->index_byte_count = GST_READ_UINT64_BE (data);
841
pack->index_sid = GST_READ_UINT32_BE (data);
845
GST_DEBUG (" index sid = %u, size = %" G_GUINT64_FORMAT, pack->index_sid,
846
pack->index_byte_count);
848
pack->body_offset = GST_READ_UINT64_BE (data);
852
pack->body_sid = GST_READ_UINT32_BE (data);
856
GST_DEBUG (" body sid = %u, offset = %" G_GUINT64_FORMAT, pack->body_sid,
859
memcpy (&pack->operational_pattern, data, 16);
863
GST_DEBUG (" operational pattern = %s",
864
mxf_ul_to_string (&pack->operational_pattern, str));
866
if (!mxf_ul_array_parse (&pack->essence_containers,
867
&pack->n_essence_containers, data, size))
870
#ifndef GST_DISABLE_GST_DEBUG
871
GST_DEBUG (" number of essence containers = %u", pack->n_essence_containers);
872
if (pack->n_essence_containers) {
873
for (i = 0; i < pack->n_essence_containers; i++) {
874
GST_DEBUG (" essence container %u = %s", i,
875
mxf_ul_to_string (&pack->essence_containers[i], str));
883
GST_ERROR ("Invalid partition pack");
885
mxf_partition_pack_reset (pack);
890
mxf_partition_pack_reset (MXFPartitionPack * pack)
892
g_return_if_fail (pack != NULL);
894
g_free (pack->essence_containers);
896
memset (pack, 0, sizeof (MXFPartitionPack));
900
mxf_partition_pack_to_buffer (const MXFPartitionPack * pack)
908
8 + 16 * pack->n_essence_containers + 16 + 4 + 8 + 4 + 8 + 8 + 8 + 8 + 8 +
911
slen = mxf_ber_encode_size (size, ber);
913
ret = gst_buffer_new_and_alloc (16 + slen + size);
914
memcpy (GST_BUFFER_DATA (ret), MXF_UL (PARTITION_PACK), 13);
915
if (pack->type == MXF_PARTITION_PACK_HEADER)
916
GST_BUFFER_DATA (ret)[13] = 0x02;
917
else if (pack->type == MXF_PARTITION_PACK_BODY)
918
GST_BUFFER_DATA (ret)[13] = 0x03;
919
else if (pack->type == MXF_PARTITION_PACK_FOOTER)
920
GST_BUFFER_DATA (ret)[13] = 0x04;
921
GST_BUFFER_DATA (ret)[14] = 0;
923
GST_BUFFER_DATA (ret)[14] |= 0x02;
925
GST_BUFFER_DATA (ret)[14] |= 0x01;
926
GST_BUFFER_DATA (ret)[14] += 1;
927
GST_BUFFER_DATA (ret)[15] = 0;
928
memcpy (GST_BUFFER_DATA (ret) + 16, &ber, slen);
930
data = GST_BUFFER_DATA (ret) + 16 + slen;
932
GST_WRITE_UINT16_BE (data, pack->major_version);
933
GST_WRITE_UINT16_BE (data + 2, pack->minor_version);
936
GST_WRITE_UINT32_BE (data, pack->kag_size);
939
GST_WRITE_UINT64_BE (data, pack->this_partition);
942
GST_WRITE_UINT64_BE (data, pack->prev_partition);
945
GST_WRITE_UINT64_BE (data, pack->footer_partition);
948
GST_WRITE_UINT64_BE (data, pack->header_byte_count);
951
GST_WRITE_UINT64_BE (data, pack->index_byte_count);
954
GST_WRITE_UINT32_BE (data, pack->index_sid);
957
GST_WRITE_UINT64_BE (data, pack->body_offset);
960
GST_WRITE_UINT32_BE (data, pack->body_sid);
963
memcpy (data, &pack->operational_pattern, 16);
966
GST_WRITE_UINT32_BE (data, pack->n_essence_containers);
967
GST_WRITE_UINT32_BE (data + 4, 16);
970
for (i = 0; i < pack->n_essence_containers; i++)
971
memcpy (data + 16 * i, &pack->essence_containers[i], 16);
976
/* SMPTE 377M 11.1 */
978
mxf_random_index_pack_parse (const MXFUL * ul, const guint8 * data, guint size,
982
MXFRandomIndexPackEntry entry;
984
g_return_val_if_fail (data != NULL, FALSE);
985
g_return_val_if_fail (array != NULL, FALSE);
990
if ((size - 4) % 12 != 0)
993
GST_DEBUG ("Parsing random index pack:");
995
len = (size - 4) / 12;
997
GST_DEBUG (" number of entries = %u", len);
1000
g_array_sized_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry), len);
1002
for (i = 0; i < len; i++) {
1003
entry.body_sid = GST_READ_UINT32_BE (data);
1004
entry.offset = GST_READ_UINT64_BE (data + 4);
1007
GST_DEBUG (" entry %u = body sid %u at offset %" G_GUINT64_FORMAT, i,
1008
entry.body_sid, entry.offset);
1010
g_array_append_val (*array, entry);
1017
mxf_random_index_pack_to_buffer (const GArray * array)
1019
MXFRandomIndexPackEntry *entry;
1022
guint8 slen, ber[9];
1026
if (array->len == 0)
1029
size = array->len * 12 + 4;
1030
slen = mxf_ber_encode_size (size, ber);
1031
ret = gst_buffer_new_and_alloc (16 + slen + size);
1032
memcpy (GST_BUFFER_DATA (ret), MXF_UL (RANDOM_INDEX_PACK), 16);
1033
memcpy (GST_BUFFER_DATA (ret) + 16, ber, slen);
1035
data = GST_BUFFER_DATA (ret) + 16 + slen;
1037
for (i = 0; i < array->len; i++) {
1038
entry = &g_array_index (array, MXFRandomIndexPackEntry, i);
1039
GST_WRITE_UINT32_BE (data, entry->body_sid);
1040
GST_WRITE_UINT64_BE (data + 4, entry->offset);
1043
GST_WRITE_UINT32_BE (data, GST_BUFFER_SIZE (ret));
1048
/* SMPTE 377M 10.2.3 */
1050
mxf_index_table_segment_parse (const MXFUL * ul,
1051
MXFIndexTableSegment * segment, const MXFPrimerPack * primer,
1052
const guint8 * data, guint size)
1054
#ifndef GST_DISABLE_GST_DEBUG
1057
guint16 tag, tag_size;
1058
const guint8 *tag_data;
1060
g_return_val_if_fail (ul != NULL, FALSE);
1061
g_return_val_if_fail (data != NULL, FALSE);
1062
g_return_val_if_fail (primer != NULL, FALSE);
1064
memset (segment, 0, sizeof (MXFIndexTableSegment));
1069
GST_DEBUG ("Parsing index table segment:");
1071
while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
1072
if (tag_size == 0 || tag == 0x0000)
1079
memcpy (&segment->instance_id, tag_data, 16);
1080
GST_DEBUG (" instance id = %s",
1081
mxf_uuid_to_string (&segment->instance_id, str));
1084
if (!mxf_fraction_parse (&segment->index_edit_rate, tag_data, tag_size))
1086
GST_DEBUG (" index edit rate = %d/%d", segment->index_edit_rate.n,
1087
segment->index_edit_rate.d);
1092
segment->index_start_position = GST_READ_UINT64_BE (tag_data);
1093
GST_DEBUG (" index start position = %" G_GINT64_FORMAT,
1094
segment->index_start_position);
1099
segment->index_duration = GST_READ_UINT64_BE (tag_data);
1100
GST_DEBUG (" index duration = %" G_GINT64_FORMAT,
1101
segment->index_duration);
1106
segment->edit_unit_byte_count = GST_READ_UINT32_BE (tag_data);
1107
GST_DEBUG (" edit unit byte count = %u",
1108
segment->edit_unit_byte_count);
1113
segment->index_sid = GST_READ_UINT32_BE (tag_data);
1114
GST_DEBUG (" index sid = %u", segment->index_sid);
1119
segment->body_sid = GST_READ_UINT32_BE (tag_data);
1120
GST_DEBUG (" body sid = %u", segment->body_sid);
1125
segment->slice_count = GST_READ_UINT8 (tag_data);
1126
GST_DEBUG (" slice count = %u", segment->slice_count);
1131
segment->pos_table_count = GST_READ_UINT8 (tag_data);
1132
GST_DEBUG (" pos table count = %u", segment->pos_table_count);
1140
len = GST_READ_UINT32_BE (tag_data);
1141
segment->n_delta_entries = len;
1142
GST_DEBUG (" number of delta entries = %u", segment->n_delta_entries);
1148
if (GST_READ_UINT32_BE (tag_data) != 6)
1154
if (tag_size < len * 6)
1157
segment->delta_entries = g_new (MXFDeltaEntry, len);
1159
for (i = 0; i < len; i++) {
1160
GST_DEBUG (" delta entry %u:", i);
1162
segment->delta_entries[i].pos_table_index = GST_READ_UINT8 (tag_data);
1165
GST_DEBUG (" pos table index = %d",
1166
segment->delta_entries[i].pos_table_index);
1168
segment->delta_entries[i].slice = GST_READ_UINT8 (tag_data);
1171
GST_DEBUG (" slice = %u", segment->delta_entries[i].slice);
1173
segment->delta_entries[i].element_delta =
1174
GST_READ_UINT32_BE (tag_data);
1177
GST_DEBUG (" element delta = %u",
1178
segment->delta_entries[i].element_delta);
1188
len = GST_READ_UINT32_BE (tag_data);
1189
segment->n_index_entries = len;
1190
GST_DEBUG (" number of index entries = %u", segment->n_index_entries);
1196
if (GST_READ_UINT32_BE (tag_data) !=
1197
(11 + 4 * segment->slice_count + 8 * segment->pos_table_count))
1203
if (tag_size < len * 11)
1206
segment->index_entries = g_new0 (MXFIndexEntry, len);
1208
for (i = 0; i < len; i++) {
1209
MXFIndexEntry *entry = &segment->index_entries[i];
1211
GST_DEBUG (" index entry %u:", i);
1213
entry->temporal_offset = GST_READ_UINT8 (tag_data);
1216
GST_DEBUG (" temporal offset = %d", entry->temporal_offset);
1218
entry->key_frame_offset = GST_READ_UINT8 (tag_data);
1221
GST_DEBUG (" keyframe offset = %d", entry->key_frame_offset);
1223
entry->flags = GST_READ_UINT8 (tag_data);
1226
GST_DEBUG (" flags = 0x%02x", entry->flags);
1228
entry->stream_offset = GST_READ_UINT64_BE (tag_data);
1231
GST_DEBUG (" stream offset = %" G_GUINT64_FORMAT,
1232
entry->stream_offset);
1234
entry->slice_offset = g_new0 (guint32, segment->slice_count);
1235
for (j = 0; j < segment->slice_count; j++) {
1236
entry->slice_offset[j] = GST_READ_UINT32_BE (tag_data);
1239
GST_DEBUG (" slice %u offset = %u", j, entry->slice_offset[j]);
1242
entry->pos_table = g_new0 (MXFFraction, segment->pos_table_count);
1243
for (j = 0; j < segment->pos_table_count; j++) {
1244
mxf_fraction_parse (&entry->pos_table[j], tag_data, tag_size);
1247
GST_DEBUG (" pos table %u = %d/%d", j, entry->pos_table[j].n,
1248
entry->pos_table[j].d);
1254
if (!primer->mappings) {
1255
GST_WARNING ("No valid primer pack for this partition");
1256
} else if (!mxf_local_tag_add_to_hash_table (primer, tag, tag_data,
1257
tag_size, &segment->other_tags)) {
1264
data += 4 + tag_size;
1265
size -= 4 + tag_size;
1270
GST_ERROR ("Invalid index table segment");
1275
mxf_index_table_segment_reset (MXFIndexTableSegment * segment)
1279
g_return_if_fail (segment != NULL);
1281
for (i = 0; i < segment->n_index_entries; i++) {
1282
g_free (segment->index_entries[i].slice_offset);
1283
g_free (segment->index_entries[i].pos_table);
1286
g_free (segment->index_entries);
1287
g_free (segment->delta_entries);
1289
if (segment->other_tags)
1290
g_hash_table_destroy (segment->other_tags);
1292
memset (segment, 0, sizeof (MXFIndexTableSegment));
1295
/* SMPTE 377M 8.2 Table 1 and 2 */
1298
_mxf_mapping_ul_free (MXFUL * ul)
1300
g_slice_free (MXFUL, ul);
1304
mxf_primer_pack_parse (const MXFUL * ul, MXFPrimerPack * pack,
1305
const guint8 * data, guint size)
1310
g_return_val_if_fail (data != NULL, FALSE);
1311
g_return_val_if_fail (size >= 8, FALSE);
1313
memset (pack, 0, sizeof (MXFPrimerPack));
1315
GST_DEBUG ("Parsing primer pack:");
1318
g_hash_table_new_full (g_direct_hash, g_direct_equal,
1319
(GDestroyNotify) NULL, (GDestroyNotify) _mxf_mapping_ul_free);
1321
n = GST_READ_UINT32_BE (data);
1324
GST_DEBUG (" number of mappings = %u", n);
1326
if (GST_READ_UINT32_BE (data) != 18)
1330
if (size < 8 + n * 18)
1333
for (i = 0; i < n; i++) {
1335
#ifndef GST_DISABLE_GST_DEBUG
1340
local_tag = GST_READ_UINT16_BE (data);
1343
if (g_hash_table_lookup (pack->mappings, GUINT_TO_POINTER (local_tag)))
1346
uid = g_slice_new (MXFUL);
1347
memcpy (uid, data, 16);
1350
g_hash_table_insert (pack->mappings, GUINT_TO_POINTER (local_tag), uid);
1351
GST_DEBUG (" Adding mapping = 0x%04x -> %s", local_tag,
1352
mxf_ul_to_string (uid, str));
1358
GST_DEBUG ("Invalid primer pack");
1359
mxf_primer_pack_reset (pack);
1364
mxf_primer_pack_reset (MXFPrimerPack * pack)
1366
g_return_if_fail (pack != NULL);
1369
g_hash_table_destroy (pack->mappings);
1370
if (pack->reverse_mappings)
1371
g_hash_table_destroy (pack->reverse_mappings);
1373
memset (pack, 0, sizeof (MXFPrimerPack));
1375
pack->next_free_tag = 0x8000;
1379
mxf_primer_pack_add_mapping (MXFPrimerPack * primer, guint16 local_tag,
1383
#ifndef GST_DISABLE_GST_DEBUG
1386
guint ltag_tmp = local_tag;
1388
if (primer->mappings == NULL) {
1389
primer->mappings = g_hash_table_new_full (g_direct_hash, g_direct_equal,
1390
(GDestroyNotify) NULL, (GDestroyNotify) _mxf_mapping_ul_free);
1393
if (primer->reverse_mappings == NULL) {
1394
primer->reverse_mappings = g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
1395
(GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) _mxf_mapping_ul_free,
1396
(GDestroyNotify) NULL);
1399
if (primer->next_free_tag == 0xffff && ltag_tmp == 0) {
1400
GST_ERROR ("Used too many dynamic tags");
1404
if (ltag_tmp == 0) {
1407
tmp = GPOINTER_TO_UINT (g_hash_table_lookup (primer->reverse_mappings, ul));
1409
ltag_tmp = primer->next_free_tag;
1410
primer->next_free_tag++;
1413
if (g_hash_table_lookup (primer->mappings, GUINT_TO_POINTER (ltag_tmp)))
1417
g_assert (ltag_tmp != 0);
1419
uid = g_slice_new (MXFUL);
1420
memcpy (uid, ul, 16);
1422
GST_DEBUG ("Adding mapping = 0x%04x -> %s", ltag_tmp,
1423
mxf_ul_to_string (uid, str));
1424
g_hash_table_insert (primer->mappings, GUINT_TO_POINTER (ltag_tmp), uid);
1425
uid = g_slice_dup (MXFUL, uid);
1426
g_hash_table_insert (primer->reverse_mappings, uid,
1427
GUINT_TO_POINTER (ltag_tmp));
1433
mxf_primer_pack_to_buffer (const MXFPrimerPack * pack)
1442
n = g_hash_table_size (pack->mappings);
1446
slen = mxf_ber_encode_size (8 + 18 * n, ber);
1448
ret = gst_buffer_new_and_alloc (16 + slen + 8 + 18 * n);
1449
memcpy (GST_BUFFER_DATA (ret), MXF_UL (PRIMER_PACK), 16);
1450
memcpy (GST_BUFFER_DATA (ret) + 16, &ber, slen);
1452
data = GST_BUFFER_DATA (ret) + 16 + slen;
1454
GST_WRITE_UINT32_BE (data, n);
1455
GST_WRITE_UINT32_BE (data + 4, 18);
1458
if (pack->mappings) {
1461
#if GLIB_CHECK_VERSION (2, 16, 0)
1462
GHashTableIter iter;
1464
g_hash_table_iter_init (&iter, pack->mappings);
1468
keys = g_hash_table_get_keys (pack->mappings);
1471
#if GLIB_CHECK_VERSION (2, 16, 0)
1472
while (g_hash_table_iter_next (&iter, (gpointer) & local_tag,
1475
for (l = keys; l; l = l->next) {
1476
local_tag = GPOINTER_TO_UINT (l->data);
1477
ul = g_hash_table_lookup (pack->mappings, GUINT_TO_POINTER (local_tag));
1479
GST_WRITE_UINT16_BE (data, local_tag);
1480
memcpy (data + 2, ul, 16);
1484
#if !GLIB_CHECK_VERSION (2, 16, 0)
1492
/* structural metadata parsing */
1495
mxf_local_tag_parse (const guint8 * data, guint size, guint16 * tag,
1496
guint16 * tag_size, const guint8 ** tag_data)
1498
g_return_val_if_fail (data != NULL, FALSE);
1503
*tag = GST_READ_UINT16_BE (data);
1504
*tag_size = GST_READ_UINT16_BE (data + 2);
1506
if (size < 4 + *tag_size)
1509
*tag_data = data + 4;
1515
mxf_local_tag_free (MXFLocalTag * tag)
1518
g_slice_free1 (tag->size, tag->data);
1521
g_slice_free (MXFLocalTag, tag);
1525
mxf_local_tag_add_to_hash_table (const MXFPrimerPack * primer,
1526
guint16 tag, const guint8 * tag_data, guint16 tag_size,
1527
GHashTable ** hash_table)
1529
MXFLocalTag *local_tag;
1532
g_return_val_if_fail (primer != NULL, FALSE);
1533
g_return_val_if_fail (tag_data != NULL, FALSE);
1534
g_return_val_if_fail (hash_table != NULL, FALSE);
1535
g_return_val_if_fail (primer->mappings != NULL, FALSE);
1537
if (*hash_table == NULL)
1539
g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
1540
(GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) NULL,
1541
(GDestroyNotify) mxf_local_tag_free);
1543
g_return_val_if_fail (*hash_table != NULL, FALSE);
1545
ul = (MXFUL *) g_hash_table_lookup (primer->mappings,
1546
GUINT_TO_POINTER (((guint) tag)));
1549
#ifndef GST_DISABLE_GST_DEBUG
1553
GST_DEBUG ("Adding local tag 0x%04x with UL %s and size %u", tag,
1554
mxf_ul_to_string (ul, str), tag_size);
1556
local_tag = g_slice_new (MXFLocalTag);
1557
memcpy (&local_tag->ul, ul, sizeof (MXFUL));
1558
local_tag->size = tag_size;
1559
local_tag->data = g_memdup (tag_data, tag_size);
1561
g_hash_table_insert (*hash_table, &local_tag->ul, local_tag);
1563
GST_WARNING ("Local tag with no entry in primer pack: 0x%04x", tag);
1570
mxf_local_tag_insert (MXFLocalTag * tag, GHashTable ** hash_table)
1572
#ifndef GST_DISABLE_GST_DEBUG
1576
g_return_val_if_fail (tag != NULL, FALSE);
1577
g_return_val_if_fail (hash_table != NULL, FALSE);
1579
if (*hash_table == NULL)
1581
g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
1582
(GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) NULL,
1583
(GDestroyNotify) mxf_local_tag_free);
1585
g_return_val_if_fail (*hash_table != NULL, FALSE);
1587
GST_DEBUG ("Adding local tag with UL %s and size %u",
1588
mxf_ul_to_string (&tag->ul, str), tag->size);
1590
g_hash_table_insert (*hash_table, &tag->ul, tag);