Mercurial > libavformat.hg
annotate mxf.c @ 1189:fb1a9ccffe89 libavformat
declare and use UID type
author | bcoudurier |
---|---|
date | Fri, 28 Jul 2006 18:18:12 +0000 |
parents | 19f761156b1f |
children | 03c0b0e61e5b |
rev | line source |
---|---|
1186 | 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 | |
1189 | 46 typedef DECLARE_ALIGNED_16(uint8_t, UID[16]); |
47 | |
1186 | 48 typedef struct { |
49 AVStream *stream; | |
1189 | 50 UID track_uid; |
51 UID sequence_uid; | |
1186 | 52 int track_id; |
53 int track_number; | |
54 } MXFTrack; | |
55 | |
56 typedef struct { | |
1189 | 57 UID essence_container; |
58 UID essence_compression; | |
1186 | 59 enum CodecType codec_type; |
60 AVRational sample_rate; | |
61 AVRational aspect_ratio; | |
62 int width; | |
63 int height; | |
64 int channels; | |
65 int bits_per_sample; | |
66 int block_align; | |
67 int linked_track_id; | |
68 int kind; | |
69 } MXFDescriptor; | |
70 | |
71 typedef struct { | |
72 AVFormatContext *fc; | |
73 MXFTrack *tracks; | |
74 MXFDescriptor *descriptors; | |
75 int descriptors_count; | |
76 int tracks_count; | |
77 } MXFContext; | |
78 | |
79 typedef struct { | |
1189 | 80 UID key; |
1186 | 81 offset_t offset; |
82 uint64_t length; | |
83 } KLVPacket; | |
84 | |
1189 | 85 static const UID mxf_metadata_source_package_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x37, 0x00 }; |
86 static const UID mxf_metadata_sequence_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x00 }; | |
87 static const UID mxf_metadata_generic_sound_descriptor_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x00 }; | |
88 static const UID mxf_metadata_cdci_descriptor_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x00 }; | |
89 static const UID mxf_metadata_mpegvideo_descriptor_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x51, 0x00 }; | |
90 static const UID mxf_metadata_wave_descriptor_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x48, 0x00 }; | |
91 static const UID mxf_metadata_track_key = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3b, 0x00 }; | |
92 | |
93 /* partial keys to match */ | |
94 static const uint8_t mxf_header_partition_pack_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01, 0x01, 0x02 }; | |
95 static const uint8_t mxf_essence_element_key[] = { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01 }; | |
1186 | 96 |
97 #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) | |
98 | |
99 #define PRINT_KEY(x) \ | |
100 do { \ | |
101 int iterpk; \ | |
102 for (iterpk = 0; iterpk < 16; iterpk++) { \ | |
103 av_log(NULL, AV_LOG_DEBUG, "%02X ", x[iterpk]); \ | |
104 } \ | |
105 av_log(NULL, AV_LOG_DEBUG, "\n"); \ | |
106 } while (0); \ | |
107 | |
108 static int64_t klv_decode_ber_length(ByteIOContext *pb) | |
109 { | |
110 int64_t size = 0; | |
111 uint8_t length = get_byte(pb); | |
112 int type = length >> 7; | |
113 | |
114 if (type) { /* long form */ | |
115 int bytes_num = length & 0x7f; | |
116 /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */ | |
117 if (bytes_num > 8) | |
118 return -1; | |
119 while (bytes_num--) | |
120 size = size << 8 | get_byte(pb); | |
121 } else { | |
122 size = length & 0x7f; | |
123 } | |
124 return size; | |
125 } | |
126 | |
127 static int klv_read_packet(KLVPacket *klv, ByteIOContext *pb) | |
128 { | |
129 klv->offset = url_ftell(pb); | |
130 get_buffer(pb, klv->key, 16); | |
131 klv->length = klv_decode_ber_length(pb); | |
132 if (klv->length == -1) | |
133 return -1; | |
134 else | |
135 return 0; | |
136 } | |
137 | |
138 static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv) | |
139 { | |
140 int id = BE_32(klv->key + 12); /* SMPTE 379M 7.3 */ | |
141 int i; | |
142 | |
143 for (i = 0; i < s->nb_streams; i++) { | |
144 if (s->streams[i]->id == id) | |
145 return i; | |
146 } | |
147 return -1; | |
148 } | |
149 | |
150 static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
151 { | |
152 KLVPacket klv; | |
153 | |
154 while (!url_feof(&s->pb)) { | |
155 if (klv_read_packet(&klv, &s->pb) < 0) | |
156 return -1; | |
157 if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
158 av_get_packet(&s->pb, pkt, klv.length); | |
159 pkt->stream_index = mxf_get_stream_index(s, &klv); | |
160 if (pkt->stream_index == -1) | |
161 return -1; | |
162 return 0; | |
163 } else | |
164 url_fskip(&s->pb, klv.length); | |
165 } | |
166 return AVERROR_IO; | |
167 } | |
168 | |
169 static int mxf_read_metadata_track(MXFContext *mxf, KLVPacket *klv) | |
170 { | |
171 ByteIOContext *pb = &mxf->fc->pb; | |
172 AVRational time_base = (AVRational){0, 0}; | |
173 uint8_t sequence_uid[16]; | |
174 uint8_t track_uid[16]; | |
175 int track_number = 0; | |
176 int track_id = 0; | |
177 int bytes_read = 0; | |
178 int i; | |
179 | |
180 while (bytes_read < klv->length) { | |
181 int tag = get_be16(pb); | |
182 int size = get_be16(pb); /* SMPTE 336M Table 8 KLV specified length, 0x53 */ | |
183 | |
184 switch (tag) { | |
185 case 0x4801: | |
186 track_id = get_be32(pb); | |
187 break; | |
188 case 0x4804: | |
189 track_number = get_be32(pb); | |
190 break; | |
191 case 0x4B01: | |
192 time_base.den = get_be32(pb); | |
193 time_base.num = get_be32(pb); | |
194 break; | |
195 case 0x4803: | |
196 get_buffer(pb, sequence_uid, 16); | |
197 break; | |
198 case 0x3C0A: | |
199 get_buffer(pb, track_uid, 16); | |
200 break; | |
201 default: | |
202 url_fskip(pb, size); | |
203 } | |
204 bytes_read += size + 4; | |
205 } | |
206 for (i = 0; i < mxf->tracks_count; i++) | |
207 if (!memcmp(track_uid, mxf->tracks[i].track_uid, 16)) { | |
208 mxf->tracks[i].track_id = track_id; | |
209 mxf->tracks[i].track_number = track_number; | |
210 mxf->tracks[i].stream->time_base = time_base; | |
211 mxf->tracks[i].stream->id = track_number; | |
212 memcpy(mxf->tracks[i].sequence_uid, sequence_uid, 16); | |
213 } | |
214 return bytes_read; | |
215 } | |
216 | |
217 static int mxf_read_metadata_sequence(MXFContext *mxf, KLVPacket *klv) | |
218 { | |
219 ByteIOContext *pb = &mxf->fc->pb; | |
220 uint8_t sequence_uid[16]; | |
221 uint8_t data_definition[16]; | |
1188
19f761156b1f
Set duration to AV_NOPTS_VALUE instead of 0 when unknown.
reimar
parents:
1186
diff
changeset
|
222 uint64_t duration = AV_NOPTS_VALUE; |
1186 | 223 int bytes_read = 0; |
224 int i; | |
225 | |
226 while (bytes_read < klv->length) { | |
227 int tag = get_be16(pb); | |
228 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
229 | |
230 switch (tag) { | |
231 case 0x3C0A: | |
232 get_buffer(pb, sequence_uid, 16); | |
233 break; | |
234 case 0x0202: | |
235 duration = get_be64(pb); | |
236 break; | |
237 case 0x0201: | |
238 get_buffer(pb, data_definition, 16); | |
239 break; | |
240 default: | |
241 url_fskip(pb, size); | |
242 } | |
243 bytes_read += size + 4; | |
244 } | |
245 | |
246 for (i = 0; i < mxf->tracks_count; i++) | |
247 if (!memcmp(sequence_uid, mxf->tracks[i].sequence_uid, 16)) { | |
1188
19f761156b1f
Set duration to AV_NOPTS_VALUE instead of 0 when unknown.
reimar
parents:
1186
diff
changeset
|
248 mxf->tracks[i].stream->start_time = 0; |
1186 | 249 mxf->tracks[i].stream->duration = duration; |
250 if (data_definition[11] == 0x02 && data_definition[12] == 0x01) | |
251 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_VIDEO; | |
252 else if (data_definition[11] == 0x02 && data_definition[12] == 0x02) | |
253 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_AUDIO; | |
254 else if (data_definition[11] == 0x01) /* SMPTE 12M Time Code track */ | |
255 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_DATA; | |
256 } | |
257 return bytes_read; | |
258 } | |
259 | |
260 static int mxf_read_metadata_source_package(MXFContext *mxf, KLVPacket *klv) | |
261 { | |
262 ByteIOContext *pb = &mxf->fc->pb; | |
263 int tracks_count; | |
264 int bytes_read = 0; | |
265 int i; | |
266 | |
267 while (bytes_read < klv->length) { | |
268 int tag = get_be16(pb); | |
269 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
270 | |
271 switch (tag) { | |
272 case 0x4403: | |
273 tracks_count = get_be32(pb); | |
274 if(tracks_count >= UINT_MAX / sizeof(*mxf->tracks) || | |
275 tracks_count >= UINT_MAX / sizeof(*mxf->descriptors)) | |
276 return -1; | |
277 mxf->tracks_count += tracks_count; /* op2a contains multiple source packages */ | |
278 mxf->tracks = av_realloc(mxf->tracks, mxf->tracks_count * sizeof(*mxf->tracks)); | |
279 mxf->descriptors = av_realloc(mxf->descriptors, mxf->tracks_count * sizeof(*mxf->descriptors)); | |
280 url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */ | |
281 for (i = mxf->tracks_count - tracks_count; i < mxf->tracks_count; i++) { | |
282 mxf->tracks[i].stream = av_new_stream(mxf->fc, 0); | |
283 get_buffer(pb, mxf->tracks[i].track_uid, 16); | |
284 } | |
285 break; | |
286 default: | |
287 url_fskip(pb, size); | |
288 } | |
289 bytes_read += size + 4; | |
290 } | |
291 return bytes_read; | |
292 } | |
293 | |
294 static int mxf_read_metadata_descriptor(MXFContext *mxf, KLVPacket *klv) | |
295 { | |
296 ByteIOContext *pb = &mxf->fc->pb; | |
297 MXFDescriptor *desc; | |
298 int bytes_read = 0; | |
299 | |
300 if (mxf->descriptors_count == mxf->tracks_count) | |
301 return -1; | |
302 desc = &mxf->descriptors[mxf->descriptors_count++]; | |
303 desc->kind = klv->key[14]; | |
304 desc->linked_track_id = -1; | |
305 | |
306 while (bytes_read < klv->length) { | |
307 int tag = get_be16(pb); | |
308 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
309 | |
310 switch (tag) { | |
311 case 0x3004: | |
312 get_buffer(pb, desc->essence_container, 16); | |
313 break; | |
314 case 0x3006: | |
315 desc->linked_track_id = get_be32(pb); | |
316 break; | |
317 case 0x3201: /* PictureEssenceCoding */ | |
318 desc->codec_type = CODEC_TYPE_VIDEO; | |
319 get_buffer(pb, desc->essence_compression, 16); | |
320 break; | |
321 case 0x3203: | |
322 desc->width = get_be32(pb); | |
323 break; | |
324 case 0x3202: | |
325 desc->height = get_be32(pb); | |
326 break; | |
327 case 0x320E: | |
328 desc->aspect_ratio.num = get_be32(pb); | |
329 desc->aspect_ratio.den = get_be32(pb); | |
330 break; | |
331 case 0x3D0A: | |
332 desc->block_align = get_be16(pb); | |
333 break; | |
334 case 0x3D03: | |
335 desc->sample_rate.num = get_be32(pb); | |
336 desc->sample_rate.den = get_be32(pb); | |
337 break; | |
338 case 0x3D06: /* SoundEssenceCompression */ | |
339 desc->codec_type = CODEC_TYPE_AUDIO; | |
340 get_buffer(pb, desc->essence_compression, 16); | |
341 break; | |
342 case 0x3D07: | |
343 desc->channels = get_be32(pb); | |
344 break; | |
345 case 0x3D01: | |
346 desc->bits_per_sample = get_be32(pb); | |
347 break; | |
348 default: | |
349 url_fskip(pb, size); | |
350 } | |
351 bytes_read += size + 4; | |
352 } | |
353 return bytes_read; | |
354 } | |
355 | |
356 /* SMPTE RP224 http://www.smpte-ra.org/mdd/index.html */ | |
357 static const CodecTag mxf_sound_essence_labels[] = { | |
358 { CODEC_ID_PCM_S16LE, 0x01000000 },/* Uncompressed Sound Coding */ | |
359 { CODEC_ID_PCM_S16LE, 0x017F0000 },/* Uncompressed Sound Coding */ | |
360 { CODEC_ID_PCM_S16BE, 0x017E0000 },/* Uncompressed Sound Coding Big Endian*/ | |
361 { CODEC_ID_PCM_ALAW, 0x02030101 }, | |
362 { CODEC_ID_AC3, 0x02030201 }, | |
363 //{ CODEC_ID_MP1, 0x02030104 }, | |
364 { CODEC_ID_MP2, 0x02030105 },/* MP2 or MP3 */ | |
365 //{ CODEC_ID_MP2, 0x02030106 },/* MPEG-2 Layer 1 */ | |
366 //{ CODEC_ID_???, 0x0203010C },/* Dolby E */ | |
367 //{ CODEC_ID_???, 0x02030301 },/* MPEG-2 AAC */ | |
368 { 0, 0 }, | |
369 }; | |
370 | |
371 static const CodecTag mxf_picture_essence_labels[] = { | |
372 { CODEC_ID_RAWVIDEO, 0x0100 }, | |
373 { CODEC_ID_MPEG2VIDEO, 0x0201 }, | |
374 { CODEC_ID_DVVIDEO, 0x0202 }, | |
375 //{ CODEC_ID_???, 0x0207 },/* D-11 HDCAM */ | |
376 { 0, 0 }, | |
377 }; | |
378 | |
379 static const CodecTag mxf_container_picture_labels[] = { | |
380 { CODEC_ID_MPEG2VIDEO, 0x0201 }, /* D-10 Mapping */ | |
381 { CODEC_ID_DVVIDEO, 0x0202 }, /* DV Mapping */ | |
382 //{ CODEC_ID_???, 0x0203 }, /* HDCAM D-11 Mapping */ | |
383 { CODEC_ID_MPEG2VIDEO, 0x0204 }, /* MPEG ES Mapping */ | |
384 }; | |
385 | |
386 static const CodecTag mxf_container_sound_labels[] = { | |
387 //{ CODEC_ID_PCM_S16??, 0x0201 }, /* D-10 Mapping */ | |
388 { CODEC_ID_MP2, 0x0204 }, /* MPEG ES Mapping */ | |
389 { CODEC_ID_PCM_S16LE, 0x0206 }, /* AES BWF Mapping */ | |
390 { CODEC_ID_PCM_ALAW, 0x020A }, | |
391 { 0, 0 }, | |
392 }; | |
393 | |
394 static void mxf_resolve_track_descriptor(MXFContext *mxf) | |
395 { | |
396 uint32_t container_label; | |
397 uint32_t essence_label; | |
398 int i, j; | |
399 | |
400 for (i = 0; i < mxf->descriptors_count; i++) { | |
401 for (j = 0; j < mxf->tracks_count; j++) { | |
402 AVStream *st = mxf->tracks[j].stream; | |
403 MXFDescriptor *desc = &mxf->descriptors[i]; | |
404 | |
405 if ((desc->linked_track_id == -1 && st->codec->codec_type == desc->codec_type) | |
406 || desc->linked_track_id == mxf->tracks[j].track_id) { | |
407 if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
408 st->codec->channels = desc->channels; | |
409 st->codec->bits_per_sample = desc->bits_per_sample; | |
410 st->codec->block_align = desc->block_align; | |
411 st->codec->sample_rate = desc->sample_rate.num / desc->sample_rate.den; | |
412 | |
413 container_label = BE_16(desc->essence_container + 12); | |
414 essence_label = BE_32(desc->essence_compression + 11); | |
415 st->codec->codec_id = codec_get_id(mxf_sound_essence_labels, essence_label); | |
416 if (st->codec->codec_id == CODEC_ID_PCM_S16LE) { | |
417 if (desc->bits_per_sample == 24) | |
418 st->codec->codec_id = CODEC_ID_PCM_S24LE; | |
419 else if (desc->bits_per_sample == 32) | |
420 st->codec->codec_id = CODEC_ID_PCM_S32LE; | |
421 } | |
422 if (st->codec->codec_id == CODEC_ID_PCM_S16BE) { | |
423 if (desc->bits_per_sample == 24) | |
424 st->codec->codec_id = CODEC_ID_PCM_S24BE; | |
425 else if (desc->bits_per_sample == 32) | |
426 st->codec->codec_id = CODEC_ID_PCM_S32BE; | |
427 } | |
428 if (!st->codec->codec_id) | |
429 st->codec->codec_id = codec_get_id(mxf_container_sound_labels, container_label); | |
430 | |
431 } else if (st->codec->codec_type == CODEC_TYPE_VIDEO) { | |
432 st->codec->width = desc->width; | |
433 st->codec->height = desc->height; | |
434 | |
435 container_label = BE_16(desc->essence_container + 12); | |
436 essence_label = BE_16(desc->essence_compression + 11); | |
437 st->codec->codec_id = codec_get_id(mxf_picture_essence_labels, essence_label); | |
438 if (!st->codec->codec_id) | |
439 st->codec->codec_id = codec_get_id(mxf_container_picture_labels, container_label); | |
440 } | |
441 } | |
442 } | |
443 } | |
444 } | |
445 | |
446 static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
447 { | |
448 MXFContext *mxf = s->priv_data; | |
449 KLVPacket klv; | |
450 int ret = 0; | |
451 | |
452 mxf->fc = s; | |
453 while (!url_feof(&s->pb)) { | |
454 if (klv_read_packet(&klv, &s->pb) < 0) | |
455 return -1; | |
456 if (IS_KLV_KEY(klv.key, mxf_metadata_track_key)) | |
457 ret = mxf_read_metadata_track(mxf, &klv); | |
458 else if (IS_KLV_KEY(klv.key, mxf_metadata_source_package_key)) | |
459 ret = mxf_read_metadata_source_package(mxf, &klv); | |
460 else if (IS_KLV_KEY(klv.key, mxf_metadata_sequence_key)) | |
461 ret = mxf_read_metadata_sequence(mxf, &klv); | |
462 else if (IS_KLV_KEY(klv.key, mxf_metadata_wave_descriptor_key)) | |
463 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
464 else if (IS_KLV_KEY(klv.key, mxf_metadata_mpegvideo_descriptor_key)) | |
465 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
466 else if (IS_KLV_KEY(klv.key, mxf_metadata_cdci_descriptor_key)) | |
467 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
468 else if (IS_KLV_KEY(klv.key, mxf_metadata_generic_sound_descriptor_key)) | |
469 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
470 else if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
471 /* FIXME avoid seek */ | |
472 url_fseek(&s->pb, klv.offset, SEEK_SET); | |
473 break; | |
474 } else | |
475 url_fskip(&s->pb, klv.length); | |
476 if (ret < 0) | |
477 return ret; | |
478 } | |
479 mxf_resolve_track_descriptor(mxf); | |
480 return 0; | |
481 } | |
482 | |
483 static int mxf_read_close(AVFormatContext *s) | |
484 { | |
485 MXFContext *mxf = s->priv_data; | |
486 | |
487 av_freep(&mxf->tracks); | |
488 av_freep(&mxf->descriptors); | |
489 return 0; | |
490 } | |
491 | |
492 static int mxf_probe(AVProbeData *p) { | |
493 /* KLV packet describing MXF header partition pack */ | |
494 if (p->buf_size < sizeof(mxf_header_partition_pack_key)) | |
495 return 0; | |
496 | |
497 if (IS_KLV_KEY(p->buf, mxf_header_partition_pack_key)) | |
498 return AVPROBE_SCORE_MAX; | |
499 else | |
500 return 0; | |
501 } | |
502 | |
503 | |
504 AVInputFormat mxf_demuxer = { | |
505 "mxf", | |
506 "MXF format", | |
507 sizeof(MXFContext), | |
508 mxf_probe, | |
509 mxf_read_header, | |
510 mxf_read_packet, | |
511 mxf_read_close, | |
512 NULL, | |
513 }; |