mxfinfo 0.0.3.6 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1507 @@
1
+ /*
2
+ * Parse metadata from an Avid MXF file
3
+ *
4
+ * Copyright (C) 2008, British Broadcasting Corporation
5
+ * All Rights Reserved.
6
+ *
7
+ * Author: Philip de Nier
8
+ *
9
+ * Redistribution and use in source and binary forms, with or without
10
+ * modification, are permitted provided that the following conditions are met:
11
+ *
12
+ * * Redistributions of source code must retain the above copyright notice,
13
+ * this list of conditions and the following disclaimer.
14
+ * * Redistributions in binary form must reproduce the above copyright
15
+ * notice, this list of conditions and the following disclaimer in the
16
+ * documentation and/or other materials provided with the distribution.
17
+ * * Neither the name of the British Broadcasting Corporation nor the names
18
+ * of its contributors may be used to endorse or promote products derived
19
+ * from this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
+ * POSSIBILITY OF SUCH DAMAGE.
32
+ */
33
+
34
+ #ifdef HAVE_CONFIG_H
35
+ #include "config.h"
36
+ #endif
37
+
38
+ #include <stdio.h>
39
+ #include <stdlib.h>
40
+ #include <string.h>
41
+ #include <assert.h>
42
+
43
+ #include <mxf/mxf.h>
44
+ #include <mxf/mxf_avid.h>
45
+ #include <mxf/mxf_uu_metadata.h>
46
+ #include <mxf/mxf_macros.h>
47
+
48
+ #include "avid_mxf_info.h"
49
+
50
+
51
+ #define DEBUG_PRINT_ERROR(cmd) \
52
+ if (printDebugError) \
53
+ { \
54
+ ; \
55
+ }
56
+
57
+ #define CHECK(cmd, ecode) \
58
+ if (!(cmd)) \
59
+ { \
60
+ DEBUG_PRINT_ERROR(cmd); \
61
+ errorCode = ecode; \
62
+ goto fail; \
63
+ }
64
+
65
+ #define DCHECK(cmd) \
66
+ if (!(cmd)) \
67
+ { \
68
+ DEBUG_PRINT_ERROR(cmd); \
69
+ errorCode = -1; \
70
+ goto fail; \
71
+ }
72
+
73
+ #define FCHECK(cmd) \
74
+ if (!(cmd)) \
75
+ { \
76
+ DEBUG_PRINT_ERROR(cmd); \
77
+ goto fail; \
78
+ }
79
+
80
+
81
+ typedef struct
82
+ {
83
+ uint32_t first;
84
+ uint32_t last;
85
+ } TrackNumberRange;
86
+
87
+
88
+ /* keep this in sync with AvidEssenceType in the header file */
89
+ static const char* ESSENCE_TYPE_STRINGS[] =
90
+ {
91
+ "not recognized",
92
+ "MPEG 30",
93
+ "MPEG 40",
94
+ "MPEG 50",
95
+ "DV 25 411",
96
+ "DV 25 420",
97
+ "DV 50",
98
+ "DV 100",
99
+ "20:1",
100
+ "2:1s",
101
+ "4:1s",
102
+ "15:1s",
103
+ "10:1",
104
+ "10:1m",
105
+ "4:1m",
106
+ "3:1",
107
+ "2:1",
108
+ "1:1",
109
+ "1:1 10b",
110
+ "35:1p",
111
+ "28:1p",
112
+ "14:1p",
113
+ "3:1p",
114
+ "2:1p",
115
+ "3:1m",
116
+ "8:1m",
117
+ "DNxHD 1235",
118
+ "DNxHD 1237",
119
+ "DNxHD 1238",
120
+ "DNxHD 1241",
121
+ "DNxHD 1242",
122
+ "DNxHD 1243",
123
+ "DNxHD 1250",
124
+ "DNxHD 1251",
125
+ "DNxHD 1252",
126
+ "DNxHD 1253",
127
+ "MPEG-4",
128
+ "XDCAM HD",
129
+ "AVC-Intra 100",
130
+ "AVC-Intra 50",
131
+ "PCM"
132
+ };
133
+
134
+
135
+ typedef struct
136
+ {
137
+ AvidEssenceType essenceType;
138
+ mxfRational editRate;
139
+ const char *name;
140
+ } DNxHDTypeString;
141
+
142
+ static const DNxHDTypeString DNXHD_TYPE_STRINGS[] =
143
+ {
144
+ /* 23.976 fps */
145
+ {DNXHD_1235_ESSENCE_TYPE, {24000, 1001}, "DNxHD 175x (1235)"},
146
+ {DNXHD_1237_ESSENCE_TYPE, {24000, 1001}, "DNxHD 115 (1237)"},
147
+ {DNXHD_1238_ESSENCE_TYPE, {24000, 1001}, "DNxHD 175 (1238)"},
148
+ {DNXHD_1250_ESSENCE_TYPE, {24000, 1001}, "DNxHD 90x (1250)"},
149
+ {DNXHD_1251_ESSENCE_TYPE, {24000, 1001}, "DNxHD 90 (1251)"},
150
+ {DNXHD_1252_ESSENCE_TYPE, {24000, 1001}, "DNxHD 60 (1252)"},
151
+ {DNXHD_1253_ESSENCE_TYPE, {24000, 1001}, "DNxHD 36 (1253)"},
152
+
153
+ /* 24 fps */
154
+ {DNXHD_1235_ESSENCE_TYPE, {24, 1}, "DNxHD 175x (1235)"},
155
+ {DNXHD_1237_ESSENCE_TYPE, {24, 1}, "DNxHD 115 (1237)"},
156
+ {DNXHD_1238_ESSENCE_TYPE, {24, 1}, "DNxHD 175 (1238)"},
157
+ {DNXHD_1253_ESSENCE_TYPE, {24, 1}, "DNxHD 36 (1253)"},
158
+
159
+ /* 25 fps */
160
+ {DNXHD_1235_ESSENCE_TYPE, {25, 1}, "DNxHD 185x (1235)"},
161
+ {DNXHD_1237_ESSENCE_TYPE, {25, 1}, "DNxHD 120 (1237)"},
162
+ {DNXHD_1238_ESSENCE_TYPE, {25, 1}, "DNxHD 185 (1238)"},
163
+ {DNXHD_1241_ESSENCE_TYPE, {25, 1}, "DNxHD 185x (1241)"},
164
+ {DNXHD_1242_ESSENCE_TYPE, {25, 1}, "DNxHD 120 (1242)"},
165
+ {DNXHD_1243_ESSENCE_TYPE, {25, 1}, "DNxHD 185 (1243)"},
166
+ {DNXHD_1250_ESSENCE_TYPE, {25, 1}, "DNxHD 90x (1250)"},
167
+ {DNXHD_1251_ESSENCE_TYPE, {25, 1}, "DNxHD 90 (1251)"},
168
+ {DNXHD_1252_ESSENCE_TYPE, {25, 1}, "DNxHD 60 (1252)"},
169
+ {DNXHD_1253_ESSENCE_TYPE, {25, 1}, "DNxHD 36 (1253)"},
170
+
171
+ /* 29.97 fps */
172
+ {DNXHD_1235_ESSENCE_TYPE, {30000, 1001}, "DNxHD 220x (1235)"},
173
+ {DNXHD_1237_ESSENCE_TYPE, {30000, 1001}, "DNxHD 145 (1237)"},
174
+ {DNXHD_1238_ESSENCE_TYPE, {30000, 1001}, "DNxHD 220 (1238)"},
175
+ {DNXHD_1241_ESSENCE_TYPE, {30000, 1001}, "DNxHD 220x (1241)"},
176
+ {DNXHD_1242_ESSENCE_TYPE, {30000, 1001}, "DNxHD 145 (1242)"},
177
+ {DNXHD_1243_ESSENCE_TYPE, {30000, 1001}, "DNxHD 220 (1243)"},
178
+ {DNXHD_1250_ESSENCE_TYPE, {30000, 1001}, "DNxHD 110x (1250)"},
179
+ {DNXHD_1251_ESSENCE_TYPE, {30000, 1001}, "DNxHD 110 (1251)"},
180
+ {DNXHD_1252_ESSENCE_TYPE, {30000, 1001}, "DNxHD 75 (1252)"},
181
+ {DNXHD_1253_ESSENCE_TYPE, {30000, 1001}, "DNxHD 45 (1253)"},
182
+
183
+ /* 50 fps */
184
+ {DNXHD_1250_ESSENCE_TYPE, {50, 1}, "DNxHD 175x (1250)"},
185
+ {DNXHD_1251_ESSENCE_TYPE, {50, 1}, "DNxHD 175 (1251)"},
186
+ {DNXHD_1252_ESSENCE_TYPE, {50, 1}, "DNxHD 115 (1252)"},
187
+
188
+ /* 59.94 fps */
189
+ {DNXHD_1250_ESSENCE_TYPE, {60000, 1001}, "DNxHD 220x (1250)"},
190
+ {DNXHD_1251_ESSENCE_TYPE, {60000, 1001}, "DNxHD 220 (1251)"},
191
+ {DNXHD_1252_ESSENCE_TYPE, {60000, 1001}, "DNxHD 145 (1252)"},
192
+ };
193
+
194
+
195
+ typedef struct
196
+ {
197
+ AvidEssenceType essenceType;
198
+ int checkPictureCodingLabel;
199
+ const mxfUL *essenceContainerLabel;
200
+ const mxfUL *pictureCodingLabel;
201
+ int32_t avidResolutionID;
202
+ } EssenceTypeMap;
203
+
204
+ static const EssenceTypeMap ESSENCE_TYPE_MAP[] =
205
+ {
206
+ {MPEG_30_ESSENCE_TYPE, 0, &MXF_EC_L(D10_30_625_50_picture_only), &MXF_CMDEF_L(D10_30_625_50), 0},
207
+ {MPEG_30_ESSENCE_TYPE, 0, &MXF_EC_L(D10_30_525_60_picture_only), &MXF_CMDEF_L(D10_30_525_60), 0},
208
+ {MPEG_40_ESSENCE_TYPE, 0, &MXF_EC_L(D10_40_625_50_picture_only), &MXF_CMDEF_L(D10_40_625_50), 0},
209
+ {MPEG_40_ESSENCE_TYPE, 0, &MXF_EC_L(D10_40_525_60_picture_only), &MXF_CMDEF_L(D10_40_525_60), 0},
210
+ {MPEG_50_ESSENCE_TYPE, 0, &MXF_EC_L(D10_50_625_50_picture_only), &MXF_CMDEF_L(D10_50_625_50), 0},
211
+ {MPEG_50_ESSENCE_TYPE, 0, &MXF_EC_L(D10_50_525_60_picture_only), &MXF_CMDEF_L(D10_50_525_60), 0},
212
+
213
+ {DV_25_411_ESSENCE_TYPE, 0, &MXF_EC_L(IECDV_25_525_60_ClipWrapped), &MXF_CMDEF_L(IECDV_25_525_60), 0},
214
+ {DV_25_420_ESSENCE_TYPE, 0, &MXF_EC_L(IECDV_25_625_50_ClipWrapped), &MXF_CMDEF_L(IECDV_25_625_50), 0},
215
+ {DV_25_411_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_25_525_60_ClipWrapped), &MXF_CMDEF_L(DVBased_25_525_60), 0},
216
+ {DV_25_411_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_25_625_50_ClipWrapped), &MXF_CMDEF_L(DVBased_25_625_50), 0},
217
+ {DV_50_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_50_525_60_ClipWrapped), &MXF_CMDEF_L(DVBased_50_525_60), 0},
218
+ {DV_50_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_50_625_50_ClipWrapped), &MXF_CMDEF_L(DVBased_50_625_50), 0},
219
+ {DV_100_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_100_720_50_P_ClipWrapped), &MXF_CMDEF_L(DVBased_100_720_50_P), 0},
220
+ {DV_100_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_100_720_60_P_ClipWrapped), &MXF_CMDEF_L(DVBased_100_720_60_P), 0},
221
+ {DV_100_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_100_1080_50_I_ClipWrapped), &MXF_CMDEF_L(DVBased_100_1080_50_I), 0},
222
+ {DV_100_ESSENCE_TYPE, 0, &MXF_EC_L(DVBased_100_1080_60_I_ClipWrapped), &MXF_CMDEF_L(DVBased_100_1080_60_I), 0},
223
+
224
+ {MJPEG_10_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG101_PAL), 0x4b},
225
+ {MJPEG_10_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG101_NTSC), 0x4b},
226
+ {MJPEG_2_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG21_PAL), 0x4c},
227
+ {MJPEG_2_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG21_NTSC), 0x4c},
228
+ {MJPEG_3_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG31_PAL), 0x4d},
229
+ {MJPEG_3_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG31_NTSC), 0x4d},
230
+ {MJPEG_15_1_S_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG151s_PAL), 0x4e},
231
+ {MJPEG_15_1_S_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG151s_NTSC), 0x4e},
232
+ {MJPEG_4_1_S_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG41s_PAL), 0x4f},
233
+ {MJPEG_4_1_S_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG41s_NTSC), 0x4f},
234
+ {MJPEG_2_1_S_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG21s_PAL), 0x50},
235
+ {MJPEG_2_1_S_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG21s_NTSC), 0x50},
236
+ {MJPEG_20_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG201_PAL), 0x52},
237
+ {MJPEG_20_1_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG201_NTSC), 0x52},
238
+ {MJPEG_3_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG31p_PAL), 0x61},
239
+ {MJPEG_3_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG31p_NTSC), 0x61},
240
+ {MJPEG_2_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG21p_PAL), 0x62},
241
+ {MJPEG_2_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG21p_NTSC), 0x62},
242
+ {MJPEG_35_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG351p_PAL), 0x66},
243
+ {MJPEG_35_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG351p_NTSC), 0x66},
244
+ {MJPEG_14_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG141p_PAL), 0x67},
245
+ {MJPEG_14_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG141p_NTSC), 0x67},
246
+ {MJPEG_28_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG281p_PAL), 0x68},
247
+ {MJPEG_28_1_P_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG281p_NTSC), 0x68},
248
+ {MJPEG_10_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG101m_PAL), 0x6e},
249
+ {MJPEG_10_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG101m_NTSC), 0x6e},
250
+ {MJPEG_4_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), 0, 0x6f},
251
+ {MJPEG_8_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG81m_PAL), 0x70},
252
+ {MJPEG_8_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG81m_NTSC), 0x70},
253
+ {MJPEG_3_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG31m_PAL), 0x71},
254
+ {MJPEG_3_1_M_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMJPEGClipWrapped), &MXF_CMDEF_L(AvidMJPEG31m_NTSC), 0x71},
255
+
256
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(SD_Unc_625_50i_422_135_ClipWrapped), 0, 0xaa},
257
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(SD_Unc_525_5994i_422_135_ClipWrapped), 0, 0xaa},
258
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(HD_Unc_1080_50i_422_ClipWrapped), 0, 0},
259
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(HD_Unc_1080_5994i_422_ClipWrapped), 0, 0},
260
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(HD_Unc_720_50p_422_ClipWrapped), 0, 0},
261
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(HD_Unc_720_5994p_422_ClipWrapped), 0, 0},
262
+ /* Avid Media Composer 5.03 wrongly used this label for 720_50p */
263
+ {UNC_1_1_ESSENCE_TYPE, 0, &MXF_EC_L(HD_Unc_720_60p_422_ClipWrapped), 0, 0},
264
+
265
+ {UNC_1_1_10B_ESSENCE_TYPE, 0, &MXF_EC_L(AvidUnc10Bit625ClipWrapped), &MXF_CMDEF_L(AvidUncSD10Bit), 0x07e6},
266
+ {UNC_1_1_10B_ESSENCE_TYPE, 0, &MXF_EC_L(AvidUnc10Bit525ClipWrapped), &MXF_CMDEF_L(AvidUncSD10Bit), 0x07e5},
267
+ {UNC_1_1_10B_ESSENCE_TYPE, 0, &MXF_EC_L(AvidUnc10Bit1080iClipWrapped), &MXF_CMDEF_L(AvidUncHD10Bit), 0x07d0},
268
+ {UNC_1_1_10B_ESSENCE_TYPE, 0, &MXF_EC_L(AvidUnc10Bit720pClipWrapped), &MXF_CMDEF_L(AvidUncHD10Bit), 0x07d4},
269
+
270
+ {DNXHD_1235_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080p1235ClipWrapped), &MXF_CMDEF_L(VC3_1080P_1235), 1235},
271
+ {DNXHD_1237_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080p1237ClipWrapped), &MXF_CMDEF_L(VC3_1080P_1237), 1237},
272
+ {DNXHD_1238_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080p1238ClipWrapped), &MXF_CMDEF_L(VC3_1080P_1238), 1238},
273
+ {DNXHD_1241_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080i1241ClipWrapped), &MXF_CMDEF_L(VC3_1080I_1241), 1241},
274
+ {DNXHD_1242_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080i1242ClipWrapped), &MXF_CMDEF_L(VC3_1080I_1242), 1242},
275
+ {DNXHD_1243_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080i1243ClipWrapped), &MXF_CMDEF_L(VC3_1080I_1243), 1243},
276
+ {DNXHD_1250_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD720p1250ClipWrapped), &MXF_CMDEF_L(VC3_720P_1250), 1250},
277
+ {DNXHD_1251_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD720p1251ClipWrapped), &MXF_CMDEF_L(VC3_720P_1251), 1251},
278
+ {DNXHD_1252_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD720p1252ClipWrapped), &MXF_CMDEF_L(VC3_720P_1252), 1252},
279
+ {DNXHD_1253_ESSENCE_TYPE, 0, &MXF_EC_L(DNxHD1080p1253ClipWrapped), &MXF_CMDEF_L(VC3_1080P_1253), 1253},
280
+
281
+ {MPEG4_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMPEGClipWrapped), &MXF_CMDEF_L(MP4AdvancedRealTimeSimpleL4), 0},
282
+
283
+ {XDCAM_HD_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMPEGClipWrapped), &MXF_CMDEF_L(MPEG2_422P_HL_LONGGOP), 0},
284
+ {XDCAM_HD_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMPEGClipWrapped), &MXF_CMDEF_L(MPEG2_MP_HL_LONGGOP), 0},
285
+ {XDCAM_HD_ESSENCE_TYPE, 1, &MXF_EC_L(AvidMPEGClipWrapped), &MXF_CMDEF_L(MPEG2_MP_H14_LONGGOP), 0},
286
+
287
+ {AVCINTRA_100_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_100_1080_60_I), 0},
288
+ {AVCINTRA_100_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_100_1080_50_I), 0},
289
+ {AVCINTRA_100_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_100_1080_30_P), 0},
290
+ {AVCINTRA_100_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_100_1080_25_P), 0},
291
+ {AVCINTRA_100_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_100_720_60_P), 0},
292
+ {AVCINTRA_100_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_100_720_50_P), 0},
293
+
294
+ {AVCINTRA_50_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_50_1080_60_I), 0},
295
+ {AVCINTRA_50_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_50_1080_50_I), 0},
296
+ {AVCINTRA_50_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_50_1080_30_P), 0},
297
+ {AVCINTRA_50_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_50_1080_25_P), 0},
298
+ {AVCINTRA_50_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_50_720_60_P), 0},
299
+ {AVCINTRA_50_ESSENCE_TYPE, 1, &MXF_EC_L(AVCIClipWrapped), &MXF_CMDEF_L(AVCI_50_720_50_P), 0},
300
+
301
+ {PCM_ESSENCE_TYPE, 0, &MXF_EC_L(BWFClipWrapped), 0, 0},
302
+ {PCM_ESSENCE_TYPE, 0, &MXF_EC_L(AES3ClipWrapped), 0, 0},
303
+ };
304
+
305
+
306
+ static const char *FRAME_LAYOUT_STRINGS[] =
307
+ {
308
+ "unknown layout",
309
+ "full frame",
310
+ "separate fields",
311
+ "single field",
312
+ "mixed field",
313
+ "segmented frame",
314
+ };
315
+
316
+
317
+
318
+ static AvidEssenceType get_essence_type(mxfUL *essenceContainerLabel, mxfUL *pictureCodingLabel,
319
+ int32_t avidResolutionID)
320
+ {
321
+ /* Note: using mxf_equals_ul_mod_regver function below because some Avid labels (e.g. D10)
322
+ use a different registry version byte */
323
+
324
+ int match_ec, match_pc, match_resid;
325
+ int null_in_ec, null_in_pc;
326
+ int null_resid, null_ec, null_pc;
327
+ size_t i;
328
+
329
+ null_in_ec = mxf_equals_ul(essenceContainerLabel, &g_Null_UL);
330
+ null_in_pc = mxf_equals_ul(pictureCodingLabel, &g_Null_UL);
331
+
332
+ for (i = 0; i < ARRAY_SIZE(ESSENCE_TYPE_MAP); i++)
333
+ {
334
+ null_ec = null_in_ec || !ESSENCE_TYPE_MAP[i].essenceContainerLabel;
335
+ null_pc = null_in_pc || !ESSENCE_TYPE_MAP[i].pictureCodingLabel;
336
+ null_resid = avidResolutionID == 0 || ESSENCE_TYPE_MAP[i].avidResolutionID == 0;
337
+
338
+ match_ec = !null_ec &&
339
+ mxf_equals_ul_mod_regver(essenceContainerLabel, ESSENCE_TYPE_MAP[i].essenceContainerLabel);
340
+ match_pc = !null_pc &&
341
+ mxf_equals_ul_mod_regver(pictureCodingLabel, ESSENCE_TYPE_MAP[i].pictureCodingLabel);
342
+ match_resid = !null_resid &&
343
+ avidResolutionID == ESSENCE_TYPE_MAP[i].avidResolutionID;
344
+
345
+ if (match_ec &&
346
+ (!ESSENCE_TYPE_MAP[i].checkPictureCodingLabel || match_pc) &&
347
+ (null_resid || match_resid))
348
+ {
349
+ return ESSENCE_TYPE_MAP[i].essenceType;
350
+ }
351
+ else if (match_ec &&
352
+ ESSENCE_TYPE_MAP[i].checkPictureCodingLabel &&
353
+ !ESSENCE_TYPE_MAP[i].pictureCodingLabel &&
354
+ match_resid)
355
+ {
356
+ return ESSENCE_TYPE_MAP[i].essenceType;
357
+ }
358
+ else if (null_ec && match_pc && (null_resid || match_resid))
359
+ {
360
+ return ESSENCE_TYPE_MAP[i].essenceType;
361
+ }
362
+ }
363
+
364
+ return UNKNOWN_ESSENCE_TYPE;
365
+ }
366
+
367
+ static const char* get_dnxhd_type_string(AvidEssenceType essenceType, mxfRational editRate)
368
+ {
369
+ size_t i;
370
+ for (i = 0; i < ARRAY_SIZE(DNXHD_TYPE_STRINGS); i++) {
371
+ if (essenceType == DNXHD_TYPE_STRINGS[i].essenceType &&
372
+ memcmp(&editRate, &DNXHD_TYPE_STRINGS[i].editRate, sizeof(editRate)) == 0)
373
+ {
374
+ return DNXHD_TYPE_STRINGS[i].name;
375
+ }
376
+ }
377
+
378
+ return ESSENCE_TYPE_STRINGS[essenceType];
379
+ }
380
+
381
+ const char* get_essence_type_string(AvidEssenceType essenceType, mxfRational editRate)
382
+ {
383
+ assert(essenceType < ARRAY_SIZE(ESSENCE_TYPE_STRINGS));
384
+ assert(PCM_ESSENCE_TYPE + 1 == ARRAY_SIZE(ESSENCE_TYPE_STRINGS));
385
+
386
+ if (essenceType == DNXHD_1235_ESSENCE_TYPE ||
387
+ essenceType == DNXHD_1237_ESSENCE_TYPE ||
388
+ essenceType == DNXHD_1238_ESSENCE_TYPE ||
389
+ essenceType == DNXHD_1241_ESSENCE_TYPE ||
390
+ essenceType == DNXHD_1242_ESSENCE_TYPE ||
391
+ essenceType == DNXHD_1243_ESSENCE_TYPE ||
392
+ essenceType == DNXHD_1250_ESSENCE_TYPE ||
393
+ essenceType == DNXHD_1251_ESSENCE_TYPE ||
394
+ essenceType == DNXHD_1252_ESSENCE_TYPE ||
395
+ essenceType == DNXHD_1253_ESSENCE_TYPE)
396
+ {
397
+ return get_dnxhd_type_string(essenceType, editRate);
398
+ }
399
+
400
+ return ESSENCE_TYPE_STRINGS[essenceType];
401
+ }
402
+
403
+ static const char* frame_layout_string(uint8_t frameLayout)
404
+ {
405
+ if ((size_t)frameLayout + 1 < ARRAY_SIZE(FRAME_LAYOUT_STRINGS))
406
+ {
407
+ return FRAME_LAYOUT_STRINGS[frameLayout + 1];
408
+ }
409
+
410
+ return FRAME_LAYOUT_STRINGS[0];
411
+ }
412
+
413
+ static void print_umid(const mxfUMID *umid)
414
+ {
415
+ printf("%02x%02x%02x%02x%02x%02x%02x%02x"
416
+ "%02x%02x%02x%02x%02x%02x%02x%02x"
417
+ "%02x%02x%02x%02x%02x%02x%02x%02x"
418
+ "%02x%02x%02x%02x%02x%02x%02x%02x",
419
+ umid->octet0, umid->octet1, umid->octet2, umid->octet3,
420
+ umid->octet4, umid->octet5, umid->octet6, umid->octet7,
421
+ umid->octet8, umid->octet9, umid->octet10, umid->octet11,
422
+ umid->octet12, umid->octet13, umid->octet14, umid->octet15,
423
+ umid->octet16, umid->octet17, umid->octet18, umid->octet19,
424
+ umid->octet20, umid->octet21, umid->octet22, umid->octet23,
425
+ umid->octet24, umid->octet25, umid->octet26, umid->octet27,
426
+ umid->octet28, umid->octet29, umid->octet30, umid->octet31);
427
+ }
428
+
429
+ static void print_timestamp(const mxfTimestamp *timestamp)
430
+ {
431
+ printf("%d-%02u-%02u %02u:%02u:%02u.%03u",
432
+ timestamp->year, timestamp->month, timestamp->day,
433
+ timestamp->hour, timestamp->min, timestamp->sec, timestamp->qmsec * 4);
434
+ }
435
+
436
+ static void print_label(const mxfUL *label)
437
+ {
438
+ printf("%02x%02x%02x%02x%02x%02x%02x%02x"
439
+ "%02x%02x%02x%02x%02x%02x%02x%02x",
440
+ label->octet0, label->octet1, label->octet2, label->octet3,
441
+ label->octet4, label->octet5, label->octet6, label->octet7,
442
+ label->octet8, label->octet9, label->octet10, label->octet11,
443
+ label->octet12, label->octet13, label->octet14, label->octet15);
444
+ }
445
+
446
+ static void print_timecode(int64_t timecode, const mxfRational *sampleRate)
447
+ {
448
+ int hour, min, sec, frame;
449
+ int roundedTimecodeBase = (int)(sampleRate->numerator / (double)sampleRate->denominator + 0.5);
450
+
451
+ hour = (int)( timecode / (60 * 60 * roundedTimecodeBase));
452
+ min = (int)(( timecode % (60 * 60 * roundedTimecodeBase)) / (60 * roundedTimecodeBase));
453
+ sec = (int)(((timecode % (60 * 60 * roundedTimecodeBase)) % (60 * roundedTimecodeBase)) / roundedTimecodeBase);
454
+ frame = (int)(((timecode % (60 * 60 * roundedTimecodeBase)) % (60 * roundedTimecodeBase)) % roundedTimecodeBase);
455
+
456
+ printf("%02d:%02d:%02d:%02d", hour, min, sec, frame);
457
+ }
458
+
459
+ static int convert_string(const mxfUTF16Char *utf16Str, char **str, int printDebugError)
460
+ {
461
+ size_t utf8Len;
462
+
463
+ utf8Len = mxf_utf16_to_utf8(0, utf16Str, 0);
464
+ FCHECK(utf8Len != (size_t)(-1));
465
+ FCHECK((*str = malloc(utf8Len + 1)) != NULL);
466
+ mxf_utf16_to_utf8(*str, utf16Str, utf8Len + 1);
467
+
468
+ return 1;
469
+
470
+ fail:
471
+ return 0;
472
+ }
473
+
474
+ static void free_avid_tagged_values(AvidTaggedValue *value, int numValues)
475
+ {
476
+ int i, j;
477
+
478
+ if (value == NULL)
479
+ {
480
+ return;
481
+ }
482
+
483
+ for (i = 0; i < numValues; i++)
484
+ {
485
+ SAFE_FREE(value[i].name);
486
+ SAFE_FREE(value[i].value);
487
+ for (j = 0; j < value[i].numAttributes; j++)
488
+ {
489
+ SAFE_FREE(value[i].attributes[j].name);
490
+ SAFE_FREE(value[i].attributes[j].value);
491
+ }
492
+ SAFE_FREE(value[i].attributes);
493
+ }
494
+
495
+ free(value);
496
+ }
497
+
498
+ static int get_string_value(MXFMetadataSet *set, const mxfKey *itemKey, char **str, int printDebugError)
499
+ {
500
+ uint16_t utf16Size;
501
+ mxfUTF16Char *utf16Str = NULL;
502
+
503
+ FCHECK(mxf_get_utf16string_item_size(set, itemKey, &utf16Size));
504
+ FCHECK((utf16Str = malloc(utf16Size * sizeof(mxfUTF16Char))) != NULL);
505
+ FCHECK(mxf_get_utf16string_item(set, itemKey, utf16Str));
506
+
507
+ FCHECK(convert_string(utf16Str, str, printDebugError));
508
+
509
+ SAFE_FREE(utf16Str);
510
+ return 1;
511
+
512
+ fail:
513
+ SAFE_FREE(utf16Str);
514
+ return 0;
515
+ }
516
+
517
+ static int get_package_tagged_values(MXFMetadataSet *packageSet, const mxfKey *itemKey, int *numValues,
518
+ AvidTaggedValue **values, int printDebugError)
519
+ {
520
+ MXFMetadataSet *taggedValueSet;
521
+ uint32_t count;
522
+ uint32_t i;
523
+ uint8_t *element;
524
+ mxfUTF16Char *taggedValueName = NULL;
525
+ mxfUTF16Char *taggedValueValue = NULL;
526
+ AvidTaggedValue *newValues = NULL;
527
+ int index;
528
+ MXFListIterator namesIter;
529
+ MXFListIterator valuesIter;
530
+ MXFList *taggedValueNames = NULL;
531
+ MXFList *taggedValueValues = NULL;
532
+
533
+ FCHECK(mxf_have_item(packageSet, itemKey));
534
+
535
+ CHK_OFAIL(mxf_get_array_item_count(packageSet, itemKey, &count));
536
+
537
+ FCHECK((newValues = (AvidTaggedValue*)malloc(count * sizeof(AvidTaggedValue))) != NULL);
538
+ memset(newValues, 0, count * sizeof(AvidTaggedValue));
539
+
540
+ for (i = 0; i < count; i++)
541
+ {
542
+ CHK_OFAIL(mxf_get_array_item_element(packageSet, itemKey, i, &element));
543
+ CHK_OFAIL(mxf_get_strongref(packageSet->headerMetadata, element, &taggedValueSet));
544
+
545
+ CHK_OFAIL(mxf_avid_read_string_tagged_value(taggedValueSet, &taggedValueName, &taggedValueValue));
546
+
547
+ FCHECK(convert_string(taggedValueName, &newValues[i].name, printDebugError));
548
+ FCHECK(convert_string(taggedValueValue, &newValues[i].value, printDebugError));
549
+ SAFE_FREE(taggedValueName);
550
+ SAFE_FREE(taggedValueValue);
551
+
552
+ /* Check for any attributes */
553
+ if (mxf_have_item(taggedValueSet, &MXF_ITEM_K(TaggedValue, TaggedValueAttributeList)))
554
+ {
555
+ CHK_OFAIL(mxf_avid_read_string_tagged_values(taggedValueSet, &MXF_ITEM_K(TaggedValue, TaggedValueAttributeList),
556
+ &taggedValueNames, &taggedValueValues));
557
+ newValues[i].numAttributes = (int)mxf_get_list_length(taggedValueNames);
558
+
559
+ FCHECK((newValues[i].attributes = (AvidNameValuePair*)malloc(newValues[i].numAttributes * sizeof(AvidNameValuePair))) != NULL);
560
+ memset(newValues[i].attributes, 0, newValues[i].numAttributes * sizeof(AvidNameValuePair));
561
+
562
+ index = 0;
563
+ mxf_initialise_list_iter(&namesIter, taggedValueNames);
564
+ mxf_initialise_list_iter(&valuesIter, taggedValueValues);
565
+ while (mxf_next_list_iter_element(&namesIter) && mxf_next_list_iter_element(&valuesIter))
566
+ {
567
+ FCHECK(convert_string(mxf_get_iter_element(&namesIter), &newValues[i].attributes[index].name, printDebugError));
568
+ FCHECK(convert_string(mxf_get_iter_element(&valuesIter), &newValues[i].attributes[index].value, printDebugError));
569
+
570
+ index++;
571
+ }
572
+
573
+ mxf_free_list(&taggedValueNames);
574
+ mxf_free_list(&taggedValueValues);
575
+ }
576
+ }
577
+
578
+ *values = newValues;
579
+ *numValues = count;
580
+
581
+ return 1;
582
+
583
+ fail:
584
+ free_avid_tagged_values(newValues, count);
585
+ SAFE_FREE(taggedValueName);
586
+ SAFE_FREE(taggedValueValue);
587
+ mxf_free_list(&taggedValueNames);
588
+ mxf_free_list(&taggedValueValues);
589
+ return 0;
590
+ }
591
+
592
+ static int get_single_track_component(MXFMetadataSet *trackSet, const mxfKey *componentSetKey,
593
+ MXFMetadataSet **componentSet, int printDebugError)
594
+ {
595
+ MXFMetadataSet *sequenceSet = NULL;
596
+ MXFMetadataSet *cSet = NULL;
597
+ uint32_t componentCount;
598
+ uint8_t *arrayElementValue;
599
+
600
+ /* get the single component in the sequence which is a subclass of componentSetKey */
601
+ FCHECK(mxf_get_strongref_item(trackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet));
602
+ if (mxf_set_is_subclass_of(sequenceSet, &MXF_SET_K(Sequence)))
603
+ {
604
+ /* is a sequence, so we get the first component */
605
+ FCHECK(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &componentCount));
606
+ if (componentCount != 1)
607
+ {
608
+ /* empty sequence or > 1 are not what we expect */
609
+ return 0;
610
+ }
611
+
612
+ /* get first component */
613
+ FCHECK(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), 0, &arrayElementValue));
614
+ if (!mxf_get_strongref(trackSet->headerMetadata, arrayElementValue, &cSet))
615
+ {
616
+ /* reference to a dark set and we assume it isn't something we're interested in */
617
+ return 0;
618
+ }
619
+ }
620
+ else
621
+ {
622
+ /* something other than a sequence */
623
+ cSet = sequenceSet;
624
+ }
625
+
626
+ if (!mxf_set_is_subclass_of(cSet, componentSetKey))
627
+ {
628
+ /* not a componentSetKey component */
629
+ return 0;
630
+ }
631
+
632
+ *componentSet = cSet;
633
+ return 1;
634
+
635
+ fail:
636
+ return 0;
637
+ }
638
+
639
+ static int64_t convert_length(const mxfRational *targetEditRate, const mxfRational *editRate, int64_t length)
640
+ {
641
+ return (int64_t)(length *
642
+ targetEditRate->numerator * editRate->denominator /
643
+ (double)(targetEditRate->denominator * editRate->numerator) + 0.5);
644
+ }
645
+
646
+ static int64_t compare_length(const mxfRational *editRateA, int64_t lengthA, const mxfRational *editRateB, int64_t lengthB)
647
+ {
648
+ return lengthA - convert_length(editRateA, editRateB, lengthB);
649
+ }
650
+
651
+ static void insert_track_number(TrackNumberRange *trackNumbers, uint32_t trackNumber, int *numTrackNumberRanges)
652
+ {
653
+ int i;
654
+ int j;
655
+
656
+ for (i = 0; i < *numTrackNumberRanges; i++)
657
+ {
658
+ if (trackNumber < trackNumbers[i].first - 1)
659
+ {
660
+ /* insert new track range */
661
+ for (j = *numTrackNumberRanges - 1; j >= i; j--)
662
+ {
663
+ trackNumbers[j + 1] = trackNumbers[j];
664
+ }
665
+ trackNumbers[i].first = trackNumber;
666
+ trackNumbers[i].last = trackNumber;
667
+
668
+ (*numTrackNumberRanges)++;
669
+ return;
670
+ }
671
+ else if (trackNumber == trackNumbers[i].first - 1)
672
+ {
673
+ /* extend range back one */
674
+ trackNumbers[i].first = trackNumber;
675
+ return;
676
+ }
677
+ else if (trackNumber == trackNumbers[i].last + 1)
678
+ {
679
+ if (i + 1 < *numTrackNumberRanges &&
680
+ trackNumber == trackNumbers[i + 1].first - 1)
681
+ {
682
+ /* merge range forwards */
683
+ trackNumbers[i + 1].first = trackNumbers[i].first;
684
+ for (j = i; j < *numTrackNumberRanges - 1; j++)
685
+ {
686
+ trackNumbers[j] = trackNumbers[j + 1];
687
+ }
688
+ (*numTrackNumberRanges)--;
689
+ }
690
+ else
691
+ {
692
+ /* extend range forward one */
693
+ trackNumbers[i].last = trackNumber;
694
+ }
695
+
696
+ return;
697
+ }
698
+ else if (trackNumber == trackNumbers[i].first ||
699
+ trackNumber == trackNumbers[i].last)
700
+ {
701
+ /* duplicate */
702
+ return;
703
+ }
704
+ }
705
+
706
+
707
+ /* append new track range */
708
+ trackNumbers[i].first = trackNumber;
709
+ trackNumbers[i].last = trackNumber;
710
+
711
+ (*numTrackNumberRanges)++;
712
+ return;
713
+ }
714
+
715
+ static size_t get_range_string(char *buffer, size_t maxSize, int isFirst, int isVideo, const TrackNumberRange *range)
716
+ {
717
+ size_t strLen = 0;
718
+
719
+ if (isFirst)
720
+ {
721
+ mxf_snprintf(buffer, maxSize, "%s", (isVideo) ? "V" : "A");
722
+ strLen = strlen(buffer);
723
+ buffer += strLen;
724
+ maxSize -= strLen;
725
+ }
726
+ else
727
+ {
728
+ mxf_snprintf(buffer, maxSize, ",");
729
+ strLen = strlen(buffer);
730
+ buffer += strLen;
731
+ maxSize -= strLen;
732
+ }
733
+
734
+
735
+ if (range->first == range->last)
736
+ {
737
+ mxf_snprintf(buffer, maxSize, "%d", range->first);
738
+ strLen += strlen(buffer);
739
+ }
740
+ else
741
+ {
742
+ mxf_snprintf(buffer, maxSize, "%d-%d", range->first, range->last);
743
+ strLen += strlen(buffer);
744
+ }
745
+
746
+ return strLen;
747
+ }
748
+
749
+
750
+ int ami_read_info(const char *filename, AvidMXFInfo *info, int printDebugError)
751
+ {
752
+ int errorCode = -1;
753
+ mxfKey key;
754
+ uint8_t llen;
755
+ uint64_t len;
756
+ uint32_t sequenceComponentCount;
757
+ uint32_t choicesCount;
758
+ uint8_t *arrayElement;
759
+ MXFList *list = NULL;
760
+ MXFListIterator listIter;
761
+ MXFArrayItemIterator arrayIter;
762
+ MXFFile *mxfFile = NULL;
763
+ MXFPartition *headerPartition = NULL;
764
+ MXFDataModel *dataModel = NULL;
765
+ MXFHeaderMetadata *headerMetadata = NULL;
766
+ MXFMetadataSet *set = NULL;
767
+ MXFMetadataSet *prefaceSet = NULL;
768
+ MXFMetadataSet *fileSourcePackageSet = NULL;
769
+ MXFMetadataSet *materialPackageSet = NULL;
770
+ MXFMetadataSet *descriptorSet = NULL;
771
+ MXFMetadataSet *locatorSet = NULL;
772
+ MXFMetadataSet *physicalSourcePackageSet = NULL;
773
+ MXFMetadataSet *materialPackageTrackSet = NULL;
774
+ MXFMetadataSet *trackSet = NULL;
775
+ MXFMetadataSet *sourceClipSet = NULL;
776
+ MXFMetadataSet *sequenceSet = NULL;
777
+ MXFMetadataSet *timecodeComponentSet = NULL;
778
+ MXFMetadataSet *refSourcePackageSet = NULL;
779
+ MXFMetadataSet *essenceGroupSet = NULL;
780
+ mxfUMID packageUID;
781
+ MXFList *taggedValueNames = NULL;
782
+ MXFList *taggedValueValues = NULL;
783
+ const mxfUTF16Char *taggedValue;
784
+ mxfUL dataDef;
785
+ mxfUMID sourcePackageID;
786
+ MXFArrayItemIterator iter3;
787
+ int64_t filePackageStartPosition;
788
+ int64_t startPosition;
789
+ mxfRational filePackageEditRate;
790
+ int64_t startTimecode;
791
+ uint16_t roundedTimecodeBase;
792
+ int haveStartTimecode;
793
+ mxfRational editRate;
794
+ int64_t trackDuration;
795
+ int64_t segmentDuration;
796
+ int64_t segmentOffset;
797
+ mxfRational maxEditRate = {25, 1};
798
+ int64_t maxDuration = 0;
799
+ int32_t avidResolutionID = 0x00;
800
+ TrackNumberRange videoTrackNumberRanges[64];
801
+ int numVideoTrackNumberRanges = 0;
802
+ TrackNumberRange audioTrackNumberRanges[64];
803
+ int numAudioTrackNumberRanges = 0;
804
+ uint32_t trackNumber;
805
+ char tracksString[256] = {0};
806
+ int i, j;
807
+ size_t remSize;
808
+ char *tracksStringPtr;
809
+ size_t strLen;
810
+ uint32_t arrayElementLen;
811
+ uint16_t fpRoundedTimecodeBase;
812
+
813
+ memset(info, 0, sizeof(AvidMXFInfo));
814
+ info->frameLayout = 0xff; /* unknown (0 is known) */
815
+
816
+
817
+ /* open file */
818
+
819
+ CHECK(mxf_disk_file_open_read(filename, &mxfFile), -2);
820
+
821
+
822
+ /* read header partition pack */
823
+
824
+ CHECK(mxf_read_header_pp_kl(mxfFile, &key, &llen, &len), -3);
825
+ CHECK(mxf_read_partition(mxfFile, &key, &headerPartition), -3);
826
+
827
+
828
+ /* check is OP-Atom */
829
+
830
+ CHECK(mxf_is_op_atom(&headerPartition->operationalPattern), -4);
831
+
832
+
833
+ /* read the header metadata (filter out meta-dictionary and dictionary except data defs) */
834
+
835
+ DCHECK(mxf_load_data_model(&dataModel));
836
+ DCHECK(mxf_avid_load_extensions(dataModel));
837
+
838
+ DCHECK(mxf_finalise_data_model(dataModel));
839
+
840
+ DCHECK(mxf_read_next_nonfiller_kl(mxfFile, &key, &llen, &len));
841
+ DCHECK(mxf_is_header_metadata(&key));
842
+ DCHECK(mxf_create_header_metadata(&headerMetadata, dataModel));
843
+ DCHECK(mxf_avid_read_filtered_header_metadata(mxfFile, 0, headerMetadata, headerPartition->headerByteCount, &key, llen, len));
844
+
845
+
846
+ /* get the preface and info */
847
+
848
+ DCHECK(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(Preface), &prefaceSet));
849
+ if (mxf_have_item(prefaceSet, &MXF_ITEM_K(Preface, ProjectName)))
850
+ {
851
+ DCHECK(get_string_value(prefaceSet, &MXF_ITEM_K(Preface, ProjectName), &info->projectName, printDebugError));
852
+ }
853
+ if (mxf_have_item(prefaceSet, &MXF_ITEM_K(Preface, ProjectEditRate)))
854
+ {
855
+ DCHECK(mxf_get_rational_item(prefaceSet, &MXF_ITEM_K(Preface, ProjectEditRate), &info->projectEditRate));
856
+ }
857
+
858
+
859
+ /* get the material package and info */
860
+
861
+ DCHECK(mxf_find_singular_set_by_key(headerMetadata, &MXF_SET_K(MaterialPackage), &materialPackageSet));
862
+ DCHECK(mxf_get_umid_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, PackageUID), &info->materialPackageUID));
863
+ if (mxf_have_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, Name)))
864
+ {
865
+ DCHECK(get_string_value(materialPackageSet, &MXF_ITEM_K(GenericPackage, Name), &info->clipName, printDebugError));
866
+ }
867
+ if (mxf_have_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, PackageCreationDate)))
868
+ {
869
+ DCHECK(mxf_get_timestamp_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, PackageCreationDate), &info->clipCreated));
870
+ }
871
+
872
+
873
+ /* get the material package project name tagged value if not already set */
874
+
875
+ if (info->projectName == NULL &&
876
+ mxf_have_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, MobAttributeList)))
877
+ {
878
+ DCHECK(mxf_avid_read_string_mob_attributes(materialPackageSet, &taggedValueNames, &taggedValueValues));
879
+ if (mxf_avid_get_mob_attribute(L"_PJ", taggedValueNames, taggedValueValues, &taggedValue))
880
+ {
881
+ DCHECK(convert_string(taggedValue, &info->projectName, printDebugError));
882
+ }
883
+ }
884
+ mxf_free_list(&taggedValueNames);
885
+ mxf_free_list(&taggedValueValues);
886
+
887
+
888
+ /* get the material package user comments */
889
+ if (mxf_have_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, UserComments)))
890
+ {
891
+ DCHECK(get_package_tagged_values(materialPackageSet, &MXF_ITEM_K(GenericPackage, UserComments), &info->numUserComments, &info->userComments, printDebugError));
892
+ }
893
+
894
+ /* get the material package attributes */
895
+ if (mxf_have_item(materialPackageSet, &MXF_ITEM_K(GenericPackage, MobAttributeList)))
896
+ {
897
+ DCHECK(get_package_tagged_values(materialPackageSet, &MXF_ITEM_K(GenericPackage, MobAttributeList), &info->numMaterialPackageAttributes, &info->materialPackageAttributes, printDebugError));
898
+ }
899
+
900
+ /* get the top level file source package and info */
901
+
902
+ DCHECK(mxf_uu_get_top_file_package(headerMetadata, &fileSourcePackageSet));
903
+ DCHECK(mxf_get_umid_item(fileSourcePackageSet, &MXF_ITEM_K(GenericPackage, PackageUID), &info->fileSourcePackageUID));
904
+
905
+
906
+ /* get the file source package essence descriptor info */
907
+
908
+ DCHECK(mxf_get_strongref_item(fileSourcePackageSet, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet));
909
+ if (mxf_is_subclass_of(dataModel, &descriptorSet->key, &MXF_SET_K(GenericPictureEssenceDescriptor)))
910
+ {
911
+ /* image aspect ratio */
912
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, AspectRatio)))
913
+ {
914
+ DCHECK(mxf_get_rational_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, AspectRatio), &info->aspectRatio));
915
+ }
916
+
917
+ /* frame layout */
918
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, FrameLayout)))
919
+ {
920
+ DCHECK(mxf_get_uint8_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, FrameLayout), &info->frameLayout));
921
+ }
922
+
923
+ /* stored width and height */
924
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, StoredWidth)))
925
+ {
926
+ DCHECK(mxf_get_uint32_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, StoredWidth), &info->storedWidth));
927
+ }
928
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, StoredHeight)))
929
+ {
930
+ DCHECK(mxf_get_uint32_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, StoredHeight), &info->storedHeight));
931
+ }
932
+
933
+ /* display width and height */
934
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayWidth)))
935
+ {
936
+ DCHECK(mxf_get_uint32_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayWidth), &info->displayWidth));
937
+ }
938
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayHeight)))
939
+ {
940
+ DCHECK(mxf_get_uint32_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, DisplayHeight), &info->displayHeight));
941
+ }
942
+
943
+ /* Avid resolution Id */
944
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, ResolutionID)))
945
+ {
946
+ DCHECK(mxf_get_int32_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, ResolutionID), &avidResolutionID));
947
+ }
948
+
949
+ /* picture essence coding label */
950
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, PictureEssenceCoding)))
951
+ {
952
+ DCHECK(mxf_get_ul_item(descriptorSet, &MXF_ITEM_K(GenericPictureEssenceDescriptor, PictureEssenceCoding), &info->pictureCodingLabel));
953
+ }
954
+ }
955
+ else if (mxf_is_subclass_of(dataModel, &descriptorSet->key, &MXF_SET_K(GenericSoundEssenceDescriptor)))
956
+ {
957
+ /* audio sampling rate */
958
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericSoundEssenceDescriptor, AudioSamplingRate)))
959
+ {
960
+ DCHECK(mxf_get_rational_item(descriptorSet, &MXF_ITEM_K(GenericSoundEssenceDescriptor, AudioSamplingRate), &info->audioSamplingRate));
961
+ }
962
+ /* quantization bits */
963
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericSoundEssenceDescriptor, QuantizationBits)))
964
+ {
965
+ DCHECK(mxf_get_uint32_item(descriptorSet, &MXF_ITEM_K(GenericSoundEssenceDescriptor, QuantizationBits), &info->quantizationBits));
966
+ }
967
+ /* channel count */
968
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericSoundEssenceDescriptor, ChannelCount)))
969
+ {
970
+ DCHECK(mxf_get_uint32_item(descriptorSet, &MXF_ITEM_K(GenericSoundEssenceDescriptor, ChannelCount), &info->channelCount));
971
+ }
972
+ }
973
+
974
+
975
+ /* get the material track referencing the file source package and info */
976
+ /* get the clip duration ( = duration of the longest track) */
977
+
978
+ DCHECK(mxf_uu_get_package_tracks(materialPackageSet, &arrayIter));
979
+ while (mxf_uu_next_track(headerMetadata, &arrayIter, &materialPackageTrackSet))
980
+ {
981
+ DCHECK(mxf_uu_get_track_datadef(materialPackageTrackSet, &dataDef));
982
+
983
+ /* some Avid files have a weak reference to a DataDefinition instead of a UL */
984
+ if (!mxf_is_picture(&dataDef) && !mxf_is_sound(&dataDef) && !mxf_is_timecode(&dataDef))
985
+ {
986
+ if (!mxf_avid_get_data_def(headerMetadata, (mxfUUID*)&dataDef, &dataDef))
987
+ {
988
+ continue;
989
+ }
990
+ }
991
+
992
+ /* skip non-video and audio tracks */
993
+ if (!mxf_is_picture(&dataDef) && !mxf_is_sound(&dataDef))
994
+ {
995
+ continue;
996
+ }
997
+
998
+ /* track counts */
999
+ if (mxf_is_picture(&dataDef))
1000
+ {
1001
+ info->numVideoTracks++;
1002
+ }
1003
+ else
1004
+ {
1005
+ info->numAudioTracks++;
1006
+ }
1007
+
1008
+ /* track number */
1009
+ if (mxf_have_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber)))
1010
+ {
1011
+ DCHECK(mxf_get_uint32_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, TrackNumber), &trackNumber));
1012
+ if (mxf_is_picture(&dataDef))
1013
+ {
1014
+ insert_track_number(videoTrackNumberRanges, trackNumber, &numVideoTrackNumberRanges);
1015
+ }
1016
+ else
1017
+ {
1018
+ insert_track_number(audioTrackNumberRanges, trackNumber, &numAudioTrackNumberRanges);
1019
+ }
1020
+ }
1021
+ else
1022
+ {
1023
+ trackNumber = 0;
1024
+ }
1025
+
1026
+ /* edit rate */
1027
+ DCHECK(mxf_get_rational_item(materialPackageTrackSet, &MXF_ITEM_K(Track, EditRate), &editRate));
1028
+
1029
+ /* track duration */
1030
+ DCHECK(mxf_uu_get_track_duration(materialPackageTrackSet, &trackDuration));
1031
+
1032
+ /* get max duration for the clip duration */
1033
+ if (compare_length(&maxEditRate, maxDuration, &editRate, trackDuration) <= 0)
1034
+ {
1035
+ maxEditRate = editRate;
1036
+ maxDuration = trackDuration;
1037
+ }
1038
+
1039
+ /* assume the project edit rate equals the video edit rate if not set */
1040
+ if (memcmp(&info->projectEditRate, &g_Null_Rational, sizeof(g_Null_Rational)) == 0 &&
1041
+ mxf_is_picture(&dataDef))
1042
+ {
1043
+ info->projectEditRate = editRate;
1044
+ }
1045
+
1046
+ /* get info from this track if it references the file source package through a source clip */
1047
+ packageUID = g_Null_UMID;
1048
+ segmentOffset = 0;
1049
+ CHK_ORET(mxf_get_strongref_item(materialPackageTrackSet, &MXF_ITEM_K(GenericTrack, Sequence), &sequenceSet));
1050
+ if (!mxf_is_subclass_of(sequenceSet->headerMetadata->dataModel, &sequenceSet->key, &MXF_SET_K(SourceClip)))
1051
+ {
1052
+ /* iterate through sequence components */
1053
+ CHK_ORET(mxf_get_array_item_count(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), &sequenceComponentCount));
1054
+ for (i = 0; i < (int)sequenceComponentCount; i++)
1055
+ {
1056
+ CHK_ORET(mxf_get_array_item_element(sequenceSet, &MXF_ITEM_K(Sequence, StructuralComponents), i, &arrayElement));
1057
+ if (!mxf_get_strongref(sequenceSet->headerMetadata, arrayElement, &sourceClipSet))
1058
+ {
1059
+ /* dark set not registered in the dictionary */
1060
+ continue;
1061
+ }
1062
+
1063
+ CHK_ORET(mxf_get_length_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, Duration), &segmentDuration));
1064
+
1065
+ if (mxf_is_subclass_of(sourceClipSet->headerMetadata->dataModel, &sourceClipSet->key, &MXF_SET_K(EssenceGroup)))
1066
+ {
1067
+ /* is an essence group - iterate through choices */
1068
+ essenceGroupSet = sourceClipSet;
1069
+ CHK_ORET(mxf_get_array_item_count(essenceGroupSet, &MXF_ITEM_K(EssenceGroup, Choices), &choicesCount));
1070
+ for (j = 0; j < (int)choicesCount; j++)
1071
+ {
1072
+ CHK_ORET(mxf_get_array_item_element(essenceGroupSet, &MXF_ITEM_K(EssenceGroup, Choices), j, &arrayElement));
1073
+ if (!mxf_get_strongref(essenceGroupSet->headerMetadata, arrayElement, &sourceClipSet))
1074
+ {
1075
+ /* dark set not registered in the dictionary */
1076
+ continue;
1077
+ }
1078
+
1079
+ if (mxf_is_subclass_of(sourceClipSet->headerMetadata->dataModel, &sourceClipSet->key, &MXF_SET_K(SourceClip)))
1080
+ {
1081
+ CHK_ORET(mxf_get_umid_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourcePackageID), &packageUID));
1082
+ if (mxf_equals_umid(&info->fileSourcePackageUID, &packageUID))
1083
+ {
1084
+ /* found source clip referencing file source package */
1085
+ break;
1086
+ }
1087
+ }
1088
+ }
1089
+ if (j < (int)choicesCount)
1090
+ {
1091
+ /* found source clip referencing file source package */
1092
+ break;
1093
+ }
1094
+ }
1095
+ else if (mxf_is_subclass_of(sourceClipSet->headerMetadata->dataModel, &sourceClipSet->key, &MXF_SET_K(SourceClip)))
1096
+ {
1097
+ CHK_ORET(mxf_get_umid_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourcePackageID), &packageUID));
1098
+ if (mxf_equals_umid(&info->fileSourcePackageUID, &packageUID))
1099
+ {
1100
+ /* found source clip referencing file source package */
1101
+ break;
1102
+ }
1103
+ }
1104
+
1105
+ segmentOffset += segmentDuration;
1106
+ }
1107
+ }
1108
+ else
1109
+ {
1110
+ /* track sequence is a source clip */
1111
+ sourceClipSet = sequenceSet;
1112
+ CHK_ORET(mxf_get_umid_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourcePackageID), &packageUID));
1113
+ CHK_ORET(mxf_get_length_item(sourceClipSet, &MXF_ITEM_K(StructuralComponent, Duration), &segmentDuration));
1114
+ segmentOffset = 0;
1115
+ }
1116
+
1117
+ if (mxf_equals_umid(&info->fileSourcePackageUID, &packageUID))
1118
+ {
1119
+ info->isVideo = mxf_is_picture(&dataDef);
1120
+ info->editRate = editRate;
1121
+ info->trackDuration = trackDuration;
1122
+ info->trackNumber = trackNumber;
1123
+ info->segmentDuration = segmentDuration;
1124
+ info->segmentOffset = segmentOffset;
1125
+ }
1126
+ }
1127
+
1128
+
1129
+ info->clipDuration = convert_length(&info->projectEditRate, &maxEditRate, maxDuration);
1130
+
1131
+
1132
+
1133
+ /* construct the tracks string */
1134
+
1135
+ remSize = sizeof(tracksString);
1136
+ tracksStringPtr = tracksString;
1137
+ for (i = 0; i < numVideoTrackNumberRanges; i++)
1138
+ {
1139
+ if (remSize < 4)
1140
+ {
1141
+ break;
1142
+ }
1143
+
1144
+ strLen = get_range_string(tracksStringPtr, remSize, i == 0, 1, &videoTrackNumberRanges[i]);
1145
+
1146
+ tracksStringPtr += strLen;
1147
+ remSize -= strLen;
1148
+ }
1149
+ if (numVideoTrackNumberRanges > 0 && numAudioTrackNumberRanges > 0)
1150
+ {
1151
+ mxf_snprintf(tracksStringPtr, remSize, " ");
1152
+ strLen = strlen(tracksStringPtr);
1153
+ tracksStringPtr += strLen;
1154
+ remSize -= strLen;
1155
+ }
1156
+ for (i = 0; i < numAudioTrackNumberRanges; i++)
1157
+ {
1158
+ if (remSize < 4)
1159
+ {
1160
+ break;
1161
+ }
1162
+ strLen = get_range_string(tracksStringPtr, remSize, i == 0, 0, &audioTrackNumberRanges[i]);
1163
+
1164
+ tracksStringPtr += strLen;
1165
+ remSize -= strLen;
1166
+ }
1167
+
1168
+ DCHECK((info->tracksString = strdup(tracksString)) != NULL);
1169
+
1170
+
1171
+
1172
+ /* get the physical source package and info */
1173
+
1174
+ DCHECK(mxf_find_set_by_key(headerMetadata, &MXF_SET_K(SourcePackage), &list));
1175
+ mxf_initialise_list_iter(&listIter, list);
1176
+ while (mxf_next_list_iter_element(&listIter))
1177
+ {
1178
+ set = (MXFMetadataSet*)mxf_get_iter_element(&listIter);
1179
+
1180
+ /* the physical source package is the source package that references a physical descriptor */
1181
+ if (mxf_have_item(set, &MXF_ITEM_K(SourcePackage, Descriptor)))
1182
+ {
1183
+ if (mxf_get_strongref_item(set, &MXF_ITEM_K(SourcePackage, Descriptor), &descriptorSet))
1184
+ {
1185
+ /* Get first physical package network locator */
1186
+ if (mxf_have_item(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators)))
1187
+ {
1188
+ DCHECK(mxf_initialise_array_item_iterator(descriptorSet, &MXF_ITEM_K(GenericDescriptor, Locators), &arrayIter));
1189
+ while (mxf_next_array_item_element(&arrayIter, &arrayElement, &arrayElementLen))
1190
+ {
1191
+ DCHECK(mxf_get_strongref(headerMetadata, arrayElement, &locatorSet));
1192
+ if (mxf_is_subclass_of(headerMetadata->dataModel, &locatorSet->key, &MXF_SET_K(NetworkLocator)))
1193
+ {
1194
+ DCHECK(get_string_value(locatorSet, &MXF_ITEM_K(NetworkLocator, URLString), &info->physicalPackageLocator, printDebugError));
1195
+ break;
1196
+ }
1197
+ }
1198
+ }
1199
+
1200
+ /* NOTE/TODO: some descriptors could be dark and so we don't assume we can dereference */
1201
+ if (mxf_is_subclass_of(dataModel, &descriptorSet->key, &MXF_SET_K(PhysicalDescriptor)))
1202
+ {
1203
+ if (mxf_is_subclass_of(dataModel, &descriptorSet->key, &MXF_SET_K(TapeDescriptor)))
1204
+ {
1205
+ info->physicalPackageType = TAPE_PHYS_TYPE;
1206
+ }
1207
+ else if (mxf_is_subclass_of(dataModel, &descriptorSet->key, &MXF_SET_K(ImportDescriptor)))
1208
+ {
1209
+ info->physicalPackageType = IMPORT_PHYS_TYPE;
1210
+ }
1211
+ else if (mxf_is_subclass_of(dataModel, &descriptorSet->key, &MXF_SET_K(RecordingDescriptor)))
1212
+ {
1213
+ info->physicalPackageType = RECORDING_PHYS_TYPE;
1214
+ }
1215
+ else
1216
+ {
1217
+ info->physicalPackageType = UNKNOWN_PHYS_TYPE;
1218
+ }
1219
+ physicalSourcePackageSet = set;
1220
+
1221
+ DCHECK(mxf_get_umid_item(physicalSourcePackageSet, &MXF_ITEM_K(GenericPackage, PackageUID), &info->physicalSourcePackageUID));
1222
+ if (mxf_have_item(physicalSourcePackageSet, &MXF_ITEM_K(GenericPackage, Name)))
1223
+ {
1224
+ DCHECK(get_string_value(physicalSourcePackageSet, &MXF_ITEM_K(GenericPackage, Name), &info->physicalPackageName, printDebugError));
1225
+ }
1226
+
1227
+ break;
1228
+ }
1229
+ }
1230
+ }
1231
+ }
1232
+ mxf_free_list(&list);
1233
+
1234
+
1235
+ /* get the start timecode */
1236
+
1237
+ /* the source timecode is calculated using the SourceClip::StartPosition in the file source package
1238
+ in conjunction with the TimecodeComponent in the referenced physical source package */
1239
+
1240
+ haveStartTimecode = 0;
1241
+ DCHECK(mxf_uu_get_package_tracks(fileSourcePackageSet, &arrayIter));
1242
+ while (!haveStartTimecode && mxf_uu_next_track(headerMetadata, &arrayIter, &trackSet))
1243
+ {
1244
+ /* skip tracks that are not picture or sound */
1245
+ DCHECK(mxf_uu_get_track_datadef(trackSet, &dataDef));
1246
+
1247
+ /* some Avid files have a weak reference to a DataDefinition instead of a UL */
1248
+ if (!mxf_is_picture(&dataDef) && !mxf_is_sound(&dataDef) && !mxf_is_timecode(&dataDef))
1249
+ {
1250
+ if (!mxf_avid_get_data_def(headerMetadata, (mxfUUID*)&dataDef, &dataDef))
1251
+ {
1252
+ continue;
1253
+ }
1254
+ }
1255
+
1256
+
1257
+ if (!mxf_is_picture(&dataDef) && !mxf_is_sound(&dataDef))
1258
+ {
1259
+ continue;
1260
+ }
1261
+
1262
+
1263
+ /* get the source clip */
1264
+ if (!get_single_track_component(trackSet, &MXF_SET_K(SourceClip), &sourceClipSet, printDebugError))
1265
+ {
1266
+ continue;
1267
+ }
1268
+
1269
+ /* get the start position and edit rate for the file source package source clip */
1270
+ DCHECK(mxf_get_rational_item(trackSet, &MXF_ITEM_K(Track, EditRate), &filePackageEditRate));
1271
+ DCHECK(mxf_get_position_item(sourceClipSet, &MXF_ITEM_K(SourceClip, StartPosition), &filePackageStartPosition));
1272
+
1273
+
1274
+ /* get the package referenced by the source clip */
1275
+ DCHECK(mxf_get_umid_item(sourceClipSet, &MXF_ITEM_K(SourceClip, SourcePackageID), &sourcePackageID));
1276
+ if (mxf_equals_umid(&g_Null_UMID, &sourcePackageID) ||
1277
+ !mxf_uu_get_referenced_package(sourceClipSet->headerMetadata, &sourcePackageID, &refSourcePackageSet))
1278
+ {
1279
+ /* either at the end of chain or don't have the referenced package */
1280
+ continue;
1281
+ }
1282
+
1283
+ /* find the timecode component in the physical source package and calculate the start timecode */
1284
+ DCHECK(mxf_uu_get_package_tracks(refSourcePackageSet, &iter3));
1285
+ while (mxf_uu_next_track(headerMetadata, &iter3, &trackSet))
1286
+ {
1287
+ /* skip non-timecode tracks */
1288
+ DCHECK(mxf_uu_get_track_datadef(trackSet, &dataDef));
1289
+
1290
+ /* some Avid files have a weak reference to a DataDefinition instead of a UL */
1291
+ if (!mxf_is_picture(&dataDef) && !mxf_is_sound(&dataDef) && !mxf_is_timecode(&dataDef))
1292
+ {
1293
+ if (!mxf_avid_get_data_def(headerMetadata, (mxfUUID*)&dataDef, &dataDef))
1294
+ {
1295
+ continue;
1296
+ }
1297
+ }
1298
+
1299
+ if (!mxf_is_timecode(&dataDef))
1300
+ {
1301
+ continue;
1302
+ }
1303
+
1304
+ /* get the timecode component */
1305
+ if (!get_single_track_component(trackSet, &MXF_SET_K(TimecodeComponent), &timecodeComponentSet, printDebugError))
1306
+ {
1307
+ continue;
1308
+ }
1309
+
1310
+ /* get the start timecode and rounded timecode base for the timecode component */
1311
+ DCHECK(mxf_get_position_item(timecodeComponentSet, &MXF_ITEM_K(TimecodeComponent, StartTimecode), &startTimecode));
1312
+ DCHECK(mxf_get_uint16_item(timecodeComponentSet, &MXF_ITEM_K(TimecodeComponent, RoundedTimecodeBase), &roundedTimecodeBase));
1313
+
1314
+ /* convert the physical package start timecode to a start position in the file source package */
1315
+ startPosition = filePackageStartPosition;
1316
+ if (startTimecode > 0) {
1317
+ fpRoundedTimecodeBase = (uint16_t)(filePackageEditRate.numerator / (double)filePackageEditRate.denominator + 0.5);
1318
+ if (fpRoundedTimecodeBase == roundedTimecodeBase)
1319
+ {
1320
+ startPosition += startTimecode;
1321
+ }
1322
+ else if (fpRoundedTimecodeBase == 2 * roundedTimecodeBase)
1323
+ {
1324
+ startPosition += 2 * startTimecode;
1325
+ }
1326
+ else
1327
+ {
1328
+ // mxf_log_warn("Ignoring non-zero TimecodeComponent::StartTimecode because edit rate combination not supported\n");
1329
+ /* TODO: complete support for different timecode and track edit rates */
1330
+ }
1331
+ }
1332
+
1333
+ /* convert the start position to material package track edit rate units */
1334
+ info->startTimecode = (int64_t)(startPosition *
1335
+ info->editRate.numerator * filePackageEditRate.denominator /
1336
+ (double)(info->editRate.denominator * filePackageEditRate.numerator) + 0.5);
1337
+
1338
+ haveStartTimecode = 1;
1339
+ break;
1340
+ }
1341
+ }
1342
+
1343
+
1344
+ /* get the essence type */
1345
+
1346
+ /* using the header partition's essence container label because the label in the FileDescriptor
1347
+ is sometimes a weak reference to a ContainerDefinition in Avid files and the ContainerDefinition
1348
+ is not of much use */
1349
+ if (mxf_get_list_length(&headerPartition->essenceContainers) > 0)
1350
+ info->essenceContainerLabel = *(mxfUL*)mxf_get_list_element(&headerPartition->essenceContainers, 0);
1351
+
1352
+ info->essenceType = get_essence_type(&info->essenceContainerLabel, &info->pictureCodingLabel, avidResolutionID);
1353
+
1354
+
1355
+
1356
+ /* clean up */
1357
+
1358
+ mxf_file_close(&mxfFile);
1359
+ mxf_free_header_metadata(&headerMetadata);
1360
+ mxf_free_data_model(&dataModel);
1361
+ mxf_free_partition(&headerPartition);
1362
+ mxf_free_list(&list);
1363
+ mxf_free_list(&taggedValueNames);
1364
+ mxf_free_list(&taggedValueValues);
1365
+
1366
+ return 0;
1367
+
1368
+
1369
+ fail:
1370
+
1371
+ mxf_file_close(&mxfFile);
1372
+ mxf_free_header_metadata(&headerMetadata);
1373
+ mxf_free_data_model(&dataModel);
1374
+ mxf_free_partition(&headerPartition);
1375
+ mxf_free_list(&list);
1376
+ mxf_free_list(&taggedValueNames);
1377
+ mxf_free_list(&taggedValueValues);
1378
+
1379
+ ami_free_info(info);
1380
+
1381
+ return errorCode;
1382
+ }
1383
+
1384
+ void ami_free_info(AvidMXFInfo *info)
1385
+ {
1386
+ SAFE_FREE(info->clipName);
1387
+ SAFE_FREE(info->projectName);
1388
+ SAFE_FREE(info->physicalPackageName);
1389
+ SAFE_FREE(info->tracksString);
1390
+ SAFE_FREE(info->physicalPackageLocator);
1391
+
1392
+ if (info->userComments != NULL)
1393
+ {
1394
+ free_avid_tagged_values(info->userComments, info->numUserComments);
1395
+ }
1396
+
1397
+ if (info->materialPackageAttributes != NULL)
1398
+ {
1399
+ free_avid_tagged_values(info->materialPackageAttributes, info->numMaterialPackageAttributes);
1400
+ }
1401
+ }
1402
+
1403
+ void ami_print_info(AvidMXFInfo *info)
1404
+ {
1405
+ int i, j;
1406
+
1407
+ printf("Project name = %s\n", (info->projectName == NULL) ? "": info->projectName);
1408
+ printf("Project edit rate = %d/%d\n", info->projectEditRate.numerator, info->projectEditRate.denominator);
1409
+ printf("Clip name = %s\n", (info->clipName == NULL) ? "": info->clipName);
1410
+ printf("Clip created = ");
1411
+ print_timestamp(&info->clipCreated);
1412
+ printf("\n");
1413
+ printf("Clip edit rate = %d/%d\n", info->projectEditRate.numerator, info->projectEditRate.denominator);
1414
+ printf("Clip duration = %"PRId64" samples (", info->clipDuration);
1415
+ print_timecode(info->clipDuration, &info->projectEditRate);
1416
+ printf(")\n");
1417
+ printf("Clip video tracks = %d\n", info->numVideoTracks);
1418
+ printf("Clip audio tracks = %d\n", info->numAudioTracks);
1419
+ printf("Clip track string = %s\n", (info->tracksString == NULL) ? "" : info->tracksString);
1420
+ printf("%s essence\n", info->isVideo ? "Video": "Audio");
1421
+ printf("Essence type = %s\n", get_essence_type_string(info->essenceType, info->projectEditRate));
1422
+ printf("Essence container label = ");
1423
+ print_label(&info->essenceContainerLabel);
1424
+ printf("\n");
1425
+ printf("Track number = %d\n", info->trackNumber);
1426
+ printf("Edit rate = %d/%d\n", info->editRate.numerator, info->editRate.denominator);
1427
+ printf("Track duration = %"PRId64" samples (", info->trackDuration);
1428
+ print_timecode(convert_length(&info->projectEditRate, &info->editRate, info->trackDuration), &info->projectEditRate);
1429
+ printf(")\n");
1430
+ printf("Track segment duration = %"PRId64" samples (", info->segmentDuration);
1431
+ print_timecode(convert_length(&info->projectEditRate, &info->editRate, info->segmentDuration), &info->projectEditRate);
1432
+ printf(")\n");
1433
+ printf("Track segment offset = %"PRId64" samples (", info->segmentOffset);
1434
+ print_timecode(convert_length(&info->projectEditRate, &info->editRate, info->segmentOffset), &info->projectEditRate);
1435
+ printf(")\n");
1436
+ printf("Start timecode = %"PRId64" samples (", info->startTimecode);
1437
+ print_timecode(convert_length(&info->projectEditRate, &info->editRate, info->startTimecode), &info->projectEditRate);
1438
+ printf(")\n");
1439
+ if (info->isVideo)
1440
+ {
1441
+ printf("Picture coding label = ");
1442
+ print_label(&info->pictureCodingLabel);
1443
+ printf("\n");
1444
+ printf("Image aspect ratio = %d/%d\n", info->aspectRatio.numerator, info->aspectRatio.denominator);
1445
+ printf("Stored WxH = %dx%d (%s)\n", info->storedWidth, info->storedHeight, frame_layout_string(info->frameLayout));
1446
+ printf("Display WxH = %dx%d (%s)\n", info->storedWidth, info->storedHeight, frame_layout_string(info->frameLayout));
1447
+ }
1448
+ else
1449
+ {
1450
+ printf("Audio sampling rate = %d/%d\n", info->audioSamplingRate.numerator, info->audioSamplingRate.denominator);
1451
+ printf("Channel count = %d\n", info->channelCount);
1452
+ printf("Quantization bits = %d\n", info->quantizationBits);
1453
+ }
1454
+ if (info->userComments != NULL)
1455
+ {
1456
+ printf("User comments:\n");
1457
+ for (i = 0; i < info->numUserComments; i++)
1458
+ {
1459
+ printf(" %s = %s\n", info->userComments[i].name, info->userComments[i].value);
1460
+ for (j = 0; j < info->userComments[i].numAttributes; j++)
1461
+ {
1462
+ printf(" %s = %s\n", info->userComments[i].attributes[j].name, info->userComments[i].attributes[j].value);
1463
+ }
1464
+ }
1465
+ }
1466
+ if (info->materialPackageAttributes != NULL)
1467
+ {
1468
+ printf("Material package attributes:\n");
1469
+ for (i = 0; i < info->numMaterialPackageAttributes; i++)
1470
+ {
1471
+ printf(" %s = %s\n", info->materialPackageAttributes[i].name, info->materialPackageAttributes[i].value);
1472
+ for (j = 0; j < info->materialPackageAttributes[i].numAttributes; j++)
1473
+ {
1474
+ printf(" %s = %s\n", info->materialPackageAttributes[i].attributes[j].name, info->materialPackageAttributes[i].attributes[j].value);
1475
+ }
1476
+ }
1477
+ }
1478
+ printf("Material package UID = ");
1479
+ print_umid(&info->materialPackageUID);
1480
+ printf("\n");
1481
+ printf("File package UID = ");
1482
+ print_umid(&info->fileSourcePackageUID);
1483
+ printf("\n");
1484
+ printf("Physical package UID = ");
1485
+ print_umid(&info->physicalSourcePackageUID);
1486
+ printf("\n");
1487
+ printf("Physical package type = ");
1488
+ switch (info->physicalPackageType)
1489
+ {
1490
+ case TAPE_PHYS_TYPE:
1491
+ printf("Tape");
1492
+ break;
1493
+ case IMPORT_PHYS_TYPE:
1494
+ printf("Import");
1495
+ break;
1496
+ case RECORDING_PHYS_TYPE:
1497
+ printf("Recording");
1498
+ break;
1499
+ case UNKNOWN_PHYS_TYPE:
1500
+ default:
1501
+ break;
1502
+ }
1503
+ printf("\n");
1504
+ printf("Physical package name = %s\n", (info->physicalPackageName == NULL) ? "": info->physicalPackageName);
1505
+ printf("Physical package locator = %s\n", (info->physicalPackageLocator == NULL) ? "": info->physicalPackageLocator);
1506
+ }
1507
+