ffmpeg / libavformat / mxfdec.c @ 2912e87a
History | View | Annotate | Download (38.3 KB)
1 | d09ea6ba | Baptiste Coudurier | /*
|
---|---|---|---|
2 | * MXF demuxer.
|
||
3 | 406792e7 | Diego Biurrun | * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
|
4 | d09ea6ba | Baptiste Coudurier | *
|
5 | 2912e87a | Mans Rullgard | * This file is part of Libav.
|
6 | d09ea6ba | Baptiste Coudurier | *
|
7 | 2912e87a | Mans Rullgard | * Libav is free software; you can redistribute it and/or
|
8 | d09ea6ba | Baptiste Coudurier | * modify it under the terms of the GNU Lesser General Public
|
9 | * License as published by the Free Software Foundation; either
|
||
10 | * version 2.1 of the License, or (at your option) any later version.
|
||
11 | *
|
||
12 | 2912e87a | Mans Rullgard | * Libav is distributed in the hope that it will be useful,
|
13 | d09ea6ba | Baptiste Coudurier | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
15 | * Lesser General Public License for more details.
|
||
16 | *
|
||
17 | * You should have received a copy of the GNU Lesser General Public
|
||
18 | 2912e87a | Mans Rullgard | * License along with Libav; if not, write to the Free Software
|
19 | d09ea6ba | Baptiste Coudurier | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20 | */
|
||
21 | |||
22 | /*
|
||
23 | * References
|
||
24 | * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value
|
||
25 | * SMPTE 377M MXF File Format Specifications
|
||
26 | * SMPTE 378M Operational Pattern 1a
|
||
27 | * SMPTE 379M MXF Generic Container
|
||
28 | * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container
|
||
29 | * SMPTE 382M Mapping AES3 and Broadcast Wave Audio into the MXF Generic Container
|
||
30 | * SMPTE 383M Mapping DV-DIF Data to the MXF Generic Container
|
||
31 | *
|
||
32 | * Principle
|
||
33 | * Search for Track numbers which will identify essence element KLV packets.
|
||
34 | * Search for SourcePackage which define tracks which contains Track numbers.
|
||
35 | * Material Package contains tracks with reference to SourcePackage tracks.
|
||
36 | * Search for Descriptors (Picture, Sound) which contains codec info and parameters.
|
||
37 | * Assign Descriptors to correct Tracks.
|
||
38 | *
|
||
39 | * Metadata reading functions read Local Tags, get InstanceUID(0x3C0A) then add MetaDataSet to MXFContext.
|
||
40 | * Metadata parsing resolves Strong References to objects.
|
||
41 | *
|
||
42 | * Simple demuxer, only OP1A supported and some files might not work at all.
|
||
43 | * Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1
|
||
44 | */
|
||
45 | |||
46 | //#define DEBUG
|
||
47 | |||
48 | #include "libavutil/aes.h" |
||
49 | 251bf875 | Baptiste Coudurier | #include "libavcodec/bytestream.h" |
50 | #include "avformat.h" |
||
51 | c69968b4 | Zhentan Feng | #include "mxf.h" |
52 | d09ea6ba | Baptiste Coudurier | |
53 | typedef struct { |
||
54 | UID uid; |
||
55 | enum MXFMetadataSetType type;
|
||
56 | UID source_container_ul; |
||
57 | } MXFCryptoContext; |
||
58 | |||
59 | typedef struct { |
||
60 | UID uid; |
||
61 | enum MXFMetadataSetType type;
|
||
62 | UID source_package_uid; |
||
63 | UID data_definition_ul; |
||
64 | int64_t duration; |
||
65 | int64_t start_position; |
||
66 | int source_track_id;
|
||
67 | } MXFStructuralComponent; |
||
68 | |||
69 | typedef struct { |
||
70 | UID uid; |
||
71 | enum MXFMetadataSetType type;
|
||
72 | UID data_definition_ul; |
||
73 | UID *structural_components_refs; |
||
74 | int structural_components_count;
|
||
75 | int64_t duration; |
||
76 | } MXFSequence; |
||
77 | |||
78 | typedef struct { |
||
79 | UID uid; |
||
80 | enum MXFMetadataSetType type;
|
||
81 | MXFSequence *sequence; /* mandatory, and only one */
|
||
82 | UID sequence_ref; |
||
83 | int track_id;
|
||
84 | uint8_t track_number[4];
|
||
85 | AVRational edit_rate; |
||
86 | } MXFTrack; |
||
87 | |||
88 | typedef struct { |
||
89 | UID uid; |
||
90 | enum MXFMetadataSetType type;
|
||
91 | UID essence_container_ul; |
||
92 | UID essence_codec_ul; |
||
93 | AVRational sample_rate; |
||
94 | AVRational aspect_ratio; |
||
95 | int width;
|
||
96 | int height;
|
||
97 | int channels;
|
||
98 | int bits_per_sample;
|
||
99 | UID *sub_descriptors_refs; |
||
100 | int sub_descriptors_count;
|
||
101 | int linked_track_id;
|
||
102 | uint8_t *extradata; |
||
103 | int extradata_size;
|
||
104 | 11fdc4d4 | Tomas Härdin | enum PixelFormat pix_fmt;
|
105 | d09ea6ba | Baptiste Coudurier | } MXFDescriptor; |
106 | |||
107 | typedef struct { |
||
108 | UID uid; |
||
109 | enum MXFMetadataSetType type;
|
||
110 | 861b4f01 | Baptiste Coudurier | } MXFIndexTableSegment; |
111 | |||
112 | typedef struct { |
||
113 | UID uid; |
||
114 | enum MXFMetadataSetType type;
|
||
115 | d09ea6ba | Baptiste Coudurier | UID package_uid; |
116 | UID *tracks_refs; |
||
117 | int tracks_count;
|
||
118 | MXFDescriptor *descriptor; /* only one */
|
||
119 | UID descriptor_ref; |
||
120 | } MXFPackage; |
||
121 | |||
122 | typedef struct { |
||
123 | UID uid; |
||
124 | enum MXFMetadataSetType type;
|
||
125 | } MXFMetadataSet; |
||
126 | |||
127 | typedef struct { |
||
128 | UID *packages_refs; |
||
129 | int packages_count;
|
||
130 | MXFMetadataSet **metadata_sets; |
||
131 | int metadata_sets_count;
|
||
132 | AVFormatContext *fc; |
||
133 | struct AVAES *aesc;
|
||
134 | uint8_t *local_tags; |
||
135 | int local_tags_count;
|
||
136 | } MXFContext; |
||
137 | |||
138 | enum MXFWrappingScheme {
|
||
139 | Frame, |
||
140 | Clip, |
||
141 | }; |
||
142 | |||
143 | ae628ec1 | Anton Khirnov | typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid); |
144 | 39bb30f6 | Reimar Döffinger | |
145 | d09ea6ba | Baptiste Coudurier | typedef struct { |
146 | const UID key;
|
||
147 | 39bb30f6 | Reimar Döffinger | MXFMetadataReadFunc *read; |
148 | d09ea6ba | Baptiste Coudurier | int ctx_size;
|
149 | enum MXFMetadataSetType type;
|
||
150 | } MXFMetadataReadTableEntry; |
||
151 | |||
152 | /* partial keys to match */
|
||
153 | static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 }; |
||
154 | static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 }; |
||
155 | static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; |
||
156 | /* complete keys to match */
|
||
157 | static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; |
||
158 | static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; |
||
159 | static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 }; |
||
160 | static const uint8_t mxf_sony_mpeg4_extradata[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0e,0x06,0x06,0x02,0x02,0x01,0x00,0x00 }; |
||
161 | |||
162 | #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) |
||
163 | |||
164 | ae628ec1 | Anton Khirnov | static int64_t klv_decode_ber_length(AVIOContext *pb)
|
165 | d09ea6ba | Baptiste Coudurier | { |
166 | b7effd4e | Anton Khirnov | uint64_t size = avio_r8(pb); |
167 | d09ea6ba | Baptiste Coudurier | if (size & 0x80) { /* long form */ |
168 | int bytes_num = size & 0x7f; |
||
169 | /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */
|
||
170 | if (bytes_num > 8) |
||
171 | return -1; |
||
172 | size = 0;
|
||
173 | while (bytes_num--)
|
||
174 | b7effd4e | Anton Khirnov | size = size << 8 | avio_r8(pb);
|
175 | d09ea6ba | Baptiste Coudurier | } |
176 | return size;
|
||
177 | } |
||
178 | |||
179 | ae628ec1 | Anton Khirnov | static int mxf_read_sync(AVIOContext *pb, const uint8_t *key, unsigned size) |
180 | d09ea6ba | Baptiste Coudurier | { |
181 | int i, b;
|
||
182 | 66e5b1df | Anton Khirnov | for (i = 0; i < size && !pb->eof_reached; i++) { |
183 | b7effd4e | Anton Khirnov | b = avio_r8(pb); |
184 | d09ea6ba | Baptiste Coudurier | if (b == key[0]) |
185 | i = 0;
|
||
186 | else if (b != key[i]) |
||
187 | i = -1;
|
||
188 | } |
||
189 | return i == size;
|
||
190 | } |
||
191 | |||
192 | ae628ec1 | Anton Khirnov | static int klv_read_packet(KLVPacket *klv, AVIOContext *pb) |
193 | d09ea6ba | Baptiste Coudurier | { |
194 | if (!mxf_read_sync(pb, mxf_klv_key, 4)) |
||
195 | return -1; |
||
196 | a2704c97 | Anton Khirnov | klv->offset = avio_tell(pb) - 4;
|
197 | d09ea6ba | Baptiste Coudurier | memcpy(klv->key, mxf_klv_key, 4);
|
198 | b7effd4e | Anton Khirnov | avio_read(pb, klv->key + 4, 12); |
199 | d09ea6ba | Baptiste Coudurier | klv->length = klv_decode_ber_length(pb); |
200 | return klv->length == -1 ? -1 : 0; |
||
201 | } |
||
202 | |||
203 | static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv) |
||
204 | { |
||
205 | int i;
|
||
206 | |||
207 | for (i = 0; i < s->nb_streams; i++) { |
||
208 | MXFTrack *track = s->streams[i]->priv_data; |
||
209 | /* SMPTE 379M 7.3 */
|
||
210 | if (!memcmp(klv->key + sizeof(mxf_essence_element_key), track->track_number, sizeof(track->track_number))) |
||
211 | return i;
|
||
212 | } |
||
213 | /* return 0 if only one stream, for OP Atom files with 0 as track number */
|
||
214 | return s->nb_streams == 1 ? 0 : -1; |
||
215 | } |
||
216 | |||
217 | /* XXX: use AVBitStreamFilter */
|
||
218 | ae628ec1 | Anton Khirnov | static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length) |
219 | d09ea6ba | Baptiste Coudurier | { |
220 | const uint8_t *buf_ptr, *end_ptr;
|
||
221 | uint8_t *data_ptr; |
||
222 | int i;
|
||
223 | |||
224 | if (length > 61444) /* worst case PAL 1920 samples 8 channels */ |
||
225 | return -1; |
||
226 | av_new_packet(pkt, length); |
||
227 | b7effd4e | Anton Khirnov | avio_read(pb, pkt->data, length); |
228 | d09ea6ba | Baptiste Coudurier | data_ptr = pkt->data; |
229 | c7a38887 | Reimar Döffinger | end_ptr = pkt->data + length; |
230 | buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */ |
||
231 | d09ea6ba | Baptiste Coudurier | for (; buf_ptr < end_ptr; ) {
|
232 | for (i = 0; i < st->codec->channels; i++) { |
||
233 | uint32_t sample = bytestream_get_le32(&buf_ptr); |
||
234 | dd1c8f3e | Luca Abeni | if (st->codec->bits_per_coded_sample == 24) |
235 | d09ea6ba | Baptiste Coudurier | bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff); |
236 | else
|
||
237 | bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff); |
||
238 | } |
||
239 | buf_ptr += 32 - st->codec->channels*4; // always 8 channels stored SMPTE 331M |
||
240 | } |
||
241 | pkt->size = data_ptr - pkt->data; |
||
242 | return 0; |
||
243 | } |
||
244 | |||
245 | static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv) |
||
246 | { |
||
247 | static const uint8_t checkv[16] = {0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b}; |
||
248 | MXFContext *mxf = s->priv_data; |
||
249 | ae628ec1 | Anton Khirnov | AVIOContext *pb = s->pb; |
250 | a2704c97 | Anton Khirnov | int64_t end = avio_tell(pb) + klv->length; |
251 | d09ea6ba | Baptiste Coudurier | uint64_t size; |
252 | uint64_t orig_size; |
||
253 | uint64_t plaintext_size; |
||
254 | uint8_t ivec[16];
|
||
255 | uint8_t tmpbuf[16];
|
||
256 | int index;
|
||
257 | |||
258 | if (!mxf->aesc && s->key && s->keylen == 16) { |
||
259 | mxf->aesc = av_malloc(av_aes_size); |
||
260 | if (!mxf->aesc)
|
||
261 | return -1; |
||
262 | av_aes_init(mxf->aesc, s->key, 128, 1); |
||
263 | } |
||
264 | // crypto context
|
||
265 | 45a8a02a | Anton Khirnov | avio_skip(pb, klv_decode_ber_length(pb)); |
266 | d09ea6ba | Baptiste Coudurier | // plaintext offset
|
267 | klv_decode_ber_length(pb); |
||
268 | b7effd4e | Anton Khirnov | plaintext_size = avio_rb64(pb); |
269 | d09ea6ba | Baptiste Coudurier | // source klv key
|
270 | klv_decode_ber_length(pb); |
||
271 | b7effd4e | Anton Khirnov | avio_read(pb, klv->key, 16);
|
272 | d09ea6ba | Baptiste Coudurier | if (!IS_KLV_KEY(klv, mxf_essence_element_key))
|
273 | return -1; |
||
274 | index = mxf_get_stream_index(s, klv); |
||
275 | if (index < 0) |
||
276 | return -1; |
||
277 | // source size
|
||
278 | klv_decode_ber_length(pb); |
||
279 | b7effd4e | Anton Khirnov | orig_size = avio_rb64(pb); |
280 | d09ea6ba | Baptiste Coudurier | if (orig_size < plaintext_size)
|
281 | return -1; |
||
282 | // enc. code
|
||
283 | size = klv_decode_ber_length(pb); |
||
284 | if (size < 32 || size - 32 < orig_size) |
||
285 | return -1; |
||
286 | b7effd4e | Anton Khirnov | avio_read(pb, ivec, 16);
|
287 | avio_read(pb, tmpbuf, 16);
|
||
288 | d09ea6ba | Baptiste Coudurier | if (mxf->aesc)
|
289 | av_aes_crypt(mxf->aesc, tmpbuf, tmpbuf, 1, ivec, 1); |
||
290 | if (memcmp(tmpbuf, checkv, 16)) |
||
291 | av_log(s, AV_LOG_ERROR, "probably incorrect decryption key\n");
|
||
292 | size -= 32;
|
||
293 | av_get_packet(pb, pkt, size); |
||
294 | size -= plaintext_size; |
||
295 | if (mxf->aesc)
|
||
296 | av_aes_crypt(mxf->aesc, &pkt->data[plaintext_size], |
||
297 | &pkt->data[plaintext_size], size >> 4, ivec, 1); |
||
298 | pkt->size = orig_size; |
||
299 | pkt->stream_index = index; |
||
300 | 45a8a02a | Anton Khirnov | avio_skip(pb, end - avio_tell(pb)); |
301 | d09ea6ba | Baptiste Coudurier | return 0; |
302 | } |
||
303 | |||
304 | static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) |
||
305 | { |
||
306 | KLVPacket klv; |
||
307 | |||
308 | 66e5b1df | Anton Khirnov | while (!s->pb->eof_reached) {
|
309 | d09ea6ba | Baptiste Coudurier | if (klv_read_packet(&klv, s->pb) < 0) |
310 | return -1; |
||
311 | PRINT_KEY(s, "read packet", klv.key);
|
||
312 | dfd2a005 | Luca Barbato | av_dlog(s, "size %lld offset %#llx\n", klv.length, klv.offset);
|
313 | d09ea6ba | Baptiste Coudurier | if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) {
|
314 | int res = mxf_decrypt_triplet(s, pkt, &klv);
|
||
315 | if (res < 0) { |
||
316 | av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n");
|
||
317 | return -1; |
||
318 | } |
||
319 | return 0; |
||
320 | } |
||
321 | if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) {
|
||
322 | int index = mxf_get_stream_index(s, &klv);
|
||
323 | if (index < 0) { |
||
324 | 66ec3d56 | Baptiste Coudurier | av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); |
325 | d09ea6ba | Baptiste Coudurier | goto skip;
|
326 | } |
||
327 | if (s->streams[index]->discard == AVDISCARD_ALL)
|
||
328 | goto skip;
|
||
329 | /* check for 8 channels AES3 element */
|
||
330 | if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) { |
||
331 | if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) { |
||
332 | av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n");
|
||
333 | return -1; |
||
334 | } |
||
335 | } else
|
||
336 | av_get_packet(s->pb, pkt, klv.length); |
||
337 | pkt->stream_index = index; |
||
338 | pkt->pos = klv.offset; |
||
339 | return 0; |
||
340 | } else
|
||
341 | skip: |
||
342 | 45a8a02a | Anton Khirnov | avio_skip(s->pb, klv.length); |
343 | d09ea6ba | Baptiste Coudurier | } |
344 | 9291fdf7 | Baptiste Coudurier | return AVERROR_EOF;
|
345 | d09ea6ba | Baptiste Coudurier | } |
346 | |||
347 | ae628ec1 | Anton Khirnov | static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
348 | d09ea6ba | Baptiste Coudurier | { |
349 | 39bb30f6 | Reimar Döffinger | MXFContext *mxf = arg; |
350 | b7effd4e | Anton Khirnov | int item_num = avio_rb32(pb);
|
351 | int item_len = avio_rb32(pb);
|
||
352 | d09ea6ba | Baptiste Coudurier | |
353 | if (item_len != 18) { |
||
354 | av_log(mxf->fc, AV_LOG_ERROR, "unsupported primer pack item length\n");
|
||
355 | return -1; |
||
356 | } |
||
357 | if (item_num > UINT_MAX / item_len)
|
||
358 | return -1; |
||
359 | mxf->local_tags_count = item_num; |
||
360 | mxf->local_tags = av_malloc(item_num*item_len); |
||
361 | if (!mxf->local_tags)
|
||
362 | return -1; |
||
363 | b7effd4e | Anton Khirnov | avio_read(pb, mxf->local_tags, item_num*item_len); |
364 | d09ea6ba | Baptiste Coudurier | return 0; |
365 | } |
||
366 | |||
367 | static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) |
||
368 | { |
||
369 | b4800b8b | Baptiste Coudurier | if (mxf->metadata_sets_count+1 >= UINT_MAX / sizeof(*mxf->metadata_sets)) |
370 | return AVERROR(ENOMEM);
|
||
371 | d09ea6ba | Baptiste Coudurier | mxf->metadata_sets = av_realloc(mxf->metadata_sets, (mxf->metadata_sets_count + 1) * sizeof(*mxf->metadata_sets)); |
372 | if (!mxf->metadata_sets)
|
||
373 | return -1; |
||
374 | mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set; |
||
375 | mxf->metadata_sets_count++; |
||
376 | return 0; |
||
377 | } |
||
378 | |||
379 | ae628ec1 | Anton Khirnov | static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
380 | d09ea6ba | Baptiste Coudurier | { |
381 | 39bb30f6 | Reimar Döffinger | MXFCryptoContext *cryptocontext = arg; |
382 | d09ea6ba | Baptiste Coudurier | if (size != 16) |
383 | return -1; |
||
384 | if (IS_KLV_KEY(uid, mxf_crypto_source_container_ul))
|
||
385 | b7effd4e | Anton Khirnov | avio_read(pb, cryptocontext->source_container_ul, 16);
|
386 | d09ea6ba | Baptiste Coudurier | return 0; |
387 | } |
||
388 | |||
389 | ae628ec1 | Anton Khirnov | static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
390 | d09ea6ba | Baptiste Coudurier | { |
391 | 39bb30f6 | Reimar Döffinger | MXFContext *mxf = arg; |
392 | d09ea6ba | Baptiste Coudurier | switch (tag) {
|
393 | case 0x1901: |
||
394 | b7effd4e | Anton Khirnov | mxf->packages_count = avio_rb32(pb); |
395 | d09ea6ba | Baptiste Coudurier | if (mxf->packages_count >= UINT_MAX / sizeof(UID)) |
396 | return -1; |
||
397 | mxf->packages_refs = av_malloc(mxf->packages_count * sizeof(UID));
|
||
398 | if (!mxf->packages_refs)
|
||
399 | return -1; |
||
400 | 45a8a02a | Anton Khirnov | avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
401 | b7effd4e | Anton Khirnov | avio_read(pb, (uint8_t *)mxf->packages_refs, mxf->packages_count * sizeof(UID));
|
402 | d09ea6ba | Baptiste Coudurier | break;
|
403 | } |
||
404 | return 0; |
||
405 | } |
||
406 | |||
407 | ae628ec1 | Anton Khirnov | static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
408 | d09ea6ba | Baptiste Coudurier | { |
409 | 39bb30f6 | Reimar Döffinger | MXFStructuralComponent *source_clip = arg; |
410 | d09ea6ba | Baptiste Coudurier | switch(tag) {
|
411 | case 0x0202: |
||
412 | b7effd4e | Anton Khirnov | source_clip->duration = avio_rb64(pb); |
413 | d09ea6ba | Baptiste Coudurier | break;
|
414 | case 0x1201: |
||
415 | b7effd4e | Anton Khirnov | source_clip->start_position = avio_rb64(pb); |
416 | d09ea6ba | Baptiste Coudurier | break;
|
417 | case 0x1101: |
||
418 | /* UMID, only get last 16 bytes */
|
||
419 | 45a8a02a | Anton Khirnov | avio_skip(pb, 16);
|
420 | b7effd4e | Anton Khirnov | avio_read(pb, source_clip->source_package_uid, 16);
|
421 | d09ea6ba | Baptiste Coudurier | break;
|
422 | case 0x1102: |
||
423 | b7effd4e | Anton Khirnov | source_clip->source_track_id = avio_rb32(pb); |
424 | d09ea6ba | Baptiste Coudurier | break;
|
425 | } |
||
426 | return 0; |
||
427 | } |
||
428 | |||
429 | ae628ec1 | Anton Khirnov | static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
430 | d09ea6ba | Baptiste Coudurier | { |
431 | 39bb30f6 | Reimar Döffinger | MXFPackage *package = arg; |
432 | d09ea6ba | Baptiste Coudurier | switch(tag) {
|
433 | case 0x4403: |
||
434 | b7effd4e | Anton Khirnov | package->tracks_count = avio_rb32(pb); |
435 | d09ea6ba | Baptiste Coudurier | if (package->tracks_count >= UINT_MAX / sizeof(UID)) |
436 | return -1; |
||
437 | package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
|
||
438 | if (!package->tracks_refs)
|
||
439 | return -1; |
||
440 | 45a8a02a | Anton Khirnov | avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
441 | b7effd4e | Anton Khirnov | avio_read(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
|
442 | d09ea6ba | Baptiste Coudurier | break;
|
443 | } |
||
444 | return 0; |
||
445 | } |
||
446 | |||
447 | ae628ec1 | Anton Khirnov | static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
448 | d09ea6ba | Baptiste Coudurier | { |
449 | 39bb30f6 | Reimar Döffinger | MXFTrack *track = arg; |
450 | d09ea6ba | Baptiste Coudurier | switch(tag) {
|
451 | case 0x4801: |
||
452 | b7effd4e | Anton Khirnov | track->track_id = avio_rb32(pb); |
453 | d09ea6ba | Baptiste Coudurier | break;
|
454 | case 0x4804: |
||
455 | b7effd4e | Anton Khirnov | avio_read(pb, track->track_number, 4);
|
456 | d09ea6ba | Baptiste Coudurier | break;
|
457 | case 0x4B01: |
||
458 | b7effd4e | Anton Khirnov | track->edit_rate.den = avio_rb32(pb); |
459 | track->edit_rate.num = avio_rb32(pb); |
||
460 | d09ea6ba | Baptiste Coudurier | break;
|
461 | case 0x4803: |
||
462 | b7effd4e | Anton Khirnov | avio_read(pb, track->sequence_ref, 16);
|
463 | d09ea6ba | Baptiste Coudurier | break;
|
464 | } |
||
465 | return 0; |
||
466 | } |
||
467 | |||
468 | ae628ec1 | Anton Khirnov | static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
469 | d09ea6ba | Baptiste Coudurier | { |
470 | 39bb30f6 | Reimar Döffinger | MXFSequence *sequence = arg; |
471 | d09ea6ba | Baptiste Coudurier | switch(tag) {
|
472 | case 0x0202: |
||
473 | b7effd4e | Anton Khirnov | sequence->duration = avio_rb64(pb); |
474 | d09ea6ba | Baptiste Coudurier | break;
|
475 | case 0x0201: |
||
476 | b7effd4e | Anton Khirnov | avio_read(pb, sequence->data_definition_ul, 16);
|
477 | d09ea6ba | Baptiste Coudurier | break;
|
478 | case 0x1001: |
||
479 | b7effd4e | Anton Khirnov | sequence->structural_components_count = avio_rb32(pb); |
480 | d09ea6ba | Baptiste Coudurier | if (sequence->structural_components_count >= UINT_MAX / sizeof(UID)) |
481 | return -1; |
||
482 | sequence->structural_components_refs = av_malloc(sequence->structural_components_count * sizeof(UID));
|
||
483 | if (!sequence->structural_components_refs)
|
||
484 | return -1; |
||
485 | 45a8a02a | Anton Khirnov | avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
486 | b7effd4e | Anton Khirnov | avio_read(pb, (uint8_t *)sequence->structural_components_refs, sequence->structural_components_count * sizeof(UID));
|
487 | d09ea6ba | Baptiste Coudurier | break;
|
488 | } |
||
489 | return 0; |
||
490 | } |
||
491 | |||
492 | ae628ec1 | Anton Khirnov | static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
493 | d09ea6ba | Baptiste Coudurier | { |
494 | 39bb30f6 | Reimar Döffinger | MXFPackage *package = arg; |
495 | d09ea6ba | Baptiste Coudurier | switch(tag) {
|
496 | case 0x4403: |
||
497 | b7effd4e | Anton Khirnov | package->tracks_count = avio_rb32(pb); |
498 | d09ea6ba | Baptiste Coudurier | if (package->tracks_count >= UINT_MAX / sizeof(UID)) |
499 | return -1; |
||
500 | package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
|
||
501 | if (!package->tracks_refs)
|
||
502 | return -1; |
||
503 | 45a8a02a | Anton Khirnov | avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
504 | b7effd4e | Anton Khirnov | avio_read(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
|
505 | d09ea6ba | Baptiste Coudurier | break;
|
506 | case 0x4401: |
||
507 | /* UMID, only get last 16 bytes */
|
||
508 | 45a8a02a | Anton Khirnov | avio_skip(pb, 16);
|
509 | b7effd4e | Anton Khirnov | avio_read(pb, package->package_uid, 16);
|
510 | d09ea6ba | Baptiste Coudurier | break;
|
511 | case 0x4701: |
||
512 | b7effd4e | Anton Khirnov | avio_read(pb, package->descriptor_ref, 16);
|
513 | d09ea6ba | Baptiste Coudurier | break;
|
514 | } |
||
515 | return 0; |
||
516 | } |
||
517 | |||
518 | ae628ec1 | Anton Khirnov | static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
519 | 861b4f01 | Baptiste Coudurier | { |
520 | switch(tag) {
|
||
521 | b7effd4e | Anton Khirnov | case 0x3F05: av_dlog(NULL, "EditUnitByteCount %d\n", avio_rb32(pb)); break; |
522 | case 0x3F06: av_dlog(NULL, "IndexSID %d\n", avio_rb32(pb)); break; |
||
523 | case 0x3F07: av_dlog(NULL, "BodySID %d\n", avio_rb32(pb)); break; |
||
524 | case 0x3F0B: av_dlog(NULL, "IndexEditRate %d/%d\n", avio_rb32(pb), avio_rb32(pb)); break; |
||
525 | case 0x3F0C: av_dlog(NULL, "IndexStartPosition %lld\n", avio_rb64(pb)); break; |
||
526 | case 0x3F0D: av_dlog(NULL, "IndexDuration %lld\n", avio_rb64(pb)); break; |
||
527 | 861b4f01 | Baptiste Coudurier | } |
528 | return 0; |
||
529 | } |
||
530 | |||
531 | ae628ec1 | Anton Khirnov | static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) |
532 | d09ea6ba | Baptiste Coudurier | { |
533 | 11fdc4d4 | Tomas Härdin | int code, value, ofs = 0; |
534 | 354b7573 | Axel Holzinger | char layout[16] = {0}; |
535 | d09ea6ba | Baptiste Coudurier | |
536 | do {
|
||
537 | b7effd4e | Anton Khirnov | code = avio_r8(pb); |
538 | value = avio_r8(pb); |
||
539 | dfd2a005 | Luca Barbato | av_dlog(NULL, "pixel layout: code %#x\n", code); |
540 | 11fdc4d4 | Tomas Härdin | |
541 | if (ofs < 16) { |
||
542 | layout[ofs++] = code; |
||
543 | layout[ofs++] = value; |
||
544 | d09ea6ba | Baptiste Coudurier | } |
545 | } while (code != 0); /* SMPTE 377M E.2.46 */ |
||
546 | 11fdc4d4 | Tomas Härdin | |
547 | ff_mxf_decode_pixel_layout(layout, &descriptor->pix_fmt); |
||
548 | d09ea6ba | Baptiste Coudurier | } |
549 | |||
550 | ae628ec1 | Anton Khirnov | static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid) |
551 | d09ea6ba | Baptiste Coudurier | { |
552 | 39bb30f6 | Reimar Döffinger | MXFDescriptor *descriptor = arg; |
553 | d09ea6ba | Baptiste Coudurier | switch(tag) {
|
554 | case 0x3F01: |
||
555 | b7effd4e | Anton Khirnov | descriptor->sub_descriptors_count = avio_rb32(pb); |
556 | d09ea6ba | Baptiste Coudurier | if (descriptor->sub_descriptors_count >= UINT_MAX / sizeof(UID)) |
557 | return -1; |
||
558 | descriptor->sub_descriptors_refs = av_malloc(descriptor->sub_descriptors_count * sizeof(UID));
|
||
559 | if (!descriptor->sub_descriptors_refs)
|
||
560 | return -1; |
||
561 | 45a8a02a | Anton Khirnov | avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
562 | b7effd4e | Anton Khirnov | avio_read(pb, (uint8_t *)descriptor->sub_descriptors_refs, descriptor->sub_descriptors_count * sizeof(UID));
|
563 | d09ea6ba | Baptiste Coudurier | break;
|
564 | case 0x3004: |
||
565 | b7effd4e | Anton Khirnov | avio_read(pb, descriptor->essence_container_ul, 16);
|
566 | d09ea6ba | Baptiste Coudurier | break;
|
567 | case 0x3006: |
||
568 | b7effd4e | Anton Khirnov | descriptor->linked_track_id = avio_rb32(pb); |
569 | d09ea6ba | Baptiste Coudurier | break;
|
570 | case 0x3201: /* PictureEssenceCoding */ |
||
571 | b7effd4e | Anton Khirnov | avio_read(pb, descriptor->essence_codec_ul, 16);
|
572 | d09ea6ba | Baptiste Coudurier | break;
|
573 | case 0x3203: |
||
574 | b7effd4e | Anton Khirnov | descriptor->width = avio_rb32(pb); |
575 | d09ea6ba | Baptiste Coudurier | break;
|
576 | case 0x3202: |
||
577 | b7effd4e | Anton Khirnov | descriptor->height = avio_rb32(pb); |
578 | d09ea6ba | Baptiste Coudurier | break;
|
579 | case 0x320E: |
||
580 | b7effd4e | Anton Khirnov | descriptor->aspect_ratio.num = avio_rb32(pb); |
581 | descriptor->aspect_ratio.den = avio_rb32(pb); |
||
582 | d09ea6ba | Baptiste Coudurier | break;
|
583 | case 0x3D03: |
||
584 | b7effd4e | Anton Khirnov | descriptor->sample_rate.num = avio_rb32(pb); |
585 | descriptor->sample_rate.den = avio_rb32(pb); |
||
586 | d09ea6ba | Baptiste Coudurier | break;
|
587 | case 0x3D06: /* SoundEssenceCompression */ |
||
588 | b7effd4e | Anton Khirnov | avio_read(pb, descriptor->essence_codec_ul, 16);
|
589 | d09ea6ba | Baptiste Coudurier | break;
|
590 | case 0x3D07: |
||
591 | b7effd4e | Anton Khirnov | descriptor->channels = avio_rb32(pb); |
592 | d09ea6ba | Baptiste Coudurier | break;
|
593 | case 0x3D01: |
||
594 | b7effd4e | Anton Khirnov | descriptor->bits_per_sample = avio_rb32(pb); |
595 | d09ea6ba | Baptiste Coudurier | break;
|
596 | case 0x3401: |
||
597 | mxf_read_pixel_layout(pb, descriptor); |
||
598 | break;
|
||
599 | default:
|
||
600 | /* Private uid used by SONY C0023S01.mxf */
|
||
601 | if (IS_KLV_KEY(uid, mxf_sony_mpeg4_extradata)) {
|
||
602 | descriptor->extradata = av_malloc(size); |
||
603 | if (!descriptor->extradata)
|
||
604 | return -1; |
||
605 | descriptor->extradata_size = size; |
||
606 | b7effd4e | Anton Khirnov | avio_read(pb, descriptor->extradata, size); |
607 | d09ea6ba | Baptiste Coudurier | } |
608 | break;
|
||
609 | } |
||
610 | return 0; |
||
611 | } |
||
612 | |||
613 | /*
|
||
614 | * Match an uid independently of the version byte and up to len common bytes
|
||
615 | * Returns: boolean
|
||
616 | */
|
||
617 | static int mxf_match_uid(const UID key, const UID uid, int len) |
||
618 | { |
||
619 | int i;
|
||
620 | for (i = 0; i < len; i++) { |
||
621 | if (i != 7 && key[i] != uid[i]) |
||
622 | return 0; |
||
623 | } |
||
624 | return 1; |
||
625 | } |
||
626 | |||
627 | static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid) |
||
628 | { |
||
629 | 5ac4d768 | Baptiste Coudurier | while (uls->uid[0]) { |
630 | d09ea6ba | Baptiste Coudurier | if(mxf_match_uid(uls->uid, *uid, uls->matching_len))
|
631 | break;
|
||
632 | uls++; |
||
633 | } |
||
634 | return uls;
|
||
635 | } |
||
636 | |||
637 | static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMetadataSetType type) |
||
638 | { |
||
639 | int i;
|
||
640 | |||
641 | if (!strong_ref)
|
||
642 | return NULL; |
||
643 | for (i = 0; i < mxf->metadata_sets_count; i++) { |
||
644 | if (!memcmp(*strong_ref, mxf->metadata_sets[i]->uid, 16) && |
||
645 | (type == AnyType || mxf->metadata_sets[i]->type == type)) { |
||
646 | return mxf->metadata_sets[i];
|
||
647 | } |
||
648 | } |
||
649 | return NULL; |
||
650 | } |
||
651 | |||
652 | 4ee873e3 | Baptiste Coudurier | static const MXFCodecUL mxf_essence_container_uls[] = { |
653 | // video essence container uls
|
||
654 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */ |
||
655 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, CODEC_ID_DVVIDEO }, /* DV 625 25mbps */ |
||
656 | // sound essence container uls
|
||
657 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */ |
||
658 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */ |
||
659 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */ |
||
660 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, |
||
661 | }; |
||
662 | |||
663 | d09ea6ba | Baptiste Coudurier | static int mxf_parse_structural_metadata(MXFContext *mxf) |
664 | { |
||
665 | MXFPackage *material_package = NULL;
|
||
666 | MXFPackage *temp_package = NULL;
|
||
667 | int i, j, k;
|
||
668 | |||
669 | dfd2a005 | Luca Barbato | av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count);
|
670 | d09ea6ba | Baptiste Coudurier | /* TODO: handle multiple material packages (OP3x) */
|
671 | for (i = 0; i < mxf->packages_count; i++) { |
||
672 | material_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], MaterialPackage); |
||
673 | if (material_package) break; |
||
674 | } |
||
675 | if (!material_package) {
|
||
676 | av_log(mxf->fc, AV_LOG_ERROR, "no material package found\n");
|
||
677 | return -1; |
||
678 | } |
||
679 | |||
680 | for (i = 0; i < material_package->tracks_count; i++) { |
||
681 | MXFPackage *source_package = NULL;
|
||
682 | MXFTrack *material_track = NULL;
|
||
683 | MXFTrack *source_track = NULL;
|
||
684 | MXFTrack *temp_track = NULL;
|
||
685 | MXFDescriptor *descriptor = NULL;
|
||
686 | MXFStructuralComponent *component = NULL;
|
||
687 | UID *essence_container_ul = NULL;
|
||
688 | const MXFCodecUL *codec_ul = NULL; |
||
689 | const MXFCodecUL *container_ul = NULL; |
||
690 | AVStream *st; |
||
691 | |||
692 | if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) {
|
||
693 | av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n");
|
||
694 | continue;
|
||
695 | } |
||
696 | |||
697 | if (!(material_track->sequence = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, Sequence))) {
|
||
698 | av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track sequence strong ref\n");
|
||
699 | 1e699993 | Reimar Döffinger | continue;
|
700 | d09ea6ba | Baptiste Coudurier | } |
701 | |||
702 | /* TODO: handle multiple source clips */
|
||
703 | for (j = 0; j < material_track->sequence->structural_components_count; j++) { |
||
704 | /* TODO: handle timecode component */
|
||
705 | component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], SourceClip); |
||
706 | if (!component)
|
||
707 | continue;
|
||
708 | |||
709 | for (k = 0; k < mxf->packages_count; k++) { |
||
710 | temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[k], SourcePackage); |
||
711 | if (!temp_package)
|
||
712 | continue;
|
||
713 | if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)) { |
||
714 | source_package = temp_package; |
||
715 | break;
|
||
716 | } |
||
717 | } |
||
718 | if (!source_package) {
|
||
719 | av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source package found\n", material_track->track_id);
|
||
720 | break;
|
||
721 | } |
||
722 | for (k = 0; k < source_package->tracks_count; k++) { |
||
723 | if (!(temp_track = mxf_resolve_strong_ref(mxf, &source_package->tracks_refs[k], Track))) {
|
||
724 | av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
|
||
725 | return -1; |
||
726 | } |
||
727 | if (temp_track->track_id == component->source_track_id) {
|
||
728 | source_track = temp_track; |
||
729 | break;
|
||
730 | } |
||
731 | } |
||
732 | if (!source_track) {
|
||
733 | av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source track found\n", material_track->track_id);
|
||
734 | break;
|
||
735 | } |
||
736 | } |
||
737 | if (!source_track)
|
||
738 | continue;
|
||
739 | |||
740 | st = av_new_stream(mxf->fc, source_track->track_id); |
||
741 | if (!st) {
|
||
742 | av_log(mxf->fc, AV_LOG_ERROR, "could not allocate stream\n");
|
||
743 | return -1; |
||
744 | } |
||
745 | st->priv_data = source_track; |
||
746 | st->duration = component->duration; |
||
747 | if (st->duration == -1) |
||
748 | st->duration = AV_NOPTS_VALUE; |
||
749 | st->start_time = component->start_position; |
||
750 | av_set_pts_info(st, 64, material_track->edit_rate.num, material_track->edit_rate.den);
|
||
751 | |||
752 | if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) {
|
||
753 | av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
|
||
754 | return -1; |
||
755 | } |
||
756 | |||
757 | PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul);
|
||
758 | 5ac4d768 | Baptiste Coudurier | codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul); |
759 | st->codec->codec_type = codec_ul->id; |
||
760 | d09ea6ba | Baptiste Coudurier | |
761 | source_package->descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor_ref, AnyType); |
||
762 | if (source_package->descriptor) {
|
||
763 | if (source_package->descriptor->type == MultipleDescriptor) {
|
||
764 | for (j = 0; j < source_package->descriptor->sub_descriptors_count; j++) { |
||
765 | MXFDescriptor *sub_descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor->sub_descriptors_refs[j], Descriptor); |
||
766 | |||
767 | if (!sub_descriptor) {
|
||
768 | av_log(mxf->fc, AV_LOG_ERROR, "could not resolve sub descriptor strong ref\n");
|
||
769 | continue;
|
||
770 | } |
||
771 | if (sub_descriptor->linked_track_id == source_track->track_id) {
|
||
772 | descriptor = sub_descriptor; |
||
773 | break;
|
||
774 | } |
||
775 | } |
||
776 | } else if (source_package->descriptor->type == Descriptor) |
||
777 | descriptor = source_package->descriptor; |
||
778 | } |
||
779 | if (!descriptor) {
|
||
780 | av_log(mxf->fc, AV_LOG_INFO, "source track %d: stream %d, no descriptor found\n", source_track->track_id, st->index);
|
||
781 | continue;
|
||
782 | } |
||
783 | PRINT_KEY(mxf->fc, "essence codec ul", descriptor->essence_codec_ul);
|
||
784 | PRINT_KEY(mxf->fc, "essence container ul", descriptor->essence_container_ul);
|
||
785 | essence_container_ul = &descriptor->essence_container_ul; |
||
786 | /* HACK: replacing the original key with mxf_encrypted_essence_container
|
||
787 | * is not allowed according to s429-6, try to find correct information anyway */
|
||
788 | if (IS_KLV_KEY(essence_container_ul, mxf_encrypted_essence_container)) {
|
||
789 | av_log(mxf->fc, AV_LOG_INFO, "broken encrypted mxf file\n");
|
||
790 | for (k = 0; k < mxf->metadata_sets_count; k++) { |
||
791 | MXFMetadataSet *metadata = mxf->metadata_sets[k]; |
||
792 | if (metadata->type == CryptoContext) {
|
||
793 | essence_container_ul = &((MXFCryptoContext *)metadata)->source_container_ul; |
||
794 | break;
|
||
795 | } |
||
796 | } |
||
797 | } |
||
798 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */
|
||
799 | c69968b4 | Zhentan Feng | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); |
800 | d09ea6ba | Baptiste Coudurier | st->codec->codec_id = codec_ul->id; |
801 | if (descriptor->extradata) {
|
||
802 | st->codec->extradata = descriptor->extradata; |
||
803 | st->codec->extradata_size = descriptor->extradata_size; |
||
804 | } |
||
805 | 72415b2a | Stefano Sabatini | if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
806 | 4ee873e3 | Baptiste Coudurier | container_ul = mxf_get_codec_ul(mxf_essence_container_uls, essence_container_ul); |
807 | d09ea6ba | Baptiste Coudurier | if (st->codec->codec_id == CODEC_ID_NONE)
|
808 | st->codec->codec_id = container_ul->id; |
||
809 | st->codec->width = descriptor->width; |
||
810 | st->codec->height = descriptor->height; |
||
811 | 11fdc4d4 | Tomas Härdin | if (st->codec->codec_id == CODEC_ID_RAWVIDEO)
|
812 | st->codec->pix_fmt = descriptor->pix_fmt; |
||
813 | d09ea6ba | Baptiste Coudurier | st->need_parsing = AVSTREAM_PARSE_HEADERS; |
814 | 72415b2a | Stefano Sabatini | } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
815 | 4ee873e3 | Baptiste Coudurier | container_ul = mxf_get_codec_ul(mxf_essence_container_uls, essence_container_ul); |
816 | d09ea6ba | Baptiste Coudurier | if (st->codec->codec_id == CODEC_ID_NONE)
|
817 | st->codec->codec_id = container_ul->id; |
||
818 | st->codec->channels = descriptor->channels; |
||
819 | dd1c8f3e | Luca Abeni | st->codec->bits_per_coded_sample = descriptor->bits_per_sample; |
820 | d09ea6ba | Baptiste Coudurier | st->codec->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den; |
821 | /* TODO: implement CODEC_ID_RAWAUDIO */
|
||
822 | if (st->codec->codec_id == CODEC_ID_PCM_S16LE) {
|
||
823 | if (descriptor->bits_per_sample == 24) |
||
824 | st->codec->codec_id = CODEC_ID_PCM_S24LE; |
||
825 | else if (descriptor->bits_per_sample == 32) |
||
826 | st->codec->codec_id = CODEC_ID_PCM_S32LE; |
||
827 | } else if (st->codec->codec_id == CODEC_ID_PCM_S16BE) { |
||
828 | if (descriptor->bits_per_sample == 24) |
||
829 | st->codec->codec_id = CODEC_ID_PCM_S24BE; |
||
830 | else if (descriptor->bits_per_sample == 32) |
||
831 | st->codec->codec_id = CODEC_ID_PCM_S32BE; |
||
832 | } else if (st->codec->codec_id == CODEC_ID_MP2) { |
||
833 | st->need_parsing = AVSTREAM_PARSE_FULL; |
||
834 | } |
||
835 | } |
||
836 | 72415b2a | Stefano Sabatini | if (st->codec->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) { |
837 | d09ea6ba | Baptiste Coudurier | av_log(mxf->fc, AV_LOG_WARNING, "only frame wrapped mappings are correctly supported\n");
|
838 | st->need_parsing = AVSTREAM_PARSE_FULL; |
||
839 | } |
||
840 | } |
||
841 | return 0; |
||
842 | } |
||
843 | |||
844 | static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { |
||
845 | { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack }, |
||
846 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType }, |
||
847 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage }, |
||
848 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage }, |
||
849 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence }, |
||
850 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip }, |
||
851 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor }, |
||
852 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */ |
||
853 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */ |
||
854 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */ |
||
855 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG 2 Video */ |
||
856 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */ |
||
857 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */ |
||
858 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ |
||
859 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ |
||
860 | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext }, |
||
861 | 861b4f01 | Baptiste Coudurier | { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment }, |
862 | d09ea6ba | Baptiste Coudurier | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType }, |
863 | }; |
||
864 | |||
865 | 39bb30f6 | Reimar Döffinger | static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadFunc *read_child, int ctx_size, enum MXFMetadataSetType type) |
866 | d09ea6ba | Baptiste Coudurier | { |
867 | ae628ec1 | Anton Khirnov | AVIOContext *pb = mxf->fc->pb; |
868 | d09ea6ba | Baptiste Coudurier | MXFMetadataSet *ctx = ctx_size ? av_mallocz(ctx_size) : mxf; |
869 | a2704c97 | Anton Khirnov | uint64_t klv_end = avio_tell(pb) + klv->length; |
870 | d09ea6ba | Baptiste Coudurier | |
871 | if (!ctx)
|
||
872 | return -1; |
||
873 | a2704c97 | Anton Khirnov | while (avio_tell(pb) + 4 < klv_end) { |
874 | b7effd4e | Anton Khirnov | int tag = avio_rb16(pb);
|
875 | int size = avio_rb16(pb); /* KLV specified by 0x53 */ |
||
876 | a2704c97 | Anton Khirnov | uint64_t next = avio_tell(pb) + size; |
877 | d09ea6ba | Baptiste Coudurier | UID uid = {0};
|
878 | |||
879 | dfd2a005 | Luca Barbato | av_dlog(mxf->fc, "local tag %#04x size %d\n", tag, size);
|
880 | d09ea6ba | Baptiste Coudurier | if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */ |
881 | 8a47ad5e | Baptiste Coudurier | av_log(mxf->fc, AV_LOG_ERROR, "local tag %#04x with 0 size\n", tag);
|
882 | d09ea6ba | Baptiste Coudurier | continue;
|
883 | } |
||
884 | if (tag > 0x7FFF) { /* dynamic tag */ |
||
885 | int i;
|
||
886 | for (i = 0; i < mxf->local_tags_count; i++) { |
||
887 | int local_tag = AV_RB16(mxf->local_tags+i*18); |
||
888 | if (local_tag == tag) {
|
||
889 | memcpy(uid, mxf->local_tags+i*18+2, 16); |
||
890 | dfd2a005 | Luca Barbato | av_dlog(mxf->fc, "local tag %#04x\n", local_tag);
|
891 | d09ea6ba | Baptiste Coudurier | PRINT_KEY(mxf->fc, "uid", uid);
|
892 | } |
||
893 | } |
||
894 | } |
||
895 | if (ctx_size && tag == 0x3C0A) |
||
896 | b7effd4e | Anton Khirnov | avio_read(pb, ctx->uid, 16);
|
897 | d09ea6ba | Baptiste Coudurier | else if (read_child(ctx, pb, tag, size, uid) < 0) |
898 | return -1; |
||
899 | |||
900 | 6b4aa5da | Anton Khirnov | avio_seek(pb, next, SEEK_SET); |
901 | d09ea6ba | Baptiste Coudurier | } |
902 | if (ctx_size) ctx->type = type;
|
||
903 | return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0; |
||
904 | } |
||
905 | |||
906 | static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) |
||
907 | { |
||
908 | MXFContext *mxf = s->priv_data; |
||
909 | KLVPacket klv; |
||
910 | |||
911 | if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) { |
||
912 | av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
|
||
913 | return -1; |
||
914 | } |
||
915 | 6b4aa5da | Anton Khirnov | avio_seek(s->pb, -14, SEEK_CUR);
|
916 | d09ea6ba | Baptiste Coudurier | mxf->fc = s; |
917 | 66e5b1df | Anton Khirnov | while (!s->pb->eof_reached) {
|
918 | d09ea6ba | Baptiste Coudurier | const MXFMetadataReadTableEntry *metadata;
|
919 | |||
920 | if (klv_read_packet(&klv, s->pb) < 0) |
||
921 | return -1; |
||
922 | PRINT_KEY(s, "read header", klv.key);
|
||
923 | dfd2a005 | Luca Barbato | av_dlog(s, "size %lld offset %#llx\n", klv.length, klv.offset);
|
924 | d09ea6ba | Baptiste Coudurier | if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) ||
|
925 | IS_KLV_KEY(klv.key, mxf_essence_element_key)) { |
||
926 | /* FIXME avoid seek */
|
||
927 | 6b4aa5da | Anton Khirnov | avio_seek(s->pb, klv.offset, SEEK_SET); |
928 | d09ea6ba | Baptiste Coudurier | break;
|
929 | } |
||
930 | |||
931 | for (metadata = mxf_metadata_read_table; metadata->read; metadata++) {
|
||
932 | if (IS_KLV_KEY(klv.key, metadata->key)) {
|
||
933 | 39bb30f6 | Reimar Döffinger | int res;
|
934 | if (klv.key[5] == 0x53) { |
||
935 | res = mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type); |
||
936 | } else
|
||
937 | res = metadata->read(mxf, s->pb, 0, 0, NULL); |
||
938 | if (res < 0) { |
||
939 | d09ea6ba | Baptiste Coudurier | av_log(s, AV_LOG_ERROR, "error reading header metadata\n");
|
940 | return -1; |
||
941 | } |
||
942 | break;
|
||
943 | } |
||
944 | } |
||
945 | if (!metadata->read)
|
||
946 | 45a8a02a | Anton Khirnov | avio_skip(s->pb, klv.length); |
947 | d09ea6ba | Baptiste Coudurier | } |
948 | return mxf_parse_structural_metadata(mxf);
|
||
949 | } |
||
950 | |||
951 | static int mxf_read_close(AVFormatContext *s) |
||
952 | { |
||
953 | MXFContext *mxf = s->priv_data; |
||
954 | int i;
|
||
955 | |||
956 | av_freep(&mxf->packages_refs); |
||
957 | 8be080ae | Baptiste Coudurier | |
958 | for (i = 0; i < s->nb_streams; i++) |
||
959 | s->streams[i]->priv_data = NULL;
|
||
960 | |||
961 | d09ea6ba | Baptiste Coudurier | for (i = 0; i < mxf->metadata_sets_count; i++) { |
962 | switch (mxf->metadata_sets[i]->type) {
|
||
963 | case MultipleDescriptor:
|
||
964 | av_freep(&((MXFDescriptor *)mxf->metadata_sets[i])->sub_descriptors_refs); |
||
965 | break;
|
||
966 | case Sequence:
|
||
967 | av_freep(&((MXFSequence *)mxf->metadata_sets[i])->structural_components_refs); |
||
968 | break;
|
||
969 | case SourcePackage:
|
||
970 | case MaterialPackage:
|
||
971 | av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs); |
||
972 | break;
|
||
973 | default:
|
||
974 | break;
|
||
975 | } |
||
976 | av_freep(&mxf->metadata_sets[i]); |
||
977 | } |
||
978 | av_freep(&mxf->metadata_sets); |
||
979 | av_freep(&mxf->aesc); |
||
980 | av_freep(&mxf->local_tags); |
||
981 | return 0; |
||
982 | } |
||
983 | |||
984 | static int mxf_probe(AVProbeData *p) { |
||
985 | uint8_t *bufp = p->buf; |
||
986 | uint8_t *end = p->buf + p->buf_size; |
||
987 | |||
988 | if (p->buf_size < sizeof(mxf_header_partition_pack_key)) |
||
989 | return 0; |
||
990 | |||
991 | /* Must skip Run-In Sequence and search for MXF header partition pack key SMPTE 377M 5.5 */
|
||
992 | end -= sizeof(mxf_header_partition_pack_key);
|
||
993 | for (; bufp < end; bufp++) {
|
||
994 | if (IS_KLV_KEY(bufp, mxf_header_partition_pack_key))
|
||
995 | return AVPROBE_SCORE_MAX;
|
||
996 | } |
||
997 | return 0; |
||
998 | } |
||
999 | |||
1000 | /* rudimentary byte seek */
|
||
1001 | /* XXX: use MXF Index */
|
||
1002 | static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) |
||
1003 | { |
||
1004 | AVStream *st = s->streams[stream_index]; |
||
1005 | int64_t seconds; |
||
1006 | |||
1007 | if (!s->bit_rate)
|
||
1008 | return -1; |
||
1009 | if (sample_time < 0) |
||
1010 | sample_time = 0;
|
||
1011 | seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den); |
||
1012 | 6b4aa5da | Anton Khirnov | avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
|
1013 | d09ea6ba | Baptiste Coudurier | av_update_cur_dts(s, st, sample_time); |
1014 | return 0; |
||
1015 | } |
||
1016 | |||
1017 | c6610a21 | Diego Elio Pettenò | AVInputFormat ff_mxf_demuxer = { |
1018 | d09ea6ba | Baptiste Coudurier | "mxf",
|
1019 | NULL_IF_CONFIG_SMALL("Material eXchange Format"),
|
||
1020 | sizeof(MXFContext),
|
||
1021 | mxf_probe, |
||
1022 | mxf_read_header, |
||
1023 | mxf_read_packet, |
||
1024 | mxf_read_close, |
||
1025 | mxf_read_seek, |
||
1026 | }; |