Mercurial > libavformat.hg
comparison mxf.c @ 1186:fbdd53c2a12d libavformat
MXF demuxer
author | bcoudurier |
---|---|
date | Tue, 25 Jul 2006 14:30:14 +0000 |
parents | |
children | 19f761156b1f |
comparison
equal
deleted
inserted
replaced
1185:13dc486b272b | 1186:fbdd53c2a12d |
---|---|
1 /* | |
2 * MXF demuxer. | |
3 * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 */ | |
19 | |
20 /* | |
21 * References | |
22 * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value | |
23 * SMPTE 377M MXF File Format Specifications | |
24 * SMPTE 378M Operational Pattern 1a | |
25 * SMPTE 379M MXF Generic Container | |
26 * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container | |
27 * SMPTE 382M Mapping AES3 and Broadcast Wave Audio into the MXF Generic Container | |
28 * SMPTE 383M Mapping DV-DIF Data to the MXF Generic Container | |
29 * | |
30 * Principle | |
31 * Search for Track numbers which will identify essence element KLV packets. | |
32 * Search for SourcePackage which define tracks which contains Track numbers. | |
33 * Material Package tracks does not contain Tracks numbers. | |
34 * Search for Descriptors (Picture, Sound) which contains codec info and parameters. | |
35 * Assign Descriptors to correct Tracks. | |
36 * | |
37 * Preliminary demuxer, only OP1A supported and some files might not work at all. | |
38 */ | |
39 | |
40 //#define DEBUG | |
41 | |
42 #include "avformat.h" | |
43 #include "dsputil.h" | |
44 #include "riff.h" | |
45 | |
46 typedef struct { | |
47 AVStream *stream; | |
48 uint8_t track_uid[16]; | |
49 uint8_t sequence_uid[16]; | |
50 int track_id; | |
51 int track_number; | |
52 } MXFTrack; | |
53 | |
54 typedef struct { | |
55 DECLARE_ALIGNED_16(uint8_t, essence_container[16]); | |
56 DECLARE_ALIGNED_16(uint8_t, essence_compression[16]); | |
57 enum CodecType codec_type; | |
58 AVRational sample_rate; | |
59 AVRational aspect_ratio; | |
60 int width; | |
61 int height; | |
62 int channels; | |
63 int bits_per_sample; | |
64 int block_align; | |
65 int linked_track_id; | |
66 int kind; | |
67 } MXFDescriptor; | |
68 | |
69 typedef struct { | |
70 AVFormatContext *fc; | |
71 MXFTrack *tracks; | |
72 MXFDescriptor *descriptors; | |
73 int descriptors_count; | |
74 int tracks_count; | |
75 } MXFContext; | |
76 | |
77 typedef struct { | |
78 DECLARE_ALIGNED_16(uint8_t, key[16]); | |
79 offset_t offset; | |
80 uint64_t length; | |
81 } KLVPacket; | |
82 | |
83 static const uint8_t mxf_metadata_source_package_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x37, 0x00 }; | |
84 static const uint8_t mxf_metadata_sequence_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x00 }; | |
85 static const uint8_t mxf_metadata_generic_sound_descriptor_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x00 }; | |
86 static const uint8_t mxf_metadata_cdci_descriptor_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x00 }; | |
87 static const uint8_t mxf_metadata_mpegvideo_descriptor_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x51, 0x00 }; | |
88 static const uint8_t mxf_metadata_wave_descriptor_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x48, 0x00 }; | |
89 static const uint8_t mxf_metadata_track_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3b, 0x00 }; | |
90 static const uint8_t mxf_header_partition_pack_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01, 0x01, 0x02 }; | |
91 static const uint8_t mxf_essence_element_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01 }; | |
92 | |
93 #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) | |
94 | |
95 #define PRINT_KEY(x) \ | |
96 do { \ | |
97 int iterpk; \ | |
98 for (iterpk = 0; iterpk < 16; iterpk++) { \ | |
99 av_log(NULL, AV_LOG_DEBUG, "%02X ", x[iterpk]); \ | |
100 } \ | |
101 av_log(NULL, AV_LOG_DEBUG, "\n"); \ | |
102 } while (0); \ | |
103 | |
104 static int64_t klv_decode_ber_length(ByteIOContext *pb) | |
105 { | |
106 int64_t size = 0; | |
107 uint8_t length = get_byte(pb); | |
108 int type = length >> 7; | |
109 | |
110 if (type) { /* long form */ | |
111 int bytes_num = length & 0x7f; | |
112 /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */ | |
113 if (bytes_num > 8) | |
114 return -1; | |
115 while (bytes_num--) | |
116 size = size << 8 | get_byte(pb); | |
117 } else { | |
118 size = length & 0x7f; | |
119 } | |
120 return size; | |
121 } | |
122 | |
123 static int klv_read_packet(KLVPacket *klv, ByteIOContext *pb) | |
124 { | |
125 klv->offset = url_ftell(pb); | |
126 get_buffer(pb, klv->key, 16); | |
127 klv->length = klv_decode_ber_length(pb); | |
128 if (klv->length == -1) | |
129 return -1; | |
130 else | |
131 return 0; | |
132 } | |
133 | |
134 static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv) | |
135 { | |
136 int id = BE_32(klv->key + 12); /* SMPTE 379M 7.3 */ | |
137 int i; | |
138 | |
139 for (i = 0; i < s->nb_streams; i++) { | |
140 if (s->streams[i]->id == id) | |
141 return i; | |
142 } | |
143 return -1; | |
144 } | |
145 | |
146 static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
147 { | |
148 KLVPacket klv; | |
149 | |
150 while (!url_feof(&s->pb)) { | |
151 if (klv_read_packet(&klv, &s->pb) < 0) | |
152 return -1; | |
153 if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
154 av_get_packet(&s->pb, pkt, klv.length); | |
155 pkt->stream_index = mxf_get_stream_index(s, &klv); | |
156 if (pkt->stream_index == -1) | |
157 return -1; | |
158 return 0; | |
159 } else | |
160 url_fskip(&s->pb, klv.length); | |
161 } | |
162 return AVERROR_IO; | |
163 } | |
164 | |
165 static int mxf_read_metadata_track(MXFContext *mxf, KLVPacket *klv) | |
166 { | |
167 ByteIOContext *pb = &mxf->fc->pb; | |
168 AVRational time_base = (AVRational){0, 0}; | |
169 uint8_t sequence_uid[16]; | |
170 uint8_t track_uid[16]; | |
171 int track_number = 0; | |
172 int track_id = 0; | |
173 int bytes_read = 0; | |
174 int i; | |
175 | |
176 while (bytes_read < klv->length) { | |
177 int tag = get_be16(pb); | |
178 int size = get_be16(pb); /* SMPTE 336M Table 8 KLV specified length, 0x53 */ | |
179 | |
180 switch (tag) { | |
181 case 0x4801: | |
182 track_id = get_be32(pb); | |
183 break; | |
184 case 0x4804: | |
185 track_number = get_be32(pb); | |
186 break; | |
187 case 0x4B01: | |
188 time_base.den = get_be32(pb); | |
189 time_base.num = get_be32(pb); | |
190 break; | |
191 case 0x4803: | |
192 get_buffer(pb, sequence_uid, 16); | |
193 break; | |
194 case 0x3C0A: | |
195 get_buffer(pb, track_uid, 16); | |
196 break; | |
197 default: | |
198 url_fskip(pb, size); | |
199 } | |
200 bytes_read += size + 4; | |
201 } | |
202 for (i = 0; i < mxf->tracks_count; i++) | |
203 if (!memcmp(track_uid, mxf->tracks[i].track_uid, 16)) { | |
204 mxf->tracks[i].track_id = track_id; | |
205 mxf->tracks[i].track_number = track_number; | |
206 mxf->tracks[i].stream->time_base = time_base; | |
207 mxf->tracks[i].stream->id = track_number; | |
208 memcpy(mxf->tracks[i].sequence_uid, sequence_uid, 16); | |
209 } | |
210 return bytes_read; | |
211 } | |
212 | |
213 static int mxf_read_metadata_sequence(MXFContext *mxf, KLVPacket *klv) | |
214 { | |
215 ByteIOContext *pb = &mxf->fc->pb; | |
216 uint8_t sequence_uid[16]; | |
217 uint8_t data_definition[16]; | |
218 uint64_t duration = 0; | |
219 int bytes_read = 0; | |
220 int i; | |
221 | |
222 while (bytes_read < klv->length) { | |
223 int tag = get_be16(pb); | |
224 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
225 | |
226 switch (tag) { | |
227 case 0x3C0A: | |
228 get_buffer(pb, sequence_uid, 16); | |
229 break; | |
230 case 0x0202: | |
231 duration = get_be64(pb); | |
232 break; | |
233 case 0x0201: | |
234 get_buffer(pb, data_definition, 16); | |
235 break; | |
236 default: | |
237 url_fskip(pb, size); | |
238 } | |
239 bytes_read += size + 4; | |
240 } | |
241 | |
242 for (i = 0; i < mxf->tracks_count; i++) | |
243 if (!memcmp(sequence_uid, mxf->tracks[i].sequence_uid, 16)) { | |
244 mxf->tracks[i].stream->duration = duration; | |
245 if (data_definition[11] == 0x02 && data_definition[12] == 0x01) | |
246 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_VIDEO; | |
247 else if (data_definition[11] == 0x02 && data_definition[12] == 0x02) | |
248 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_AUDIO; | |
249 else if (data_definition[11] == 0x01) /* SMPTE 12M Time Code track */ | |
250 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_DATA; | |
251 } | |
252 return bytes_read; | |
253 } | |
254 | |
255 static int mxf_read_metadata_source_package(MXFContext *mxf, KLVPacket *klv) | |
256 { | |
257 ByteIOContext *pb = &mxf->fc->pb; | |
258 int tracks_count; | |
259 int bytes_read = 0; | |
260 int i; | |
261 | |
262 while (bytes_read < klv->length) { | |
263 int tag = get_be16(pb); | |
264 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
265 | |
266 switch (tag) { | |
267 case 0x4403: | |
268 tracks_count = get_be32(pb); | |
269 if(tracks_count >= UINT_MAX / sizeof(*mxf->tracks) || | |
270 tracks_count >= UINT_MAX / sizeof(*mxf->descriptors)) | |
271 return -1; | |
272 mxf->tracks_count += tracks_count; /* op2a contains multiple source packages */ | |
273 mxf->tracks = av_realloc(mxf->tracks, mxf->tracks_count * sizeof(*mxf->tracks)); | |
274 mxf->descriptors = av_realloc(mxf->descriptors, mxf->tracks_count * sizeof(*mxf->descriptors)); | |
275 url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */ | |
276 for (i = mxf->tracks_count - tracks_count; i < mxf->tracks_count; i++) { | |
277 mxf->tracks[i].stream = av_new_stream(mxf->fc, 0); | |
278 get_buffer(pb, mxf->tracks[i].track_uid, 16); | |
279 } | |
280 break; | |
281 default: | |
282 url_fskip(pb, size); | |
283 } | |
284 bytes_read += size + 4; | |
285 } | |
286 return bytes_read; | |
287 } | |
288 | |
289 static int mxf_read_metadata_descriptor(MXFContext *mxf, KLVPacket *klv) | |
290 { | |
291 ByteIOContext *pb = &mxf->fc->pb; | |
292 MXFDescriptor *desc; | |
293 int bytes_read = 0; | |
294 | |
295 if (mxf->descriptors_count == mxf->tracks_count) | |
296 return -1; | |
297 desc = &mxf->descriptors[mxf->descriptors_count++]; | |
298 desc->kind = klv->key[14]; | |
299 desc->linked_track_id = -1; | |
300 | |
301 while (bytes_read < klv->length) { | |
302 int tag = get_be16(pb); | |
303 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
304 | |
305 switch (tag) { | |
306 case 0x3004: | |
307 get_buffer(pb, desc->essence_container, 16); | |
308 break; | |
309 case 0x3006: | |
310 desc->linked_track_id = get_be32(pb); | |
311 break; | |
312 case 0x3201: /* PictureEssenceCoding */ | |
313 desc->codec_type = CODEC_TYPE_VIDEO; | |
314 get_buffer(pb, desc->essence_compression, 16); | |
315 break; | |
316 case 0x3203: | |
317 desc->width = get_be32(pb); | |
318 break; | |
319 case 0x3202: | |
320 desc->height = get_be32(pb); | |
321 break; | |
322 case 0x320E: | |
323 desc->aspect_ratio.num = get_be32(pb); | |
324 desc->aspect_ratio.den = get_be32(pb); | |
325 break; | |
326 case 0x3D0A: | |
327 desc->block_align = get_be16(pb); | |
328 break; | |
329 case 0x3D03: | |
330 desc->sample_rate.num = get_be32(pb); | |
331 desc->sample_rate.den = get_be32(pb); | |
332 break; | |
333 case 0x3D06: /* SoundEssenceCompression */ | |
334 desc->codec_type = CODEC_TYPE_AUDIO; | |
335 get_buffer(pb, desc->essence_compression, 16); | |
336 break; | |
337 case 0x3D07: | |
338 desc->channels = get_be32(pb); | |
339 break; | |
340 case 0x3D01: | |
341 desc->bits_per_sample = get_be32(pb); | |
342 break; | |
343 default: | |
344 url_fskip(pb, size); | |
345 } | |
346 bytes_read += size + 4; | |
347 } | |
348 return bytes_read; | |
349 } | |
350 | |
351 /* SMPTE RP224 http://www.smpte-ra.org/mdd/index.html */ | |
352 static const CodecTag mxf_sound_essence_labels[] = { | |
353 { CODEC_ID_PCM_S16LE, 0x01000000 },/* Uncompressed Sound Coding */ | |
354 { CODEC_ID_PCM_S16LE, 0x017F0000 },/* Uncompressed Sound Coding */ | |
355 { CODEC_ID_PCM_S16BE, 0x017E0000 },/* Uncompressed Sound Coding Big Endian*/ | |
356 { CODEC_ID_PCM_ALAW, 0x02030101 }, | |
357 { CODEC_ID_AC3, 0x02030201 }, | |
358 //{ CODEC_ID_MP1, 0x02030104 }, | |
359 { CODEC_ID_MP2, 0x02030105 },/* MP2 or MP3 */ | |
360 //{ CODEC_ID_MP2, 0x02030106 },/* MPEG-2 Layer 1 */ | |
361 //{ CODEC_ID_???, 0x0203010C },/* Dolby E */ | |
362 //{ CODEC_ID_???, 0x02030301 },/* MPEG-2 AAC */ | |
363 { 0, 0 }, | |
364 }; | |
365 | |
366 static const CodecTag mxf_picture_essence_labels[] = { | |
367 { CODEC_ID_RAWVIDEO, 0x0100 }, | |
368 { CODEC_ID_MPEG2VIDEO, 0x0201 }, | |
369 { CODEC_ID_DVVIDEO, 0x0202 }, | |
370 //{ CODEC_ID_???, 0x0207 },/* D-11 HDCAM */ | |
371 { 0, 0 }, | |
372 }; | |
373 | |
374 static const CodecTag mxf_container_picture_labels[] = { | |
375 { CODEC_ID_MPEG2VIDEO, 0x0201 }, /* D-10 Mapping */ | |
376 { CODEC_ID_DVVIDEO, 0x0202 }, /* DV Mapping */ | |
377 //{ CODEC_ID_???, 0x0203 }, /* HDCAM D-11 Mapping */ | |
378 { CODEC_ID_MPEG2VIDEO, 0x0204 }, /* MPEG ES Mapping */ | |
379 }; | |
380 | |
381 static const CodecTag mxf_container_sound_labels[] = { | |
382 //{ CODEC_ID_PCM_S16??, 0x0201 }, /* D-10 Mapping */ | |
383 { CODEC_ID_MP2, 0x0204 }, /* MPEG ES Mapping */ | |
384 { CODEC_ID_PCM_S16LE, 0x0206 }, /* AES BWF Mapping */ | |
385 { CODEC_ID_PCM_ALAW, 0x020A }, | |
386 { 0, 0 }, | |
387 }; | |
388 | |
389 static void mxf_resolve_track_descriptor(MXFContext *mxf) | |
390 { | |
391 uint32_t container_label; | |
392 uint32_t essence_label; | |
393 int i, j; | |
394 | |
395 for (i = 0; i < mxf->descriptors_count; i++) { | |
396 for (j = 0; j < mxf->tracks_count; j++) { | |
397 AVStream *st = mxf->tracks[j].stream; | |
398 MXFDescriptor *desc = &mxf->descriptors[i]; | |
399 | |
400 if ((desc->linked_track_id == -1 && st->codec->codec_type == desc->codec_type) | |
401 || desc->linked_track_id == mxf->tracks[j].track_id) { | |
402 if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
403 st->codec->channels = desc->channels; | |
404 st->codec->bits_per_sample = desc->bits_per_sample; | |
405 st->codec->block_align = desc->block_align; | |
406 st->codec->sample_rate = desc->sample_rate.num / desc->sample_rate.den; | |
407 | |
408 container_label = BE_16(desc->essence_container + 12); | |
409 essence_label = BE_32(desc->essence_compression + 11); | |
410 st->codec->codec_id = codec_get_id(mxf_sound_essence_labels, essence_label); | |
411 if (st->codec->codec_id == CODEC_ID_PCM_S16LE) { | |
412 if (desc->bits_per_sample == 24) | |
413 st->codec->codec_id = CODEC_ID_PCM_S24LE; | |
414 else if (desc->bits_per_sample == 32) | |
415 st->codec->codec_id = CODEC_ID_PCM_S32LE; | |
416 } | |
417 if (st->codec->codec_id == CODEC_ID_PCM_S16BE) { | |
418 if (desc->bits_per_sample == 24) | |
419 st->codec->codec_id = CODEC_ID_PCM_S24BE; | |
420 else if (desc->bits_per_sample == 32) | |
421 st->codec->codec_id = CODEC_ID_PCM_S32BE; | |
422 } | |
423 if (!st->codec->codec_id) | |
424 st->codec->codec_id = codec_get_id(mxf_container_sound_labels, container_label); | |
425 | |
426 } else if (st->codec->codec_type == CODEC_TYPE_VIDEO) { | |
427 st->codec->width = desc->width; | |
428 st->codec->height = desc->height; | |
429 | |
430 container_label = BE_16(desc->essence_container + 12); | |
431 essence_label = BE_16(desc->essence_compression + 11); | |
432 st->codec->codec_id = codec_get_id(mxf_picture_essence_labels, essence_label); | |
433 if (!st->codec->codec_id) | |
434 st->codec->codec_id = codec_get_id(mxf_container_picture_labels, container_label); | |
435 } | |
436 } | |
437 } | |
438 } | |
439 } | |
440 | |
441 static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
442 { | |
443 MXFContext *mxf = s->priv_data; | |
444 KLVPacket klv; | |
445 int ret = 0; | |
446 | |
447 mxf->fc = s; | |
448 while (!url_feof(&s->pb)) { | |
449 if (klv_read_packet(&klv, &s->pb) < 0) | |
450 return -1; | |
451 if (IS_KLV_KEY(klv.key, mxf_metadata_track_key)) | |
452 ret = mxf_read_metadata_track(mxf, &klv); | |
453 else if (IS_KLV_KEY(klv.key, mxf_metadata_source_package_key)) | |
454 ret = mxf_read_metadata_source_package(mxf, &klv); | |
455 else if (IS_KLV_KEY(klv.key, mxf_metadata_sequence_key)) | |
456 ret = mxf_read_metadata_sequence(mxf, &klv); | |
457 else if (IS_KLV_KEY(klv.key, mxf_metadata_wave_descriptor_key)) | |
458 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
459 else if (IS_KLV_KEY(klv.key, mxf_metadata_mpegvideo_descriptor_key)) | |
460 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
461 else if (IS_KLV_KEY(klv.key, mxf_metadata_cdci_descriptor_key)) | |
462 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
463 else if (IS_KLV_KEY(klv.key, mxf_metadata_generic_sound_descriptor_key)) | |
464 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
465 else if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
466 /* FIXME avoid seek */ | |
467 url_fseek(&s->pb, klv.offset, SEEK_SET); | |
468 break; | |
469 } else | |
470 url_fskip(&s->pb, klv.length); | |
471 if (ret < 0) | |
472 return ret; | |
473 } | |
474 mxf_resolve_track_descriptor(mxf); | |
475 return 0; | |
476 } | |
477 | |
478 static int mxf_read_close(AVFormatContext *s) | |
479 { | |
480 MXFContext *mxf = s->priv_data; | |
481 | |
482 av_freep(&mxf->tracks); | |
483 av_freep(&mxf->descriptors); | |
484 return 0; | |
485 } | |
486 | |
487 static int mxf_probe(AVProbeData *p) { | |
488 /* KLV packet describing MXF header partition pack */ | |
489 if (p->buf_size < sizeof(mxf_header_partition_pack_key)) | |
490 return 0; | |
491 | |
492 if (IS_KLV_KEY(p->buf, mxf_header_partition_pack_key)) | |
493 return AVPROBE_SCORE_MAX; | |
494 else | |
495 return 0; | |
496 } | |
497 | |
498 | |
499 AVInputFormat mxf_demuxer = { | |
500 "mxf", | |
501 "MXF format", | |
502 sizeof(MXFContext), | |
503 mxf_probe, | |
504 mxf_read_header, | |
505 mxf_read_packet, | |
506 mxf_read_close, | |
507 NULL, | |
508 }; |