~oah-dev/oah/gst-plugins-bad

« back to all changes in this revision

Viewing changes to gst/mxf/mxfparse.c

  • Committer: Haakon Sporsheim
  • Date: 2009-03-12 13:52:03 UTC
  • Revision ID: haakon.sporsheim@tandberg.com-20090312135203-i5k294hgkushb0mt
Initial import of git repository: git://anongit.freedesktop.org/gstreamer/gst-plugins-bad (tag: RELEASE-0_10_10)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GStreamer
 
2
 * Copyright (C) 2008 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 "mxfparse.h"
 
28
 
 
29
GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
 
30
#define GST_CAT_DEFAULT mxf_debug
 
31
 
 
32
/* SMPTE 377M 3.3: A value of 0 for every field means unknown timestamp */
 
33
static const MXFTimestamp mxf_timestamp_unknown = { 0, 0, 0, 0, 0, 0, 0 };
 
34
 
 
35
static const MXFUMID umid_zero = { {0,} };
 
36
static const MXFUL key_zero = { {0,} };
 
37
 
 
38
/* UL common to all MXF UL */
 
39
static const guint8 mxf_key[] = { 0x06, 0x0e, 0x2b, 0x34 };
 
40
 
 
41
/* SMPTE 377M 6.1 */
 
42
static const guint8 partition_pack_key[] =
 
43
    { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
 
44
  0x01
 
45
};
 
46
 
 
47
/* SMPTE 336M */
 
48
static const guint8 fill_key[] =
 
49
    { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x02, 0x10,
 
50
  0x01, 0x00, 0x00, 0x00
 
51
};
 
52
 
 
53
/* SMPTE 377M 8.1 */
 
54
static const guint8 primer_pack_key[] =
 
55
    { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
 
56
  0x01, 0x05, 0x01, 0x00
 
57
};
 
58
 
 
59
/* SMPTE 377M 8.6 */
 
60
static const guint8 metadata_key[] =
 
61
    { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01,
 
62
  0x01
 
63
};
 
64
 
 
65
static const guint8 random_index_pack_key[] =
 
66
    { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
 
67
  0x01, 0x11, 0x01, 0x00
 
68
};
 
69
 
 
70
static const guint8 index_table_segment_key[] =
 
71
    { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
 
72
  0x01, 0x10, 0x01, 0x00
 
73
};
 
74
 
 
75
gboolean
 
76
mxf_is_mxf_packet (const MXFUL * key)
 
77
{
 
78
  return (memcmp (key, mxf_key, 4) == 0);
 
79
}
 
80
 
 
81
/* SMPTE 377M 6.1: Check if this is a valid partition pack */
 
82
gboolean
 
83
mxf_is_partition_pack (const MXFUL * key)
 
84
{
 
85
  if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] >= 0x02
 
86
      && key->u[13] <= 0x04 && key->u[14] < 0x05 && key->u[15] == 0x00)
 
87
    return TRUE;
 
88
 
 
89
  return FALSE;
 
90
}
 
91
 
 
92
/* SMPTE 377M 6.2: header partition pack has byte 14 == 0x02 */
 
93
gboolean
 
94
mxf_is_header_partition_pack (const MXFUL * key)
 
95
{
 
96
  if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] == 0x02 &&
 
97
      key->u[14] < 0x05 && key->u[15] == 0x00)
 
98
    return TRUE;
 
99
 
 
100
  return FALSE;
 
101
}
 
102
 
 
103
/* SMPTE 377M 6.3: body partition pack has byte 14 == 0x03 */
 
104
gboolean
 
105
mxf_is_body_partition_pack (const MXFUL * key)
 
106
{
 
107
  if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] == 0x03 &&
 
108
      key->u[14] < 0x05 && key->u[15] == 0x00)
 
109
    return TRUE;
 
110
 
 
111
  return FALSE;
 
112
}
 
113
 
 
114
/* SMPTE 377M 6.4: footer partition pack has byte 14 == 0x04 */
 
115
gboolean
 
116
mxf_is_footer_partition_pack (const MXFUL * key)
 
117
{
 
118
  if (memcmp (key, partition_pack_key, 13) == 0 && key->u[13] == 0x04 &&
 
119
      key->u[14] < 0x05 && key->u[15] == 0x00)
 
120
    return TRUE;
 
121
 
 
122
  return FALSE;
 
123
}
 
124
 
 
125
gboolean
 
126
mxf_is_fill (const MXFUL * key)
 
127
{
 
128
  return (memcmp (key, fill_key, 16) == 0);
 
129
}
 
130
 
 
131
gboolean
 
132
mxf_is_primer_pack (const MXFUL * key)
 
133
{
 
134
  return (memcmp (key, primer_pack_key, 16) == 0);
 
135
}
 
136
 
 
137
gboolean
 
138
mxf_is_metadata (const MXFUL * key)
 
139
{
 
140
  return (memcmp (key, metadata_key, 13) == 0 && key->u[15] == 0x00);
 
141
}
 
142
 
 
143
/* SMPTE 377M 8.7.3 */
 
144
gboolean
 
145
mxf_is_descriptive_metadata (const MXFUL * key)
 
146
{
 
147
  return (memcmp (key, mxf_key, 4) == 0 &&
 
148
      key->u[4] == 0x02 &&
 
149
      key->u[6] == 0x01 &&
 
150
      key->u[7] == 0x01 &&
 
151
      key->u[8] == 0x0d &&
 
152
      key->u[9] == 0x01 && key->u[10] == 0x04 && key->u[11] == 0x01);
 
153
}
 
154
 
 
155
gboolean
 
156
mxf_is_random_index_pack (const MXFUL * key)
 
157
{
 
158
  return (memcmp (key, random_index_pack_key, 16) == 0);
 
159
}
 
160
 
 
161
gboolean
 
162
mxf_is_index_table_segment (const MXFUL * key)
 
163
{
 
164
  return (memcmp (key, index_table_segment_key, 16) == 0);
 
165
}
 
166
 
 
167
/* SMPTE 379M 6.2.1 */
 
168
gboolean
 
169
mxf_is_generic_container_system_item (const MXFUL * key)
 
170
{
 
171
  return (memcmp (key, mxf_key, 4) == 0 && key->u[4] == 0x02
 
172
      && key->u[6] == 0x01 && key->u[8] == 0x0d && key->u[9] == 0x01
 
173
      && key->u[10] == 0x03 && key->u[11] == 0x01 && (key->u[12] == 0x04
 
174
          || key->u[12] == 0x14));
 
175
}
 
176
 
 
177
/* SMPTE 379M 7.1 */
 
178
gboolean
 
179
mxf_is_generic_container_essence_element (const MXFUL * key)
 
180
{
 
181
  return (memcmp (key, mxf_key, 4) == 0 && key->u[4] == 0x01
 
182
      && key->u[5] == 0x02 && key->u[6] == 0x01 && key->u[8] == 0x0d
 
183
      && key->u[9] == 0x01 && key->u[10] == 0x03 && key->u[11] == 0x01
 
184
      && (key->u[12] == 0x05 || key->u[12] == 0x06 || key->u[12] == 0x07
 
185
          || key->u[12] == 0x15 || key->u[12] == 0x16 || key->u[12] == 0x17
 
186
          || key->u[12] == 0x18));
 
187
}
 
188
 
 
189
/* SMPTE 379M 8 */
 
190
gboolean
 
191
mxf_is_generic_container_essence_container_label (const MXFUL * key)
 
192
{
 
193
  return (key->u[0] == 0x06 &&
 
194
      key->u[1] == 0x0e &&
 
195
      key->u[2] == 0x2b &&
 
196
      key->u[3] == 0x34 &&
 
197
      key->u[4] == 0x04 &&
 
198
      key->u[5] == 0x01 &&
 
199
      key->u[6] == 0x01 &&
 
200
      key->u[8] == 0x0d &&
 
201
      key->u[9] == 0x01 &&
 
202
      key->u[10] == 0x03 &&
 
203
      key->u[11] == 0x01 && (key->u[12] == 0x01 || key->u[12] == 0x02));
 
204
}
 
205
 
 
206
gboolean
 
207
mxf_ul_is_equal (const MXFUL * a, const MXFUL * b)
 
208
{
 
209
  return (memcmp (a, b, 16) == 0);
 
210
}
 
211
 
 
212
gboolean
 
213
mxf_ul_is_zero (const MXFUL * key)
 
214
{
 
215
  return (memcmp (key, &key_zero, 16) == 0);
 
216
}
 
217
 
 
218
gchar *
 
219
mxf_ul_to_string (const MXFUL * key, gchar str[48])
 
220
{
 
221
  g_return_val_if_fail (key != NULL, NULL);
 
222
  g_return_val_if_fail (str != NULL, NULL);
 
223
 
 
224
  g_snprintf (str, 48,
 
225
      "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
 
226
      key->u[0], key->u[1], key->u[2], key->u[3], key->u[4], key->u[5],
 
227
      key->u[6], key->u[7], key->u[8], key->u[9], key->u[10], key->u[11],
 
228
      key->u[12], key->u[13], key->u[14], key->u[15]);
 
229
 
 
230
  return str;
 
231
}
 
232
 
 
233
gboolean
 
234
mxf_umid_is_equal (const MXFUMID * a, const MXFUMID * b)
 
235
{
 
236
  return (memcmp (a, b, 32) == 0);
 
237
}
 
238
 
 
239
gboolean
 
240
mxf_umid_is_zero (const MXFUMID * umid)
 
241
{
 
242
  return (memcmp (umid, &umid_zero, 32) == 0);
 
243
}
 
244
 
 
245
gchar *
 
246
mxf_umid_to_string (const MXFUMID * key, gchar str[96])
 
247
{
 
248
  g_return_val_if_fail (key != NULL, NULL);
 
249
  g_return_val_if_fail (str != NULL, NULL);
 
250
 
 
251
  g_snprintf (str, 96,
 
252
      "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x."
 
253
      "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
 
254
      key->u[0], key->u[1], key->u[2], key->u[3], key->u[4], key->u[5],
 
255
      key->u[6], key->u[7], key->u[8], key->u[9], key->u[10], key->u[11],
 
256
      key->u[12], key->u[13], key->u[14], key->u[15],
 
257
      key->u[16],
 
258
      key->u[17],
 
259
      key->u[18],
 
260
      key->u[19],
 
261
      key->u[20],
 
262
      key->u[21],
 
263
      key->u[22],
 
264
      key->u[23],
 
265
      key->u[24],
 
266
      key->u[25],
 
267
      key->u[26], key->u[27], key->u[28], key->u[29], key->u[30], key->u[31]
 
268
      );
 
269
 
 
270
  return str;
 
271
}
 
272
 
 
273
MXFUMID *
 
274
mxf_umid_from_string (const gchar * str, MXFUMID * umid)
 
275
{
 
276
  gint len;
 
277
  guint i, j;
 
278
 
 
279
  g_return_val_if_fail (str != NULL, NULL);
 
280
  len = strlen (str);
 
281
 
 
282
  memset (umid, 0, 32);
 
283
 
 
284
  if (len != 95) {
 
285
    GST_ERROR ("Invalid UMID string length %d", len);
 
286
    return NULL;
 
287
  }
 
288
 
 
289
  for (i = 0, j = 0; i < 32; i++) {
 
290
    if (!g_ascii_isxdigit (str[j]) ||
 
291
        !g_ascii_isxdigit (str[j + 1]) ||
 
292
        (str[j + 2] != '.' && str[j + 2] != '\0')) {
 
293
      GST_ERROR ("Invalid UMID string '%s'", str);
 
294
      return NULL;
 
295
    }
 
296
 
 
297
    umid->u[i] =
 
298
        (g_ascii_xdigit_value (str[j]) << 4) | (g_ascii_xdigit_value (str[j +
 
299
                1]));
 
300
    j += 3;
 
301
  }
 
302
  return umid;
 
303
}
 
304
 
 
305
static guint
 
306
gst_mxf_ul_hash (const MXFUL * key)
 
307
{
 
308
  guint32 ret = 0;
 
309
  guint i;
 
310
 
 
311
  for (i = 0; i < 4; i++)
 
312
    ret ^=
 
313
        (key->u[i * 4 + 0] << 24) | (key->u[i * 4 + 1] << 16) | (key->u[i * 4 +
 
314
            2] << 8) | (key->u[i * 4 + 3] << 0);
 
315
 
 
316
  return ret;
 
317
}
 
318
 
 
319
static gboolean
 
320
gst_mxf_ul_equal (const MXFUL * a, const MXFUL * b)
 
321
{
 
322
  return (memcmp (a, b, 16) == 0);
 
323
}
 
324
 
 
325
gboolean
 
326
mxf_timestamp_parse (MXFTimestamp * timestamp, const guint8 * data, guint size)
 
327
{
 
328
  g_return_val_if_fail (data != NULL, FALSE);
 
329
  g_return_val_if_fail (timestamp != NULL, FALSE);
 
330
 
 
331
  memset (timestamp, 0, sizeof (MXFTimestamp));
 
332
 
 
333
  if (size < 8)
 
334
    return FALSE;
 
335
 
 
336
  timestamp->year = GST_READ_UINT16_BE (data);
 
337
  timestamp->month = GST_READ_UINT8 (data + 2);
 
338
  timestamp->day = GST_READ_UINT8 (data + 3);
 
339
  timestamp->hour = GST_READ_UINT8 (data + 4);
 
340
  timestamp->minute = GST_READ_UINT8 (data + 5);
 
341
  timestamp->second = GST_READ_UINT8 (data + 6);
 
342
  timestamp->quarter_msecond = GST_READ_UINT8 (data + 7);
 
343
 
 
344
  return TRUE;
 
345
}
 
346
 
 
347
gboolean
 
348
mxf_timestamp_is_unknown (const MXFTimestamp * a)
 
349
{
 
350
  return (memcmp (a, &mxf_timestamp_unknown, sizeof (MXFTimestamp)) == 0);
 
351
}
 
352
 
 
353
gint
 
354
mxf_timestamp_compare (const MXFTimestamp * a, const MXFTimestamp * b)
 
355
{
 
356
  gint diff;
 
357
 
 
358
  if ((diff = a->year - b->year) != 0)
 
359
    return diff;
 
360
  else if ((diff = a->month - b->month) != 0)
 
361
    return diff;
 
362
  else if ((diff = a->day - b->day) != 0)
 
363
    return diff;
 
364
  else if ((diff = a->hour - b->hour) != 0)
 
365
    return diff;
 
366
  else if ((diff = a->minute - b->minute) != 0)
 
367
    return diff;
 
368
  else if ((diff = a->second - b->second) != 0)
 
369
    return diff;
 
370
  else if ((diff = a->quarter_msecond - b->quarter_msecond) != 0)
 
371
    return diff;
 
372
  else
 
373
    return 0;
 
374
}
 
375
 
 
376
gboolean
 
377
mxf_fraction_parse (MXFFraction * fraction, const guint8 * data, guint size)
 
378
{
 
379
  g_return_val_if_fail (fraction != NULL, FALSE);
 
380
  g_return_val_if_fail (data != NULL, FALSE);
 
381
 
 
382
  memset (fraction, 0, sizeof (MXFFraction));
 
383
 
 
384
  if (size < 8)
 
385
    return FALSE;
 
386
 
 
387
  fraction->n = GST_READ_UINT32_BE (data);
 
388
  fraction->d = GST_READ_UINT32_BE (data + 4);
 
389
 
 
390
  return TRUE;
 
391
}
 
392
 
 
393
gchar *
 
394
mxf_utf16_to_utf8 (const guint8 * data, guint size)
 
395
{
 
396
  gchar *ret;
 
397
  GError *error = NULL;
 
398
 
 
399
  ret =
 
400
      g_convert ((const gchar *) data, size, "UTF-8", "UTF-16BE", NULL, NULL,
 
401
      &error);
 
402
 
 
403
  if (ret == NULL) {
 
404
    GST_WARNING ("UTF-16-BE to UTF-8 conversion failed: %s", error->message);
 
405
    g_error_free (error);
 
406
    return NULL;
 
407
  }
 
408
 
 
409
  return ret;
 
410
}
 
411
 
 
412
gboolean
 
413
mxf_product_version_parse (MXFProductVersion * product_version,
 
414
    const guint8 * data, guint size)
 
415
{
 
416
  g_return_val_if_fail (product_version != NULL, FALSE);
 
417
  g_return_val_if_fail (data != NULL, FALSE);
 
418
 
 
419
  memset (product_version, 0, sizeof (MXFProductVersion));
 
420
 
 
421
  if (size < 9)
 
422
    return FALSE;
 
423
 
 
424
  product_version->major = GST_READ_UINT16_BE (data);
 
425
  product_version->minor = GST_READ_UINT16_BE (data + 2);
 
426
  product_version->patch = GST_READ_UINT16_BE (data + 4);
 
427
  product_version->build = GST_READ_UINT16_BE (data + 6);
 
428
 
 
429
  /* Avid writes a 9 byte product version */
 
430
  if (size == 9)
 
431
    product_version->release = GST_READ_UINT8 (data + 8);
 
432
  else
 
433
    product_version->release = GST_READ_UINT16_BE (data + 8);
 
434
 
 
435
  return TRUE;
 
436
}
 
437
 
 
438
/* SMPTE 377M 6.1, Table 2 */
 
439
gboolean
 
440
mxf_partition_pack_parse (const MXFUL * key, MXFPartitionPack * pack,
 
441
    const guint8 * data, guint size)
 
442
{
 
443
  guint i;
 
444
#ifndef GST_DISABLE_GST_DEBUG
 
445
  gchar str[48];
 
446
#endif
 
447
 
 
448
  g_return_val_if_fail (data != NULL, FALSE);
 
449
  g_return_val_if_fail (size >= 84, FALSE);
 
450
 
 
451
  memset (pack, 0, sizeof (MXFPartitionPack));
 
452
 
 
453
  GST_DEBUG ("Parsing partition pack:");
 
454
 
 
455
  if (key->u[13] == 0x02)
 
456
    pack->type = MXF_PARTITION_PACK_HEADER;
 
457
  else if (key->u[13] == 0x03)
 
458
    pack->type = MXF_PARTITION_PACK_BODY;
 
459
  else if (key->u[13] == 0x04)
 
460
    pack->type = MXF_PARTITION_PACK_FOOTER;
 
461
 
 
462
  GST_DEBUG ("  type = %s",
 
463
      (pack->type == MXF_PARTITION_PACK_HEADER) ? "header" : (pack->type ==
 
464
          MXF_PARTITION_PACK_BODY) ? "body" : "footer");
 
465
 
 
466
  pack->closed = (key->u[14] == 0x02 || key->u[14] == 0x04);
 
467
  pack->complete = (key->u[14] == 0x03 || key->u[14] == 0x04);
 
468
 
 
469
  GST_DEBUG ("  closed = %s, complete = %s", (pack->closed) ? "yes" : "no",
 
470
      (pack->complete) ? "yes" : "no");
 
471
 
 
472
  pack->major_version = GST_READ_UINT16_BE (data);
 
473
  if (pack->major_version != 1)
 
474
    goto error;
 
475
  data += 2;
 
476
  size -= 2;
 
477
 
 
478
  pack->minor_version = GST_READ_UINT16_BE (data);
 
479
  data += 2;
 
480
  size -= 2;
 
481
 
 
482
  GST_DEBUG ("  MXF version = %u.%u", pack->major_version, pack->minor_version);
 
483
 
 
484
  pack->kag_size = GST_READ_UINT32_BE (data);
 
485
  data += 4;
 
486
  size -= 4;
 
487
 
 
488
  GST_DEBUG ("  KAG size = %u", pack->kag_size);
 
489
 
 
490
  pack->this_partition = GST_READ_UINT64_BE (data);
 
491
  data += 8;
 
492
  size -= 8;
 
493
 
 
494
  GST_DEBUG ("  this partition offset = %" G_GUINT64_FORMAT,
 
495
      pack->this_partition);
 
496
 
 
497
  pack->prev_partition = GST_READ_UINT64_BE (data);
 
498
  data += 8;
 
499
  size -= 8;
 
500
 
 
501
  GST_DEBUG ("  previous partition offset = %" G_GUINT64_FORMAT,
 
502
      pack->prev_partition);
 
503
 
 
504
  pack->footer_partition = GST_READ_UINT64_BE (data);
 
505
  data += 8;
 
506
  size -= 8;
 
507
 
 
508
  GST_DEBUG ("  footer partition offset = %" G_GUINT64_FORMAT,
 
509
      pack->footer_partition);
 
510
 
 
511
  pack->header_byte_count = GST_READ_UINT64_BE (data);
 
512
  data += 8;
 
513
  size -= 8;
 
514
 
 
515
  GST_DEBUG ("  header byte count = %" G_GUINT64_FORMAT,
 
516
      pack->header_byte_count);
 
517
 
 
518
  pack->index_byte_count = GST_READ_UINT64_BE (data);
 
519
  data += 8;
 
520
  size -= 8;
 
521
 
 
522
  pack->index_sid = GST_READ_UINT32_BE (data);
 
523
  data += 4;
 
524
  size -= 4;
 
525
 
 
526
  GST_DEBUG ("  index sid = %u, size = %" G_GUINT64_FORMAT, pack->index_sid,
 
527
      pack->index_byte_count);
 
528
 
 
529
  pack->body_offset = GST_READ_UINT64_BE (data);
 
530
  data += 8;
 
531
  size -= 8;
 
532
 
 
533
  pack->body_sid = GST_READ_UINT32_BE (data);
 
534
  data += 4;
 
535
  size -= 4;
 
536
 
 
537
  GST_DEBUG ("  body sid = %u, offset = %" G_GUINT64_FORMAT, pack->body_sid,
 
538
      pack->body_offset);
 
539
 
 
540
  memcpy (&pack->operational_pattern, data, 16);
 
541
  data += 16;
 
542
  size -= 16;
 
543
 
 
544
  GST_DEBUG ("  operational pattern = %s",
 
545
      mxf_ul_to_string (&pack->operational_pattern, str));
 
546
 
 
547
  pack->n_essence_containers = GST_READ_UINT32_BE (data);
 
548
  data += 4;
 
549
  size -= 4;
 
550
 
 
551
  GST_DEBUG ("  number of essence containers = %u", pack->n_essence_containers);
 
552
 
 
553
  if (GST_READ_UINT32_BE (data) != 16)
 
554
    goto error;
 
555
  data += 4;
 
556
  size -= 4;
 
557
 
 
558
  if (size < 16 * pack->n_essence_containers)
 
559
    goto error;
 
560
 
 
561
  if (pack->n_essence_containers) {
 
562
    pack->essence_containers = g_new (MXFUL, pack->n_essence_containers);
 
563
    for (i = 0; i < pack->n_essence_containers; i++) {
 
564
      memcpy (&pack->essence_containers[i], data + i * 16, 16);
 
565
      GST_DEBUG ("  essence container %u = %s", i,
 
566
          mxf_ul_to_string (&pack->essence_containers[i], str));
 
567
    }
 
568
  }
 
569
 
 
570
  pack->valid = TRUE;
 
571
 
 
572
  return TRUE;
 
573
 
 
574
error:
 
575
  GST_ERROR ("Invalid partition pack");
 
576
 
 
577
  mxf_partition_pack_reset (pack);
 
578
  return FALSE;
 
579
}
 
580
 
 
581
void
 
582
mxf_partition_pack_reset (MXFPartitionPack * pack)
 
583
{
 
584
  g_return_if_fail (pack != NULL);
 
585
 
 
586
  g_free (pack->essence_containers);
 
587
 
 
588
  memset (pack, 0, sizeof (MXFPartitionPack));
 
589
}
 
590
 
 
591
/* SMPTE 377M 11.1 */
 
592
gboolean
 
593
mxf_random_index_pack_parse (const MXFUL * key, const guint8 * data, guint size,
 
594
    GArray ** array)
 
595
{
 
596
  guint len, i;
 
597
  MXFRandomIndexPackEntry entry;
 
598
 
 
599
  g_return_val_if_fail (data != NULL, FALSE);
 
600
  g_return_val_if_fail (array != NULL, FALSE);
 
601
 
 
602
  if (size < 4)
 
603
    return FALSE;
 
604
 
 
605
  if ((size - 4) % 12 != 0)
 
606
    return FALSE;
 
607
 
 
608
  GST_DEBUG ("Parsing random index pack:");
 
609
 
 
610
  len = (size - 4) / 12;
 
611
 
 
612
  GST_DEBUG ("  number of entries = %u", len);
 
613
 
 
614
  *array =
 
615
      g_array_sized_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry), len);
 
616
 
 
617
  for (i = 0; i < len; i++) {
 
618
    entry.body_sid = GST_READ_UINT32_BE (data);
 
619
    entry.offset = GST_READ_UINT64_BE (data + 4);
 
620
    data += 12;
 
621
 
 
622
    GST_DEBUG ("  entry %u = body sid %u at offset %" G_GUINT64_FORMAT, i,
 
623
        entry.body_sid, entry.offset);
 
624
 
 
625
    g_array_append_val (*array, entry);
 
626
  }
 
627
 
 
628
  return TRUE;
 
629
}
 
630
 
 
631
/* SMPTE 377M 10.2.3 */
 
632
gboolean
 
633
mxf_index_table_segment_parse (const MXFUL * key,
 
634
    MXFIndexTableSegment * segment, const MXFPrimerPack * primer,
 
635
    const guint8 * data, guint size)
 
636
{
 
637
#ifndef GST_DISABLE_GST_DEBUG
 
638
  gchar str[48];
 
639
#endif
 
640
  guint16 tag, tag_size;
 
641
  const guint8 *tag_data;
 
642
 
 
643
  g_return_val_if_fail (key != NULL, FALSE);
 
644
  g_return_val_if_fail (data != NULL, FALSE);
 
645
  g_return_val_if_fail (primer != NULL, FALSE);
 
646
 
 
647
  memset (segment, 0, sizeof (MXFIndexTableSegment));
 
648
 
 
649
  if (size < 70)
 
650
    return FALSE;
 
651
 
 
652
  GST_DEBUG ("Parsing index table segment:");
 
653
 
 
654
  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
 
655
    if (tag_size == 0 || tag == 0x0000)
 
656
      goto next;
 
657
 
 
658
    switch (tag) {
 
659
      case 0x3c0a:
 
660
        if (tag_size != 16)
 
661
          goto error;
 
662
        memcpy (&segment->instance_id, tag_data, 16);
 
663
        GST_DEBUG ("  instance id = %s",
 
664
            mxf_ul_to_string (&segment->instance_id, str));
 
665
        break;
 
666
      case 0x3f0b:
 
667
        if (!mxf_fraction_parse (&segment->index_edit_rate, tag_data, tag_size))
 
668
          goto error;
 
669
        GST_DEBUG ("  index edit rate = %d/%d", segment->index_edit_rate.n,
 
670
            segment->index_edit_rate.d);
 
671
        break;
 
672
      case 0x3f0c:
 
673
        if (tag_size != 8)
 
674
          goto error;
 
675
        segment->index_start_position = GST_READ_UINT64_BE (tag_data);
 
676
        GST_DEBUG ("  index start position = %" G_GINT64_FORMAT,
 
677
            segment->index_start_position);
 
678
        break;
 
679
      case 0x3f0d:
 
680
        if (tag_size != 8)
 
681
          goto error;
 
682
        segment->index_duration = GST_READ_UINT64_BE (tag_data);
 
683
        GST_DEBUG ("  index duration = %" G_GINT64_FORMAT,
 
684
            segment->index_duration);
 
685
        break;
 
686
      case 0x3f05:
 
687
        if (tag_size != 4)
 
688
          goto error;
 
689
        segment->edit_unit_byte_count = GST_READ_UINT32_BE (tag_data);
 
690
        GST_DEBUG ("  edit unit byte count = %u",
 
691
            segment->edit_unit_byte_count);
 
692
        break;
 
693
      case 0x3f06:
 
694
        if (tag_size != 4)
 
695
          goto error;
 
696
        segment->index_sid = GST_READ_UINT32_BE (tag_data);
 
697
        GST_DEBUG ("  index sid = %u", segment->index_sid);
 
698
        break;
 
699
      case 0x3f07:
 
700
        if (tag_size != 4)
 
701
          goto error;
 
702
        segment->body_sid = GST_READ_UINT32_BE (tag_data);
 
703
        GST_DEBUG ("  body sid = %u", segment->body_sid);
 
704
        break;
 
705
      case 0x3f08:
 
706
        if (tag_size != 1)
 
707
          goto error;
 
708
        segment->slice_count = GST_READ_UINT8 (tag_data);
 
709
        GST_DEBUG ("  slice count = %u", segment->slice_count);
 
710
        break;
 
711
      case 0x3f0e:
 
712
        if (tag_size != 1)
 
713
          goto error;
 
714
        segment->pos_table_count = GST_READ_UINT8 (tag_data);
 
715
        GST_DEBUG ("  pos table count = %u", segment->pos_table_count);
 
716
        break;
 
717
      case 0x3f09:{
 
718
        guint len, i;
 
719
 
 
720
        if (tag_size < 8)
 
721
          goto error;
 
722
 
 
723
        len = GST_READ_UINT32_BE (tag_data);
 
724
        segment->n_delta_entries = len;
 
725
        GST_DEBUG ("  number of delta entries = %u", segment->n_delta_entries);
 
726
        if (len == 0)
 
727
          goto next;
 
728
        tag_data += 4;
 
729
        tag_size -= 4;
 
730
 
 
731
        if (GST_READ_UINT32_BE (tag_data) != 6)
 
732
          goto error;
 
733
 
 
734
        tag_data += 4;
 
735
        tag_size -= 4;
 
736
 
 
737
        if (tag_size < len * 6)
 
738
          goto error;
 
739
 
 
740
        segment->delta_entries = g_new (MXFDeltaEntry, len);
 
741
 
 
742
        for (i = 0; i < len; i++) {
 
743
          GST_DEBUG ("    delta entry %u:", i);
 
744
 
 
745
          segment->delta_entries[i].pos_table_index = GST_READ_UINT8 (tag_data);
 
746
          tag_data += 1;
 
747
          tag_size -= 1;
 
748
          GST_DEBUG ("    pos table index = %d",
 
749
              segment->delta_entries[i].pos_table_index);
 
750
 
 
751
          segment->delta_entries[i].slice = GST_READ_UINT8 (tag_data);
 
752
          tag_data += 1;
 
753
          tag_size -= 1;
 
754
          GST_DEBUG ("    slice = %u", segment->delta_entries[i].slice);
 
755
 
 
756
          segment->delta_entries[i].element_delta =
 
757
              GST_READ_UINT32_BE (tag_data);
 
758
          tag_data += 4;
 
759
          tag_size -= 4;
 
760
          GST_DEBUG ("    element delta = %u",
 
761
              segment->delta_entries[i].element_delta);
 
762
        }
 
763
        break;
 
764
      }
 
765
      case 0x3f0a:{
 
766
        guint len, i, j;
 
767
 
 
768
        if (tag_size < 8)
 
769
          goto error;
 
770
 
 
771
        len = GST_READ_UINT32_BE (tag_data);
 
772
        segment->n_index_entries = len;
 
773
        GST_DEBUG ("  number of index entries = %u", segment->n_index_entries);
 
774
        if (len == 0)
 
775
          goto next;
 
776
        tag_data += 4;
 
777
        tag_size -= 4;
 
778
 
 
779
        if (GST_READ_UINT32_BE (tag_data) !=
 
780
            (11 + 4 * segment->slice_count + 8 * segment->pos_table_count))
 
781
          goto error;
 
782
 
 
783
        tag_data += 4;
 
784
        tag_size -= 4;
 
785
 
 
786
        if (tag_size <
 
787
            len * (11 + 4 * segment->slice_count +
 
788
                8 * segment->pos_table_count))
 
789
          goto error;
 
790
 
 
791
        segment->index_entries = g_new (MXFIndexEntry, len);
 
792
 
 
793
        for (i = 0; i < len; i++) {
 
794
          MXFIndexEntry *entry = &segment->index_entries[i];
 
795
 
 
796
          GST_DEBUG ("    index entry %u:", i);
 
797
 
 
798
          entry->temporal_offset = GST_READ_UINT8 (tag_data);
 
799
          tag_data += 1;
 
800
          tag_size -= 1;
 
801
          GST_DEBUG ("    temporal offset = %d", entry->temporal_offset);
 
802
 
 
803
          entry->key_frame_offset = GST_READ_UINT8 (tag_data);
 
804
          tag_data += 1;
 
805
          tag_size -= 1;
 
806
          GST_DEBUG ("    keyframe offset = %d", entry->key_frame_offset);
 
807
 
 
808
          entry->flags = GST_READ_UINT8 (tag_data);
 
809
          tag_data += 1;
 
810
          tag_size -= 1;
 
811
          GST_DEBUG ("    flags = 0x%02x", entry->flags);
 
812
 
 
813
          entry->stream_offset = GST_READ_UINT64_BE (tag_data);
 
814
          tag_data += 8;
 
815
          tag_size -= 8;
 
816
          GST_DEBUG ("    stream offset = %" G_GUINT64_FORMAT,
 
817
              entry->stream_offset);
 
818
 
 
819
          for (j = 0; j < segment->slice_count; j++) {
 
820
            entry->slice_offset[j] = GST_READ_UINT32_BE (tag_data);
 
821
            tag_data += 4;
 
822
            tag_size -= 4;
 
823
            GST_DEBUG ("    slice %u offset = %u", j, entry->slice_offset[j]);
 
824
          }
 
825
 
 
826
          for (j = 0; j < segment->pos_table_count; j++) {
 
827
            mxf_fraction_parse (&entry->pos_table[j], tag_data, tag_size);
 
828
            tag_data += 8;
 
829
            tag_size -= 8;
 
830
            GST_DEBUG ("    pos table %u = %d/%d", j, entry->pos_table[j].n,
 
831
                entry->pos_table[j].d);
 
832
          }
 
833
        }
 
834
        break;
 
835
      }
 
836
      default:
 
837
        if (!mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size,
 
838
                &segment->other_tags))
 
839
          goto error;
 
840
        break;
 
841
    }
 
842
 
 
843
  next:
 
844
    data += 4 + tag_size;
 
845
    size -= 4 + tag_size;
 
846
  }
 
847
  return TRUE;
 
848
 
 
849
error:
 
850
  GST_ERROR ("Invalid index table segment");
 
851
  return FALSE;
 
852
}
 
853
 
 
854
void
 
855
mxf_index_table_segment_reset (MXFIndexTableSegment * segment)
 
856
{
 
857
  guint i;
 
858
  g_return_if_fail (segment != NULL);
 
859
 
 
860
  for (i = 0; i < segment->n_index_entries; i++) {
 
861
    g_free (segment->index_entries[i].slice_offset);
 
862
    g_free (segment->index_entries[i].pos_table);
 
863
  }
 
864
  g_free (segment->index_entries);
 
865
  g_free (segment->delta_entries);
 
866
 
 
867
  if (segment->other_tags)
 
868
    g_hash_table_destroy (segment->other_tags);
 
869
 
 
870
  memset (segment, 0, sizeof (MXFIndexTableSegment));
 
871
}
 
872
 
 
873
/* SMPTE 377M 8.2 Table 1 and 2 */
 
874
 
 
875
static void
 
876
_mxf_mapping_ul_free (MXFUL * ul)
 
877
{
 
878
  g_slice_free (MXFUL, ul);
 
879
}
 
880
 
 
881
gboolean
 
882
mxf_primer_pack_parse (const MXFUL * key, MXFPrimerPack * pack,
 
883
    const guint8 * data, guint size)
 
884
{
 
885
  guint i;
 
886
  guint32 n;
 
887
 
 
888
  g_return_val_if_fail (data != NULL, FALSE);
 
889
  g_return_val_if_fail (size >= 8, FALSE);
 
890
 
 
891
  memset (pack, 0, sizeof (MXFPrimerPack));
 
892
 
 
893
  GST_DEBUG ("Parsing primer pack:");
 
894
 
 
895
  pack->mappings =
 
896
      g_hash_table_new_full (g_direct_hash, g_direct_equal,
 
897
      (GDestroyNotify) NULL, (GDestroyNotify) _mxf_mapping_ul_free);
 
898
 
 
899
  n = GST_READ_UINT32_BE (data);
 
900
  data += 4;
 
901
 
 
902
  GST_DEBUG ("  number of mappings = %u", n);
 
903
 
 
904
  if (GST_READ_UINT32_BE (data) != 18)
 
905
    goto error;
 
906
  data += 4;
 
907
 
 
908
  if (size < 8 + n * 18)
 
909
    goto error;
 
910
 
 
911
  for (i = 0; i < n; i++) {
 
912
    guint local_tag;
 
913
#ifndef GST_DISABLE_GST_DEBUG
 
914
    gchar str[48];
 
915
#endif
 
916
    MXFUL *uid;
 
917
 
 
918
    local_tag = GST_READ_UINT16_BE (data);
 
919
    data += 2;
 
920
 
 
921
    if (g_hash_table_lookup (pack->mappings, GUINT_TO_POINTER (local_tag)))
 
922
      continue;
 
923
 
 
924
    uid = g_slice_new (MXFUL);
 
925
    memcpy (uid, data, 16);
 
926
    data += 16;
 
927
 
 
928
    g_hash_table_insert (pack->mappings, GUINT_TO_POINTER (local_tag), uid);
 
929
    GST_DEBUG ("  Adding mapping = 0x%04x -> %s", local_tag,
 
930
        mxf_ul_to_string (uid, str));
 
931
  }
 
932
 
 
933
  pack->valid = TRUE;
 
934
 
 
935
  return TRUE;
 
936
 
 
937
error:
 
938
  GST_DEBUG ("Invalid primer pack");
 
939
  mxf_primer_pack_reset (pack);
 
940
  return FALSE;
 
941
}
 
942
 
 
943
void
 
944
mxf_primer_pack_reset (MXFPrimerPack * pack)
 
945
{
 
946
  g_return_if_fail (pack != NULL);
 
947
 
 
948
  if (pack->mappings)
 
949
    g_hash_table_destroy (pack->mappings);
 
950
  memset (pack, 0, sizeof (MXFPrimerPack));
 
951
}
 
952
 
 
953
/* structural metadata parsing */
 
954
 
 
955
gboolean
 
956
mxf_local_tag_parse (const guint8 * data, guint size, guint16 * tag,
 
957
    guint16 * tag_size, const guint8 ** tag_data)
 
958
{
 
959
  g_return_val_if_fail (data != NULL, FALSE);
 
960
 
 
961
  if (size < 4)
 
962
    return FALSE;
 
963
 
 
964
  *tag = GST_READ_UINT16_BE (data);
 
965
  *tag_size = GST_READ_UINT16_BE (data + 2);
 
966
 
 
967
  if (size < 4 + *tag_size)
 
968
    return FALSE;
 
969
 
 
970
  *tag_data = data + 4;
 
971
 
 
972
  return TRUE;
 
973
}
 
974
 
 
975
void
 
976
gst_mxf_local_tag_free (MXFLocalTag * tag)
 
977
{
 
978
  g_free (tag->data);
 
979
  g_slice_free (MXFLocalTag, tag);
 
980
}
 
981
 
 
982
gboolean
 
983
mxf_local_tag_add_to_hash_table (const MXFPrimerPack * primer,
 
984
    guint16 tag, const guint8 * tag_data, guint16 tag_size,
 
985
    GHashTable ** hash_table)
 
986
{
 
987
  MXFLocalTag *local_tag;
 
988
  MXFUL *key;
 
989
 
 
990
  g_return_val_if_fail (primer != NULL, FALSE);
 
991
  g_return_val_if_fail (tag_data != NULL, FALSE);
 
992
  g_return_val_if_fail (hash_table != NULL, FALSE);
 
993
  g_return_val_if_fail (primer->mappings != NULL, FALSE);
 
994
 
 
995
  if (*hash_table == NULL)
 
996
    *hash_table =
 
997
        g_hash_table_new_full ((GHashFunc) gst_mxf_ul_hash,
 
998
        (GEqualFunc) gst_mxf_ul_equal, (GDestroyNotify) NULL,
 
999
        (GDestroyNotify) gst_mxf_local_tag_free);
 
1000
 
 
1001
  g_return_val_if_fail (*hash_table != NULL, FALSE);
 
1002
 
 
1003
  key = (MXFUL *) g_hash_table_lookup (primer->mappings,
 
1004
      GUINT_TO_POINTER (((guint) tag)));
 
1005
 
 
1006
  if (key) {
 
1007
#ifndef GST_DISABLE_GST_DEBUG
 
1008
    gchar str[48];
 
1009
#endif
 
1010
 
 
1011
    GST_DEBUG ("Adding local tag 0x%04x with UL %s and size %u", tag,
 
1012
        mxf_ul_to_string (key, str), tag_size);
 
1013
 
 
1014
    local_tag = g_slice_new (MXFLocalTag);
 
1015
    memcpy (&local_tag->key, key, sizeof (MXFUL));
 
1016
    local_tag->size = tag_size;
 
1017
    local_tag->data = g_memdup (tag_data, tag_size);
 
1018
 
 
1019
    g_hash_table_insert (*hash_table, &local_tag->key, local_tag);
 
1020
  } else {
 
1021
    GST_WARNING ("Local tag with no entry in primer pack: 0x%04x", tag);
 
1022
  }
 
1023
 
 
1024
  return TRUE;
 
1025
}
 
1026
 
 
1027
static GSList *_mxf_essence_element_handler_registry = NULL;
 
1028
 
 
1029
void
 
1030
mxf_essence_element_handler_register (const MXFEssenceElementHandler * handler)
 
1031
{
 
1032
  _mxf_essence_element_handler_registry =
 
1033
      g_slist_prepend (_mxf_essence_element_handler_registry,
 
1034
      (gpointer) handler);
 
1035
}
 
1036
 
 
1037
const MXFEssenceElementHandler *
 
1038
mxf_essence_element_handler_find (const MXFMetadataTimelineTrack * track)
 
1039
{
 
1040
  GSList *l;
 
1041
  const MXFEssenceElementHandler *ret = NULL;
 
1042
 
 
1043
  for (l = _mxf_essence_element_handler_registry; l; l = l->next) {
 
1044
    MXFEssenceElementHandler *current = l->data;
 
1045
 
 
1046
    if (current->handles_track (track)) {
 
1047
      ret = current;
 
1048
    }
 
1049
  }
 
1050
 
 
1051
  return ret;
 
1052
}