~ubuntu-branches/ubuntu/precise/gst-plugins-bad0.10/precise-proposed

« back to all changes in this revision

Viewing changes to gst/mxf/mxftypes.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2009-05-12 09:51:24 UTC
  • mto: (18.3.2 experimental) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 31.
  • Revision ID: james.westby@ubuntu.com-20090512095124-ugy051q0n88kk9f8
Tags: upstream-0.10.11.2
Import upstream version 0.10.11.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, 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
 
 
29
GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
 
30
#define GST_CAT_DEFAULT mxf_debug
 
31
 
 
32
gboolean
 
33
mxf_is_mxf_packet (const MXFUL * ul)
 
34
{
 
35
  return mxf_ul_is_subclass (MXF_UL (SMPTE), ul);
 
36
}
 
37
 
 
38
/* SMPTE 377M 6.1: Check if this is a valid partition pack */
 
39
gboolean
 
40
mxf_is_partition_pack (const MXFUL * ul)
 
41
{
 
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)
 
45
    return TRUE;
 
46
 
 
47
  return FALSE;
 
48
}
 
49
 
 
50
/* SMPTE 377M 6.2: header partition pack has byte 14 == 0x02 */
 
51
gboolean
 
52
mxf_is_header_partition_pack (const MXFUL * ul)
 
53
{
 
54
  if (mxf_is_partition_pack (ul) && ul->u[13] == 0x02)
 
55
    return TRUE;
 
56
 
 
57
  return FALSE;
 
58
}
 
59
 
 
60
/* SMPTE 377M 6.3: body partition pack has byte 14 == 0x03 */
 
61
gboolean
 
62
mxf_is_body_partition_pack (const MXFUL * ul)
 
63
{
 
64
  if (mxf_is_partition_pack (ul) && ul->u[13] == 0x03)
 
65
    return TRUE;
 
66
 
 
67
  return FALSE;
 
68
}
 
69
 
 
70
/* SMPTE 377M 6.4: footer partition pack has byte 14 == 0x04 */
 
71
gboolean
 
72
mxf_is_footer_partition_pack (const MXFUL * ul)
 
73
{
 
74
  if (mxf_is_partition_pack (ul) && ul->u[13] == 0x04)
 
75
    return TRUE;
 
76
 
 
77
  return FALSE;
 
78
}
 
79
 
 
80
gboolean
 
81
mxf_is_fill (const MXFUL * ul)
 
82
{
 
83
  return (mxf_ul_is_subclass (MXF_UL (FILL), ul));
 
84
}
 
85
 
 
86
gboolean
 
87
mxf_is_primer_pack (const MXFUL * ul)
 
88
{
 
89
  return (mxf_ul_is_subclass (MXF_UL (PRIMER_PACK), ul));
 
90
}
 
91
 
 
92
gboolean
 
93
mxf_is_metadata (const MXFUL * ul)
 
94
{
 
95
  return (mxf_ul_is_subclass (MXF_UL (METADATA), ul));
 
96
}
 
97
 
 
98
/* SMPTE 377M 8.7.3 */
 
99
gboolean
 
100
mxf_is_descriptive_metadata (const MXFUL * ul)
 
101
{
 
102
  return (mxf_ul_is_subclass (MXF_UL (DESCRIPTIVE_METADATA), ul));
 
103
}
 
104
 
 
105
gboolean
 
106
mxf_is_random_index_pack (const MXFUL * ul)
 
107
{
 
108
  return (mxf_ul_is_subclass (MXF_UL (RANDOM_INDEX_PACK), ul));
 
109
}
 
110
 
 
111
gboolean
 
112
mxf_is_index_table_segment (const MXFUL * ul)
 
113
{
 
114
  return (mxf_ul_is_subclass (MXF_UL (INDEX_TABLE_SEGMENT), ul));
 
115
}
 
116
 
 
117
/* SMPTE 379M 6.2.1 */
 
118
gboolean
 
119
mxf_is_generic_container_system_item (const MXFUL * ul)
 
120
{
 
121
  return (mxf_ul_is_subclass (MXF_UL (GENERIC_CONTAINER_SYSTEM_ITEM), ul) &&
 
122
      (ul->u[12] == 0x04 || ul->u[12] == 0x14));
 
123
}
 
124
 
 
125
/* SMPTE 379M 7.1 */
 
126
gboolean
 
127
mxf_is_generic_container_essence_element (const MXFUL * ul)
 
128
{
 
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));
 
133
}
 
134
 
 
135
/* SMPTE 379M 8 */
 
136
gboolean
 
137
mxf_is_generic_container_essence_container_label (const MXFUL * ul)
 
138
{
 
139
  return (mxf_ul_is_subclass (MXF_UL
 
140
          (GENERIC_CONTAINER_ESSENCE_CONTAINER_LABEL), ul) && (ul->u[12] == 0x01
 
141
          || ul->u[12] == 0x02));
 
142
}
 
143
 
 
144
/* Essence container label found in files generated by Avid */
 
145
gboolean
 
146
mxf_is_avid_essence_container_label (const MXFUL * ul)
 
147
{
 
148
  return (mxf_ul_is_subclass (MXF_UL (AVID_ESSENCE_CONTAINER_ESSENCE_LABEL),
 
149
          ul));
 
150
}
 
151
 
 
152
/* Essence element key found in files generated by Avid */
 
153
gboolean
 
154
mxf_is_avid_essence_container_essence_element (const MXFUL * ul)
 
155
{
 
156
  return (mxf_ul_is_subclass (MXF_UL (AVID_ESSENCE_CONTAINER_ESSENCE_ELEMENT),
 
157
          ul));
 
158
}
 
159
 
 
160
guint
 
161
mxf_ber_encode_size (guint size, guint8 ber[9])
 
162
{
 
163
  guint8 slen, i;
 
164
  guint8 tmp[8];
 
165
 
 
166
  memset (ber, 0, 9);
 
167
 
 
168
  if (size <= 127) {
 
169
    ber[0] = size;
 
170
    return 1;
 
171
  } else if (size > G_MAXUINT) {
 
172
    return 0;
 
173
  }
 
174
 
 
175
  slen = 0;
 
176
  while (size > 0) {
 
177
    tmp[slen] = size & 0xff;
 
178
    size >>= 8;
 
179
    slen++;
 
180
  }
 
181
 
 
182
  ber[0] = 0x80 | slen;
 
183
  for (i = 0; i < slen; i++) {
 
184
    ber[i + 1] = tmp[slen - i - 1];
 
185
  }
 
186
 
 
187
  return slen + 1;
 
188
}
 
189
 
 
190
GstBuffer *
 
191
mxf_fill_to_buffer (guint size)
 
192
{
 
193
  GstBuffer *ret;
 
194
  guint slen;
 
195
  guint8 ber[9];
 
196
 
 
197
  slen = mxf_ber_encode_size (size, ber);
 
198
 
 
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);
 
203
 
 
204
  return ret;
 
205
}
 
206
 
 
207
void
 
208
mxf_uuid_init (MXFUUID * uuid, GHashTable * hashtable)
 
209
{
 
210
  guint i;
 
211
 
 
212
  do {
 
213
    for (i = 0; i < 4; i++)
 
214
      GST_WRITE_UINT32_BE (&uuid->u[i * 4], g_random_int ());
 
215
 
 
216
  } while (hashtable && (mxf_uuid_is_zero (uuid) ||
 
217
          g_hash_table_lookup_extended (hashtable, uuid, NULL, NULL)));
 
218
}
 
219
 
 
220
gboolean
 
221
mxf_uuid_is_equal (const MXFUUID * a, const MXFUUID * b)
 
222
{
 
223
  g_return_val_if_fail (a != NULL, FALSE);
 
224
  g_return_val_if_fail (b != NULL, FALSE);
 
225
 
 
226
  return (memcmp (a, b, 16) == 0);
 
227
}
 
228
 
 
229
gboolean
 
230
mxf_uuid_is_zero (const MXFUUID * a)
 
231
{
 
232
  static const guint8 zero[16] = { 0x00, };
 
233
 
 
234
  g_return_val_if_fail (a != NULL, FALSE);
 
235
 
 
236
  return (memcmp (a, zero, 16) == 0);
 
237
}
 
238
 
 
239
guint
 
240
mxf_uuid_hash (const MXFUUID * uuid)
 
241
{
 
242
  guint32 ret = 0;
 
243
  guint i;
 
244
 
 
245
  g_return_val_if_fail (uuid != NULL, 0);
 
246
 
 
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);
 
251
 
 
252
  return ret;
 
253
}
 
254
 
 
255
gchar *
 
256
mxf_uuid_to_string (const MXFUUID * uuid, gchar str[48])
 
257
{
 
258
  gchar *ret = str;
 
259
 
 
260
  g_return_val_if_fail (uuid != NULL, NULL);
 
261
 
 
262
  if (ret == NULL)
 
263
    ret = g_malloc (48);
 
264
 
 
265
  g_snprintf (ret, 48,
 
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]);
 
274
 
 
275
  return ret;
 
276
}
 
277
 
 
278
MXFUUID *
 
279
mxf_uuid_from_string (const gchar * str, MXFUUID * uuid)
 
280
{
 
281
  MXFUUID *ret = uuid;
 
282
  gint len;
 
283
  guint i, j;
 
284
 
 
285
  g_return_val_if_fail (str != NULL, NULL);
 
286
 
 
287
  len = strlen (str);
 
288
  if (len != 47) {
 
289
    GST_ERROR ("Invalid UUID string length %d, should be 47", len);
 
290
    return NULL;
 
291
  }
 
292
 
 
293
  if (ret == NULL)
 
294
    ret = g_new0 (MXFUUID, 1);
 
295
 
 
296
  memset (ret, 0, 16);
 
297
 
 
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);
 
303
      if (uuid == NULL)
 
304
        g_free (ret);
 
305
      return NULL;
 
306
    }
 
307
 
 
308
    ret->u[i] = (g_ascii_xdigit_value (str[j]) << 4) |
 
309
        (g_ascii_xdigit_value (str[j + 1]));
 
310
    j += 3;
 
311
  }
 
312
  return ret;
 
313
}
 
314
 
 
315
gboolean
 
316
mxf_uuid_array_parse (MXFUUID ** array, guint32 * count, const guint8 * data,
 
317
    guint size)
 
318
{
 
319
  guint32 element_count, element_size;
 
320
  guint i;
 
321
 
 
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);
 
325
 
 
326
  if (size < 8)
 
327
    return FALSE;
 
328
 
 
329
  element_count = GST_READ_UINT32_BE (data);
 
330
  data += 4;
 
331
  size -= 4;
 
332
 
 
333
  if (element_count == 0) {
 
334
    *array = NULL;
 
335
    *count = 0;
 
336
    return TRUE;
 
337
  }
 
338
 
 
339
  element_size = GST_READ_UINT32_BE (data);
 
340
  data += 4;
 
341
  size -= 4;
 
342
 
 
343
  if (element_size != 16) {
 
344
    *array = NULL;
 
345
    *count = 0;
 
346
    return FALSE;
 
347
  }
 
348
 
 
349
  if (16 * element_count < size) {
 
350
    *array = NULL;
 
351
    *count = 0;
 
352
    return FALSE;
 
353
  }
 
354
 
 
355
  *array = g_new (MXFUUID, element_count);
 
356
  *count = element_count;
 
357
 
 
358
  for (i = 0; i < element_count; i++) {
 
359
    memcpy (&((*array)[i]), data, 16);
 
360
    data += 16;
 
361
  }
 
362
 
 
363
  return TRUE;
 
364
}
 
365
 
 
366
gboolean
 
367
mxf_umid_is_equal (const MXFUMID * a, const MXFUMID * b)
 
368
{
 
369
  return (memcmp (a, b, 32) == 0);
 
370
}
 
371
 
 
372
gboolean
 
373
mxf_umid_is_zero (const MXFUMID * umid)
 
374
{
 
375
  static const MXFUMID zero = { {0,} };
 
376
 
 
377
  return (memcmp (umid, &zero, 32) == 0);
 
378
}
 
379
 
 
380
gchar *
 
381
mxf_umid_to_string (const MXFUMID * umid, gchar str[96])
 
382
{
 
383
  g_return_val_if_fail (umid != NULL, NULL);
 
384
  g_return_val_if_fail (str != NULL, NULL);
 
385
 
 
386
  g_snprintf (str, 96,
 
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],
 
392
      umid->u[16],
 
393
      umid->u[17],
 
394
      umid->u[18],
 
395
      umid->u[19],
 
396
      umid->u[20],
 
397
      umid->u[21],
 
398
      umid->u[22],
 
399
      umid->u[23],
 
400
      umid->u[24],
 
401
      umid->u[25],
 
402
      umid->u[26], umid->u[27], umid->u[28], umid->u[29], umid->u[30],
 
403
      umid->u[31]
 
404
      );
 
405
 
 
406
  return str;
 
407
}
 
408
 
 
409
MXFUMID *
 
410
mxf_umid_from_string (const gchar * str, MXFUMID * umid)
 
411
{
 
412
  gint len;
 
413
  guint i, j;
 
414
 
 
415
  g_return_val_if_fail (str != NULL, NULL);
 
416
  len = strlen (str);
 
417
 
 
418
  memset (umid, 0, 32);
 
419
 
 
420
  if (len != 95) {
 
421
    GST_ERROR ("Invalid UMID string length %d", len);
 
422
    return NULL;
 
423
  }
 
424
 
 
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);
 
430
      return NULL;
 
431
    }
 
432
 
 
433
    umid->u[i] =
 
434
        (g_ascii_xdigit_value (str[j]) << 4) | (g_ascii_xdigit_value (str[j +
 
435
                1]));
 
436
    j += 3;
 
437
  }
 
438
  return umid;
 
439
}
 
440
 
 
441
void
 
442
mxf_umid_init (MXFUMID * umid)
 
443
{
 
444
  guint i;
 
445
  guint32 tmp;
 
446
 
 
447
  /* SMPTE S330M 5.1.1:
 
448
   *    UMID Identifier
 
449
   */
 
450
  umid->u[0] = 0x06;
 
451
  umid->u[1] = 0x0a;
 
452
  umid->u[2] = 0x2b;
 
453
  umid->u[3] = 0x34;
 
454
  umid->u[4] = 0x01;
 
455
  umid->u[5] = 0x01;
 
456
  umid->u[6] = 0x01;
 
457
  umid->u[7] = 0x05;            /* version, see RP210 */
 
458
  umid->u[8] = 0x01;
 
459
  umid->u[9] = 0x01;
 
460
  umid->u[10] = 0x0d;           /* mixed group of components in a single container */
 
461
 
 
462
  /* - UUID/UL method for material number
 
463
   * - 24 bit PRG for instance number
 
464
   */
 
465
  umid->u[11] = 0x20 | 0x02;
 
466
 
 
467
  /* Length of remaining data */
 
468
  umid->u[12] = 0x13;
 
469
 
 
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;
 
475
 
 
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 ());
 
479
 
 
480
  umid->u[16 + 6] &= 0x0f;
 
481
  umid->u[16 + 6] |= 0x40;
 
482
 
 
483
  umid->u[16 + 8] &= 0x3f;
 
484
  umid->u[16 + 8] |= 0x80;
 
485
}
 
486
 
 
487
gboolean
 
488
mxf_timestamp_parse (MXFTimestamp * timestamp, const guint8 * data, guint size)
 
489
{
 
490
  g_return_val_if_fail (data != NULL, FALSE);
 
491
  g_return_val_if_fail (timestamp != NULL, FALSE);
 
492
 
 
493
  memset (timestamp, 0, sizeof (MXFTimestamp));
 
494
 
 
495
  if (size < 8)
 
496
    return FALSE;
 
497
 
 
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;
 
505
 
 
506
  return TRUE;
 
507
}
 
508
 
 
509
/* SMPTE 377M 3.3: A value of 0 for every field means unknown timestamp */
 
510
gboolean
 
511
mxf_timestamp_is_unknown (const MXFTimestamp * a)
 
512
{
 
513
  static const MXFTimestamp unknown = { 0, 0, 0, 0, 0, 0, 0 };
 
514
 
 
515
  return (memcmp (a, &unknown, sizeof (MXFTimestamp)) == 0);
 
516
}
 
517
 
 
518
gint
 
519
mxf_timestamp_compare (const MXFTimestamp * a, const MXFTimestamp * b)
 
520
{
 
521
  gint diff;
 
522
 
 
523
  if ((diff = a->year - b->year) != 0)
 
524
    return diff;
 
525
  else if ((diff = a->month - b->month) != 0)
 
526
    return diff;
 
527
  else if ((diff = a->day - b->day) != 0)
 
528
    return diff;
 
529
  else if ((diff = a->hour - b->hour) != 0)
 
530
    return diff;
 
531
  else if ((diff = a->minute - b->minute) != 0)
 
532
    return diff;
 
533
  else if ((diff = a->second - b->second) != 0)
 
534
    return diff;
 
535
  else if ((diff = a->msecond - b->msecond) != 0)
 
536
    return diff;
 
537
  else
 
538
    return 0;
 
539
}
 
540
 
 
541
gchar *
 
542
mxf_timestamp_to_string (const MXFTimestamp * t, gchar str[32])
 
543
{
 
544
  g_snprintf (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);
 
547
  return str;
 
548
}
 
549
 
 
550
void
 
551
mxf_timestamp_set_now (MXFTimestamp * timestamp)
 
552
{
 
553
  GTimeVal tv;
 
554
  time_t t;
 
555
  struct tm *tm;
 
556
 
 
557
#ifdef HAVE_GMTIME_R
 
558
  struct tm tm_;
 
559
#endif
 
560
 
 
561
  g_get_current_time (&tv);
 
562
  t = (time_t) tv.tv_sec;
 
563
 
 
564
#ifdef HAVE_GMTIME_R
 
565
  tm = gmtime_r (&t, &tm_);
 
566
#else
 
567
  tm = gmtime (&t);
 
568
#endif
 
569
 
 
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;
 
577
}
 
578
 
 
579
void
 
580
mxf_timestamp_write (const MXFTimestamp * timestamp, guint8 * data)
 
581
{
 
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);
 
589
}
 
590
 
 
591
gboolean
 
592
mxf_fraction_parse (MXFFraction * fraction, const guint8 * data, guint size)
 
593
{
 
594
  g_return_val_if_fail (fraction != NULL, FALSE);
 
595
  g_return_val_if_fail (data != NULL, FALSE);
 
596
 
 
597
  memset (fraction, 0, sizeof (MXFFraction));
 
598
 
 
599
  if (size < 8)
 
600
    return FALSE;
 
601
 
 
602
  fraction->n = GST_READ_UINT32_BE (data);
 
603
  fraction->d = GST_READ_UINT32_BE (data + 4);
 
604
 
 
605
  return TRUE;
 
606
}
 
607
 
 
608
gdouble
 
609
mxf_fraction_to_double (const MXFFraction * fraction)
 
610
{
 
611
  return ((gdouble) fraction->n) / ((gdouble) fraction->d);
 
612
}
 
613
 
 
614
gchar *
 
615
mxf_utf16_to_utf8 (const guint8 * data, guint size)
 
616
{
 
617
  gchar *ret;
 
618
  GError *error = NULL;
 
619
 
 
620
  ret =
 
621
      g_convert ((const gchar *) data, size, "UTF-8", "UTF-16BE", NULL, NULL,
 
622
      &error);
 
623
 
 
624
  if (ret == NULL) {
 
625
    GST_WARNING ("UTF-16-BE to UTF-8 conversion failed: %s", error->message);
 
626
    g_error_free (error);
 
627
    return NULL;
 
628
  }
 
629
 
 
630
  return ret;
 
631
}
 
632
 
 
633
guint8 *
 
634
mxf_utf8_to_utf16 (const gchar * str, guint16 * size)
 
635
{
 
636
  guint8 *ret;
 
637
  GError *error = NULL;
 
638
  gsize s;
 
639
 
 
640
  g_return_val_if_fail (size != NULL, NULL);
 
641
 
 
642
  if (str == NULL) {
 
643
    *size = 0;
 
644
    return NULL;
 
645
  }
 
646
 
 
647
  ret = (guint8 *)
 
648
      g_convert_with_fallback (str, -1, "UTF-16BE", "UTF-8", "*", NULL, &s,
 
649
      &error);
 
650
 
 
651
  if (ret == NULL) {
 
652
    GST_WARNING ("UTF-16-BE to UTF-8 conversion failed: %s", error->message);
 
653
    g_error_free (error);
 
654
    *size = 0;
 
655
    return NULL;
 
656
  }
 
657
 
 
658
  *size = s;
 
659
  return (guint8 *) ret;
 
660
}
 
661
 
 
662
gboolean
 
663
mxf_product_version_parse (MXFProductVersion * product_version,
 
664
    const guint8 * data, guint size)
 
665
{
 
666
  g_return_val_if_fail (product_version != NULL, FALSE);
 
667
  g_return_val_if_fail (data != NULL, FALSE);
 
668
 
 
669
  memset (product_version, 0, sizeof (MXFProductVersion));
 
670
 
 
671
  if (size < 9)
 
672
    return FALSE;
 
673
 
 
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);
 
678
 
 
679
  /* Avid writes a 9 byte product version */
 
680
  if (size == 9)
 
681
    product_version->release = GST_READ_UINT8 (data + 8);
 
682
  else
 
683
    product_version->release = GST_READ_UINT16_BE (data + 8);
 
684
 
 
685
  return TRUE;
 
686
}
 
687
 
 
688
gboolean
 
689
mxf_product_version_is_valid (const MXFProductVersion * version)
 
690
{
 
691
  static const guint8 null[sizeof (MXFProductVersion)] = { 0, };
 
692
 
 
693
  return (memcmp (version, &null, sizeof (MXFProductVersion)) == 0);
 
694
}
 
695
 
 
696
void
 
697
mxf_product_version_write (const MXFProductVersion * version, guint8 * data)
 
698
{
 
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);
 
704
}
 
705
 
 
706
void
 
707
mxf_op_set_atom (MXFUL * ul, gboolean single_sourceclip,
 
708
    gboolean single_essence_track)
 
709
{
 
710
  memcpy (&ul->u, MXF_UL (OPERATIONAL_PATTERN_IDENTIFICATION), 12);
 
711
  ul->u[12] = 0x10;
 
712
  ul->u[13] = 0;
 
713
 
 
714
  if (!single_sourceclip)
 
715
    ul->u[13] |= 0x80;
 
716
 
 
717
  if (!single_essence_track)
 
718
    ul->u[13] |= 0x40;
 
719
 
 
720
  ul->u[14] = 0;
 
721
  ul->u[15] = 0;
 
722
}
 
723
 
 
724
void
 
725
mxf_op_set_generalized (MXFUL * ul, MXFOperationalPattern pattern,
 
726
    gboolean internal_essence, gboolean streamable, gboolean single_track)
 
727
{
 
728
  g_return_if_fail (pattern >= MXF_OP_1a);
 
729
 
 
730
  memcpy (&ul->u, MXF_UL (OPERATIONAL_PATTERN_IDENTIFICATION), 12);
 
731
 
 
732
  if (pattern == MXF_OP_1a || pattern == MXF_OP_1b || pattern == MXF_OP_1c)
 
733
    ul->u[12] = 0x01;
 
734
  else if (pattern == MXF_OP_2a || pattern == MXF_OP_2b || pattern == MXF_OP_2c)
 
735
    ul->u[12] = 0x02;
 
736
  else if (pattern == MXF_OP_3a || pattern == MXF_OP_3b || pattern == MXF_OP_3c)
 
737
    ul->u[12] = 0x03;
 
738
 
 
739
  if (pattern == MXF_OP_1a || pattern == MXF_OP_2a || pattern == MXF_OP_3a)
 
740
    ul->u[13] = 0x01;
 
741
  else if (pattern == MXF_OP_1b || pattern == MXF_OP_2b || pattern == MXF_OP_3b)
 
742
    ul->u[13] = 0x02;
 
743
  else if (pattern == MXF_OP_1c || pattern == MXF_OP_2c || pattern == MXF_OP_3c)
 
744
    ul->u[13] = 0x02;
 
745
 
 
746
  ul->u[14] = 0x80;
 
747
  if (!internal_essence)
 
748
    ul->u[14] |= 0x40;
 
749
  if (!streamable)
 
750
    ul->u[14] |= 0x20;
 
751
  if (!single_track)
 
752
    ul->u[14] |= 0x10;
 
753
 
 
754
  ul->u[15] = 0;
 
755
}
 
756
 
 
757
/* SMPTE 377M 6.1, Table 2 */
 
758
gboolean
 
759
mxf_partition_pack_parse (const MXFUL * ul, MXFPartitionPack * pack,
 
760
    const guint8 * data, guint size)
 
761
{
 
762
#ifndef GST_DISABLE_GST_DEBUG
 
763
  guint i;
 
764
  gchar str[48];
 
765
#endif
 
766
 
 
767
  g_return_val_if_fail (data != NULL, FALSE);
 
768
  g_return_val_if_fail (size >= 84, FALSE);
 
769
 
 
770
  memset (pack, 0, sizeof (MXFPartitionPack));
 
771
 
 
772
  GST_DEBUG ("Parsing partition pack:");
 
773
 
 
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;
 
780
 
 
781
  GST_DEBUG ("  type = %s",
 
782
      (pack->type == MXF_PARTITION_PACK_HEADER) ? "header" : (pack->type ==
 
783
          MXF_PARTITION_PACK_BODY) ? "body" : "footer");
 
784
 
 
785
  pack->closed = (ul->u[14] == 0x02 || ul->u[14] == 0x04);
 
786
  pack->complete = (ul->u[14] == 0x03 || ul->u[14] == 0x04);
 
787
 
 
788
  GST_DEBUG ("  closed = %s, complete = %s", (pack->closed) ? "yes" : "no",
 
789
      (pack->complete) ? "yes" : "no");
 
790
 
 
791
  pack->major_version = GST_READ_UINT16_BE (data);
 
792
  if (pack->major_version != 1)
 
793
    goto error;
 
794
  data += 2;
 
795
  size -= 2;
 
796
 
 
797
  pack->minor_version = GST_READ_UINT16_BE (data);
 
798
  data += 2;
 
799
  size -= 2;
 
800
 
 
801
  GST_DEBUG ("  MXF version = %u.%u", pack->major_version, pack->minor_version);
 
802
 
 
803
  pack->kag_size = GST_READ_UINT32_BE (data);
 
804
  data += 4;
 
805
  size -= 4;
 
806
 
 
807
  GST_DEBUG ("  KAG size = %u", pack->kag_size);
 
808
 
 
809
  pack->this_partition = GST_READ_UINT64_BE (data);
 
810
  data += 8;
 
811
  size -= 8;
 
812
 
 
813
  GST_DEBUG ("  this partition offset = %" G_GUINT64_FORMAT,
 
814
      pack->this_partition);
 
815
 
 
816
  pack->prev_partition = GST_READ_UINT64_BE (data);
 
817
  data += 8;
 
818
  size -= 8;
 
819
 
 
820
  GST_DEBUG ("  previous partition offset = %" G_GUINT64_FORMAT,
 
821
      pack->prev_partition);
 
822
 
 
823
  pack->footer_partition = GST_READ_UINT64_BE (data);
 
824
  data += 8;
 
825
  size -= 8;
 
826
 
 
827
  GST_DEBUG ("  footer partition offset = %" G_GUINT64_FORMAT,
 
828
      pack->footer_partition);
 
829
 
 
830
  pack->header_byte_count = GST_READ_UINT64_BE (data);
 
831
  data += 8;
 
832
  size -= 8;
 
833
 
 
834
  GST_DEBUG ("  header byte count = %" G_GUINT64_FORMAT,
 
835
      pack->header_byte_count);
 
836
 
 
837
  pack->index_byte_count = GST_READ_UINT64_BE (data);
 
838
  data += 8;
 
839
  size -= 8;
 
840
 
 
841
  pack->index_sid = GST_READ_UINT32_BE (data);
 
842
  data += 4;
 
843
  size -= 4;
 
844
 
 
845
  GST_DEBUG ("  index sid = %u, size = %" G_GUINT64_FORMAT, pack->index_sid,
 
846
      pack->index_byte_count);
 
847
 
 
848
  pack->body_offset = GST_READ_UINT64_BE (data);
 
849
  data += 8;
 
850
  size -= 8;
 
851
 
 
852
  pack->body_sid = GST_READ_UINT32_BE (data);
 
853
  data += 4;
 
854
  size -= 4;
 
855
 
 
856
  GST_DEBUG ("  body sid = %u, offset = %" G_GUINT64_FORMAT, pack->body_sid,
 
857
      pack->body_offset);
 
858
 
 
859
  memcpy (&pack->operational_pattern, data, 16);
 
860
  data += 16;
 
861
  size -= 16;
 
862
 
 
863
  GST_DEBUG ("  operational pattern = %s",
 
864
      mxf_ul_to_string (&pack->operational_pattern, str));
 
865
 
 
866
  if (!mxf_ul_array_parse (&pack->essence_containers,
 
867
          &pack->n_essence_containers, data, size))
 
868
    goto error;
 
869
 
 
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));
 
876
    }
 
877
  }
 
878
#endif
 
879
 
 
880
  return TRUE;
 
881
 
 
882
error:
 
883
  GST_ERROR ("Invalid partition pack");
 
884
 
 
885
  mxf_partition_pack_reset (pack);
 
886
  return FALSE;
 
887
}
 
888
 
 
889
void
 
890
mxf_partition_pack_reset (MXFPartitionPack * pack)
 
891
{
 
892
  g_return_if_fail (pack != NULL);
 
893
 
 
894
  g_free (pack->essence_containers);
 
895
 
 
896
  memset (pack, 0, sizeof (MXFPartitionPack));
 
897
}
 
898
 
 
899
GstBuffer *
 
900
mxf_partition_pack_to_buffer (const MXFPartitionPack * pack)
 
901
{
 
902
  guint slen;
 
903
  guint8 ber[9];
 
904
  GstBuffer *ret;
 
905
  guint8 *data;
 
906
  guint i;
 
907
  guint size =
 
908
      8 + 16 * pack->n_essence_containers + 16 + 4 + 8 + 4 + 8 + 8 + 8 + 8 + 8 +
 
909
      4 + 2 + 2;
 
910
 
 
911
  slen = mxf_ber_encode_size (size, ber);
 
912
 
 
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;
 
922
  if (pack->complete)
 
923
    GST_BUFFER_DATA (ret)[14] |= 0x02;
 
924
  if (pack->closed)
 
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);
 
929
 
 
930
  data = GST_BUFFER_DATA (ret) + 16 + slen;
 
931
 
 
932
  GST_WRITE_UINT16_BE (data, pack->major_version);
 
933
  GST_WRITE_UINT16_BE (data + 2, pack->minor_version);
 
934
  data += 4;
 
935
 
 
936
  GST_WRITE_UINT32_BE (data, pack->kag_size);
 
937
  data += 4;
 
938
 
 
939
  GST_WRITE_UINT64_BE (data, pack->this_partition);
 
940
  data += 8;
 
941
 
 
942
  GST_WRITE_UINT64_BE (data, pack->prev_partition);
 
943
  data += 8;
 
944
 
 
945
  GST_WRITE_UINT64_BE (data, pack->footer_partition);
 
946
  data += 8;
 
947
 
 
948
  GST_WRITE_UINT64_BE (data, pack->header_byte_count);
 
949
  data += 8;
 
950
 
 
951
  GST_WRITE_UINT64_BE (data, pack->index_byte_count);
 
952
  data += 8;
 
953
 
 
954
  GST_WRITE_UINT32_BE (data, pack->index_sid);
 
955
  data += 4;
 
956
 
 
957
  GST_WRITE_UINT64_BE (data, pack->body_offset);
 
958
  data += 8;
 
959
 
 
960
  GST_WRITE_UINT32_BE (data, pack->body_sid);
 
961
  data += 4;
 
962
 
 
963
  memcpy (data, &pack->operational_pattern, 16);
 
964
  data += 16;
 
965
 
 
966
  GST_WRITE_UINT32_BE (data, pack->n_essence_containers);
 
967
  GST_WRITE_UINT32_BE (data + 4, 16);
 
968
  data += 8;
 
969
 
 
970
  for (i = 0; i < pack->n_essence_containers; i++)
 
971
    memcpy (data + 16 * i, &pack->essence_containers[i], 16);
 
972
 
 
973
  return ret;
 
974
}
 
975
 
 
976
/* SMPTE 377M 11.1 */
 
977
gboolean
 
978
mxf_random_index_pack_parse (const MXFUL * ul, const guint8 * data, guint size,
 
979
    GArray ** array)
 
980
{
 
981
  guint len, i;
 
982
  MXFRandomIndexPackEntry entry;
 
983
 
 
984
  g_return_val_if_fail (data != NULL, FALSE);
 
985
  g_return_val_if_fail (array != NULL, FALSE);
 
986
 
 
987
  if (size < 4)
 
988
    return FALSE;
 
989
 
 
990
  if ((size - 4) % 12 != 0)
 
991
    return FALSE;
 
992
 
 
993
  GST_DEBUG ("Parsing random index pack:");
 
994
 
 
995
  len = (size - 4) / 12;
 
996
 
 
997
  GST_DEBUG ("  number of entries = %u", len);
 
998
 
 
999
  *array =
 
1000
      g_array_sized_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry), len);
 
1001
 
 
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);
 
1005
    data += 12;
 
1006
 
 
1007
    GST_DEBUG ("  entry %u = body sid %u at offset %" G_GUINT64_FORMAT, i,
 
1008
        entry.body_sid, entry.offset);
 
1009
 
 
1010
    g_array_append_val (*array, entry);
 
1011
  }
 
1012
 
 
1013
  return TRUE;
 
1014
}
 
1015
 
 
1016
GstBuffer *
 
1017
mxf_random_index_pack_to_buffer (const GArray * array)
 
1018
{
 
1019
  MXFRandomIndexPackEntry *entry;
 
1020
  guint i;
 
1021
  GstBuffer *ret;
 
1022
  guint8 slen, ber[9];
 
1023
  guint size;
 
1024
  guint8 *data;
 
1025
 
 
1026
  if (array->len == 0)
 
1027
    return NULL;
 
1028
 
 
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);
 
1034
 
 
1035
  data = GST_BUFFER_DATA (ret) + 16 + slen;
 
1036
 
 
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);
 
1041
    data += 12;
 
1042
  }
 
1043
  GST_WRITE_UINT32_BE (data, GST_BUFFER_SIZE (ret));
 
1044
 
 
1045
  return ret;
 
1046
}
 
1047
 
 
1048
/* SMPTE 377M 10.2.3 */
 
1049
gboolean
 
1050
mxf_index_table_segment_parse (const MXFUL * ul,
 
1051
    MXFIndexTableSegment * segment, const MXFPrimerPack * primer,
 
1052
    const guint8 * data, guint size)
 
1053
{
 
1054
#ifndef GST_DISABLE_GST_DEBUG
 
1055
  gchar str[48];
 
1056
#endif
 
1057
  guint16 tag, tag_size;
 
1058
  const guint8 *tag_data;
 
1059
 
 
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);
 
1063
 
 
1064
  memset (segment, 0, sizeof (MXFIndexTableSegment));
 
1065
 
 
1066
  if (size < 70)
 
1067
    return FALSE;
 
1068
 
 
1069
  GST_DEBUG ("Parsing index table segment:");
 
1070
 
 
1071
  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
 
1072
    if (tag_size == 0 || tag == 0x0000)
 
1073
      goto next;
 
1074
 
 
1075
    switch (tag) {
 
1076
      case 0x3c0a:
 
1077
        if (tag_size != 16)
 
1078
          goto error;
 
1079
        memcpy (&segment->instance_id, tag_data, 16);
 
1080
        GST_DEBUG ("  instance id = %s",
 
1081
            mxf_uuid_to_string (&segment->instance_id, str));
 
1082
        break;
 
1083
      case 0x3f0b:
 
1084
        if (!mxf_fraction_parse (&segment->index_edit_rate, tag_data, tag_size))
 
1085
          goto error;
 
1086
        GST_DEBUG ("  index edit rate = %d/%d", segment->index_edit_rate.n,
 
1087
            segment->index_edit_rate.d);
 
1088
        break;
 
1089
      case 0x3f0c:
 
1090
        if (tag_size != 8)
 
1091
          goto error;
 
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);
 
1095
        break;
 
1096
      case 0x3f0d:
 
1097
        if (tag_size != 8)
 
1098
          goto error;
 
1099
        segment->index_duration = GST_READ_UINT64_BE (tag_data);
 
1100
        GST_DEBUG ("  index duration = %" G_GINT64_FORMAT,
 
1101
            segment->index_duration);
 
1102
        break;
 
1103
      case 0x3f05:
 
1104
        if (tag_size != 4)
 
1105
          goto error;
 
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);
 
1109
        break;
 
1110
      case 0x3f06:
 
1111
        if (tag_size != 4)
 
1112
          goto error;
 
1113
        segment->index_sid = GST_READ_UINT32_BE (tag_data);
 
1114
        GST_DEBUG ("  index sid = %u", segment->index_sid);
 
1115
        break;
 
1116
      case 0x3f07:
 
1117
        if (tag_size != 4)
 
1118
          goto error;
 
1119
        segment->body_sid = GST_READ_UINT32_BE (tag_data);
 
1120
        GST_DEBUG ("  body sid = %u", segment->body_sid);
 
1121
        break;
 
1122
      case 0x3f08:
 
1123
        if (tag_size != 1)
 
1124
          goto error;
 
1125
        segment->slice_count = GST_READ_UINT8 (tag_data);
 
1126
        GST_DEBUG ("  slice count = %u", segment->slice_count);
 
1127
        break;
 
1128
      case 0x3f0e:
 
1129
        if (tag_size != 1)
 
1130
          goto error;
 
1131
        segment->pos_table_count = GST_READ_UINT8 (tag_data);
 
1132
        GST_DEBUG ("  pos table count = %u", segment->pos_table_count);
 
1133
        break;
 
1134
      case 0x3f09:{
 
1135
        guint len, i;
 
1136
 
 
1137
        if (tag_size < 8)
 
1138
          goto error;
 
1139
 
 
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);
 
1143
        if (len == 0)
 
1144
          goto next;
 
1145
        tag_data += 4;
 
1146
        tag_size -= 4;
 
1147
 
 
1148
        if (GST_READ_UINT32_BE (tag_data) != 6)
 
1149
          goto error;
 
1150
 
 
1151
        tag_data += 4;
 
1152
        tag_size -= 4;
 
1153
 
 
1154
        if (tag_size < len * 6)
 
1155
          goto error;
 
1156
 
 
1157
        segment->delta_entries = g_new (MXFDeltaEntry, len);
 
1158
 
 
1159
        for (i = 0; i < len; i++) {
 
1160
          GST_DEBUG ("    delta entry %u:", i);
 
1161
 
 
1162
          segment->delta_entries[i].pos_table_index = GST_READ_UINT8 (tag_data);
 
1163
          tag_data += 1;
 
1164
          tag_size -= 1;
 
1165
          GST_DEBUG ("    pos table index = %d",
 
1166
              segment->delta_entries[i].pos_table_index);
 
1167
 
 
1168
          segment->delta_entries[i].slice = GST_READ_UINT8 (tag_data);
 
1169
          tag_data += 1;
 
1170
          tag_size -= 1;
 
1171
          GST_DEBUG ("    slice = %u", segment->delta_entries[i].slice);
 
1172
 
 
1173
          segment->delta_entries[i].element_delta =
 
1174
              GST_READ_UINT32_BE (tag_data);
 
1175
          tag_data += 4;
 
1176
          tag_size -= 4;
 
1177
          GST_DEBUG ("    element delta = %u",
 
1178
              segment->delta_entries[i].element_delta);
 
1179
        }
 
1180
        break;
 
1181
      }
 
1182
      case 0x3f0a:{
 
1183
        guint len, i, j;
 
1184
 
 
1185
        if (tag_size < 8)
 
1186
          goto error;
 
1187
 
 
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);
 
1191
        if (len == 0)
 
1192
          goto next;
 
1193
        tag_data += 4;
 
1194
        tag_size -= 4;
 
1195
 
 
1196
        if (GST_READ_UINT32_BE (tag_data) !=
 
1197
            (11 + 4 * segment->slice_count + 8 * segment->pos_table_count))
 
1198
          goto error;
 
1199
 
 
1200
        tag_data += 4;
 
1201
        tag_size -= 4;
 
1202
 
 
1203
        if (tag_size < len * 11)
 
1204
          goto error;
 
1205
 
 
1206
        segment->index_entries = g_new0 (MXFIndexEntry, len);
 
1207
 
 
1208
        for (i = 0; i < len; i++) {
 
1209
          MXFIndexEntry *entry = &segment->index_entries[i];
 
1210
 
 
1211
          GST_DEBUG ("    index entry %u:", i);
 
1212
 
 
1213
          entry->temporal_offset = GST_READ_UINT8 (tag_data);
 
1214
          tag_data += 1;
 
1215
          tag_size -= 1;
 
1216
          GST_DEBUG ("    temporal offset = %d", entry->temporal_offset);
 
1217
 
 
1218
          entry->key_frame_offset = GST_READ_UINT8 (tag_data);
 
1219
          tag_data += 1;
 
1220
          tag_size -= 1;
 
1221
          GST_DEBUG ("    keyframe offset = %d", entry->key_frame_offset);
 
1222
 
 
1223
          entry->flags = GST_READ_UINT8 (tag_data);
 
1224
          tag_data += 1;
 
1225
          tag_size -= 1;
 
1226
          GST_DEBUG ("    flags = 0x%02x", entry->flags);
 
1227
 
 
1228
          entry->stream_offset = GST_READ_UINT64_BE (tag_data);
 
1229
          tag_data += 8;
 
1230
          tag_size -= 8;
 
1231
          GST_DEBUG ("    stream offset = %" G_GUINT64_FORMAT,
 
1232
              entry->stream_offset);
 
1233
 
 
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);
 
1237
            tag_data += 4;
 
1238
            tag_size -= 4;
 
1239
            GST_DEBUG ("    slice %u offset = %u", j, entry->slice_offset[j]);
 
1240
          }
 
1241
 
 
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);
 
1245
            tag_data += 8;
 
1246
            tag_size -= 8;
 
1247
            GST_DEBUG ("    pos table %u = %d/%d", j, entry->pos_table[j].n,
 
1248
                entry->pos_table[j].d);
 
1249
          }
 
1250
        }
 
1251
        break;
 
1252
      }
 
1253
      default:
 
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)) {
 
1258
          goto error;
 
1259
        }
 
1260
        break;
 
1261
    }
 
1262
 
 
1263
  next:
 
1264
    data += 4 + tag_size;
 
1265
    size -= 4 + tag_size;
 
1266
  }
 
1267
  return TRUE;
 
1268
 
 
1269
error:
 
1270
  GST_ERROR ("Invalid index table segment");
 
1271
  return FALSE;
 
1272
}
 
1273
 
 
1274
void
 
1275
mxf_index_table_segment_reset (MXFIndexTableSegment * segment)
 
1276
{
 
1277
  guint i;
 
1278
 
 
1279
  g_return_if_fail (segment != NULL);
 
1280
 
 
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);
 
1284
  }
 
1285
 
 
1286
  g_free (segment->index_entries);
 
1287
  g_free (segment->delta_entries);
 
1288
 
 
1289
  if (segment->other_tags)
 
1290
    g_hash_table_destroy (segment->other_tags);
 
1291
 
 
1292
  memset (segment, 0, sizeof (MXFIndexTableSegment));
 
1293
}
 
1294
 
 
1295
/* SMPTE 377M 8.2 Table 1 and 2 */
 
1296
 
 
1297
static void
 
1298
_mxf_mapping_ul_free (MXFUL * ul)
 
1299
{
 
1300
  g_slice_free (MXFUL, ul);
 
1301
}
 
1302
 
 
1303
gboolean
 
1304
mxf_primer_pack_parse (const MXFUL * ul, MXFPrimerPack * pack,
 
1305
    const guint8 * data, guint size)
 
1306
{
 
1307
  guint i;
 
1308
  guint32 n;
 
1309
 
 
1310
  g_return_val_if_fail (data != NULL, FALSE);
 
1311
  g_return_val_if_fail (size >= 8, FALSE);
 
1312
 
 
1313
  memset (pack, 0, sizeof (MXFPrimerPack));
 
1314
 
 
1315
  GST_DEBUG ("Parsing primer pack:");
 
1316
 
 
1317
  pack->mappings =
 
1318
      g_hash_table_new_full (g_direct_hash, g_direct_equal,
 
1319
      (GDestroyNotify) NULL, (GDestroyNotify) _mxf_mapping_ul_free);
 
1320
 
 
1321
  n = GST_READ_UINT32_BE (data);
 
1322
  data += 4;
 
1323
 
 
1324
  GST_DEBUG ("  number of mappings = %u", n);
 
1325
 
 
1326
  if (GST_READ_UINT32_BE (data) != 18)
 
1327
    goto error;
 
1328
  data += 4;
 
1329
 
 
1330
  if (size < 8 + n * 18)
 
1331
    goto error;
 
1332
 
 
1333
  for (i = 0; i < n; i++) {
 
1334
    guint local_tag;
 
1335
#ifndef GST_DISABLE_GST_DEBUG
 
1336
    gchar str[48];
 
1337
#endif
 
1338
    MXFUL *uid;
 
1339
 
 
1340
    local_tag = GST_READ_UINT16_BE (data);
 
1341
    data += 2;
 
1342
 
 
1343
    if (g_hash_table_lookup (pack->mappings, GUINT_TO_POINTER (local_tag)))
 
1344
      continue;
 
1345
 
 
1346
    uid = g_slice_new (MXFUL);
 
1347
    memcpy (uid, data, 16);
 
1348
    data += 16;
 
1349
 
 
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));
 
1353
  }
 
1354
 
 
1355
  return TRUE;
 
1356
 
 
1357
error:
 
1358
  GST_DEBUG ("Invalid primer pack");
 
1359
  mxf_primer_pack_reset (pack);
 
1360
  return FALSE;
 
1361
}
 
1362
 
 
1363
void
 
1364
mxf_primer_pack_reset (MXFPrimerPack * pack)
 
1365
{
 
1366
  g_return_if_fail (pack != NULL);
 
1367
 
 
1368
  if (pack->mappings)
 
1369
    g_hash_table_destroy (pack->mappings);
 
1370
  if (pack->reverse_mappings)
 
1371
    g_hash_table_destroy (pack->reverse_mappings);
 
1372
 
 
1373
  memset (pack, 0, sizeof (MXFPrimerPack));
 
1374
 
 
1375
  pack->next_free_tag = 0x8000;
 
1376
}
 
1377
 
 
1378
guint16
 
1379
mxf_primer_pack_add_mapping (MXFPrimerPack * primer, guint16 local_tag,
 
1380
    const MXFUL * ul)
 
1381
{
 
1382
  MXFUL *uid;
 
1383
#ifndef GST_DISABLE_GST_DEBUG
 
1384
  gchar str[48];
 
1385
#endif
 
1386
  guint ltag_tmp = local_tag;
 
1387
 
 
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);
 
1391
  }
 
1392
 
 
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);
 
1397
  }
 
1398
 
 
1399
  if (primer->next_free_tag == 0xffff && ltag_tmp == 0) {
 
1400
    GST_ERROR ("Used too many dynamic tags");
 
1401
    return 0;
 
1402
  }
 
1403
 
 
1404
  if (ltag_tmp == 0) {
 
1405
    guint tmp;
 
1406
 
 
1407
    tmp = GPOINTER_TO_UINT (g_hash_table_lookup (primer->reverse_mappings, ul));
 
1408
    if (tmp == 0) {
 
1409
      ltag_tmp = primer->next_free_tag;
 
1410
      primer->next_free_tag++;
 
1411
    }
 
1412
  } else {
 
1413
    if (g_hash_table_lookup (primer->mappings, GUINT_TO_POINTER (ltag_tmp)))
 
1414
      return ltag_tmp;
 
1415
  }
 
1416
 
 
1417
  g_assert (ltag_tmp != 0);
 
1418
 
 
1419
  uid = g_slice_new (MXFUL);
 
1420
  memcpy (uid, ul, 16);
 
1421
 
 
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));
 
1428
 
 
1429
  return ltag_tmp;
 
1430
}
 
1431
 
 
1432
GstBuffer *
 
1433
mxf_primer_pack_to_buffer (const MXFPrimerPack * pack)
 
1434
{
 
1435
  guint slen;
 
1436
  guint8 ber[9];
 
1437
  GstBuffer *ret;
 
1438
  guint n;
 
1439
  guint8 *data;
 
1440
 
 
1441
  if (pack->mappings)
 
1442
    n = g_hash_table_size (pack->mappings);
 
1443
  else
 
1444
    n = 0;
 
1445
 
 
1446
  slen = mxf_ber_encode_size (8 + 18 * n, ber);
 
1447
 
 
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);
 
1451
 
 
1452
  data = GST_BUFFER_DATA (ret) + 16 + slen;
 
1453
 
 
1454
  GST_WRITE_UINT32_BE (data, n);
 
1455
  GST_WRITE_UINT32_BE (data + 4, 18);
 
1456
  data += 8;
 
1457
 
 
1458
  if (pack->mappings) {
 
1459
    guint local_tag;
 
1460
    MXFUL *ul;
 
1461
#if GLIB_CHECK_VERSION (2, 16, 0)
 
1462
    GHashTableIter iter;
 
1463
 
 
1464
    g_hash_table_iter_init (&iter, pack->mappings);
 
1465
#else
 
1466
    GList *l, *keys;
 
1467
 
 
1468
    keys = g_hash_table_get_keys (pack->mappings);
 
1469
#endif
 
1470
 
 
1471
#if GLIB_CHECK_VERSION (2, 16, 0)
 
1472
    while (g_hash_table_iter_next (&iter, (gpointer) & local_tag,
 
1473
            (gpointer) & ul)) {
 
1474
#else
 
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));
 
1478
#endif
 
1479
      GST_WRITE_UINT16_BE (data, local_tag);
 
1480
      memcpy (data + 2, ul, 16);
 
1481
      data += 18;
 
1482
    }
 
1483
 
 
1484
#if !GLIB_CHECK_VERSION (2, 16, 0)
 
1485
    g_list_free (keys);
 
1486
#endif
 
1487
  }
 
1488
 
 
1489
  return ret;
 
1490
}
 
1491
 
 
1492
/* structural metadata parsing */
 
1493
 
 
1494
gboolean
 
1495
mxf_local_tag_parse (const guint8 * data, guint size, guint16 * tag,
 
1496
    guint16 * tag_size, const guint8 ** tag_data)
 
1497
{
 
1498
  g_return_val_if_fail (data != NULL, FALSE);
 
1499
 
 
1500
  if (size < 4)
 
1501
    return FALSE;
 
1502
 
 
1503
  *tag = GST_READ_UINT16_BE (data);
 
1504
  *tag_size = GST_READ_UINT16_BE (data + 2);
 
1505
 
 
1506
  if (size < 4 + *tag_size)
 
1507
    return FALSE;
 
1508
 
 
1509
  *tag_data = data + 4;
 
1510
 
 
1511
  return TRUE;
 
1512
}
 
1513
 
 
1514
void
 
1515
mxf_local_tag_free (MXFLocalTag * tag)
 
1516
{
 
1517
  if (tag->g_slice)
 
1518
    g_slice_free1 (tag->size, tag->data);
 
1519
  else
 
1520
    g_free (tag->data);
 
1521
  g_slice_free (MXFLocalTag, tag);
 
1522
}
 
1523
 
 
1524
gboolean
 
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)
 
1528
{
 
1529
  MXFLocalTag *local_tag;
 
1530
  MXFUL *ul;
 
1531
 
 
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);
 
1536
 
 
1537
  if (*hash_table == NULL)
 
1538
    *hash_table =
 
1539
        g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
 
1540
        (GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) NULL,
 
1541
        (GDestroyNotify) mxf_local_tag_free);
 
1542
 
 
1543
  g_return_val_if_fail (*hash_table != NULL, FALSE);
 
1544
 
 
1545
  ul = (MXFUL *) g_hash_table_lookup (primer->mappings,
 
1546
      GUINT_TO_POINTER (((guint) tag)));
 
1547
 
 
1548
  if (ul) {
 
1549
#ifndef GST_DISABLE_GST_DEBUG
 
1550
    gchar str[48];
 
1551
#endif
 
1552
 
 
1553
    GST_DEBUG ("Adding local tag 0x%04x with UL %s and size %u", tag,
 
1554
        mxf_ul_to_string (ul, str), tag_size);
 
1555
 
 
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);
 
1560
 
 
1561
    g_hash_table_insert (*hash_table, &local_tag->ul, local_tag);
 
1562
  } else {
 
1563
    GST_WARNING ("Local tag with no entry in primer pack: 0x%04x", tag);
 
1564
  }
 
1565
 
 
1566
  return TRUE;
 
1567
}
 
1568
 
 
1569
gboolean
 
1570
mxf_local_tag_insert (MXFLocalTag * tag, GHashTable ** hash_table)
 
1571
{
 
1572
#ifndef GST_DISABLE_GST_DEBUG
 
1573
  gchar str[48];
 
1574
#endif
 
1575
 
 
1576
  g_return_val_if_fail (tag != NULL, FALSE);
 
1577
  g_return_val_if_fail (hash_table != NULL, FALSE);
 
1578
 
 
1579
  if (*hash_table == NULL)
 
1580
    *hash_table =
 
1581
        g_hash_table_new_full ((GHashFunc) mxf_ul_hash,
 
1582
        (GEqualFunc) mxf_ul_is_equal, (GDestroyNotify) NULL,
 
1583
        (GDestroyNotify) mxf_local_tag_free);
 
1584
 
 
1585
  g_return_val_if_fail (*hash_table != NULL, FALSE);
 
1586
 
 
1587
  GST_DEBUG ("Adding local tag with UL %s and size %u",
 
1588
      mxf_ul_to_string (&tag->ul, str), tag->size);
 
1589
 
 
1590
  g_hash_table_insert (*hash_table, &tag->ul, tag);
 
1591
 
 
1592
  return TRUE;
 
1593
}