Mercurial > libavformat.hg
annotate mxf.c @ 1188:19f761156b1f libavformat
Set duration to AV_NOPTS_VALUE instead of 0 when unknown.
Set start_time to 0 when duration is known to indicate we have
valid timestamps for this track.
author | reimar |
---|---|
date | Fri, 28 Jul 2006 13:31:08 +0000 |
parents | fbdd53c2a12d |
children | fb1a9ccffe89 |
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 | |
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]; | |
1188
19f761156b1f
Set duration to AV_NOPTS_VALUE instead of 0 when unknown.
reimar
parents:
1186
diff
changeset
|
218 uint64_t duration = AV_NOPTS_VALUE; |
1186 | 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)) { | |
1188
19f761156b1f
Set duration to AV_NOPTS_VALUE instead of 0 when unknown.
reimar
parents:
1186
diff
changeset
|
244 mxf->tracks[i].stream->start_time = 0; |
1186 | 245 mxf->tracks[i].stream->duration = duration; |
246 if (data_definition[11] == 0x02 && data_definition[12] == 0x01) | |
247 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_VIDEO; | |
248 else if (data_definition[11] == 0x02 && data_definition[12] == 0x02) | |
249 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_AUDIO; | |
250 else if (data_definition[11] == 0x01) /* SMPTE 12M Time Code track */ | |
251 mxf->tracks[i].stream->codec->codec_type = CODEC_TYPE_DATA; | |
252 } | |
253 return bytes_read; | |
254 } | |
255 | |
256 static int mxf_read_metadata_source_package(MXFContext *mxf, KLVPacket *klv) | |
257 { | |
258 ByteIOContext *pb = &mxf->fc->pb; | |
259 int tracks_count; | |
260 int bytes_read = 0; | |
261 int i; | |
262 | |
263 while (bytes_read < klv->length) { | |
264 int tag = get_be16(pb); | |
265 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
266 | |
267 switch (tag) { | |
268 case 0x4403: | |
269 tracks_count = get_be32(pb); | |
270 if(tracks_count >= UINT_MAX / sizeof(*mxf->tracks) || | |
271 tracks_count >= UINT_MAX / sizeof(*mxf->descriptors)) | |
272 return -1; | |
273 mxf->tracks_count += tracks_count; /* op2a contains multiple source packages */ | |
274 mxf->tracks = av_realloc(mxf->tracks, mxf->tracks_count * sizeof(*mxf->tracks)); | |
275 mxf->descriptors = av_realloc(mxf->descriptors, mxf->tracks_count * sizeof(*mxf->descriptors)); | |
276 url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */ | |
277 for (i = mxf->tracks_count - tracks_count; i < mxf->tracks_count; i++) { | |
278 mxf->tracks[i].stream = av_new_stream(mxf->fc, 0); | |
279 get_buffer(pb, mxf->tracks[i].track_uid, 16); | |
280 } | |
281 break; | |
282 default: | |
283 url_fskip(pb, size); | |
284 } | |
285 bytes_read += size + 4; | |
286 } | |
287 return bytes_read; | |
288 } | |
289 | |
290 static int mxf_read_metadata_descriptor(MXFContext *mxf, KLVPacket *klv) | |
291 { | |
292 ByteIOContext *pb = &mxf->fc->pb; | |
293 MXFDescriptor *desc; | |
294 int bytes_read = 0; | |
295 | |
296 if (mxf->descriptors_count == mxf->tracks_count) | |
297 return -1; | |
298 desc = &mxf->descriptors[mxf->descriptors_count++]; | |
299 desc->kind = klv->key[14]; | |
300 desc->linked_track_id = -1; | |
301 | |
302 while (bytes_read < klv->length) { | |
303 int tag = get_be16(pb); | |
304 int size = get_be16(pb); /* KLV specified by 0x53 */ | |
305 | |
306 switch (tag) { | |
307 case 0x3004: | |
308 get_buffer(pb, desc->essence_container, 16); | |
309 break; | |
310 case 0x3006: | |
311 desc->linked_track_id = get_be32(pb); | |
312 break; | |
313 case 0x3201: /* PictureEssenceCoding */ | |
314 desc->codec_type = CODEC_TYPE_VIDEO; | |
315 get_buffer(pb, desc->essence_compression, 16); | |
316 break; | |
317 case 0x3203: | |
318 desc->width = get_be32(pb); | |
319 break; | |
320 case 0x3202: | |
321 desc->height = get_be32(pb); | |
322 break; | |
323 case 0x320E: | |
324 desc->aspect_ratio.num = get_be32(pb); | |
325 desc->aspect_ratio.den = get_be32(pb); | |
326 break; | |
327 case 0x3D0A: | |
328 desc->block_align = get_be16(pb); | |
329 break; | |
330 case 0x3D03: | |
331 desc->sample_rate.num = get_be32(pb); | |
332 desc->sample_rate.den = get_be32(pb); | |
333 break; | |
334 case 0x3D06: /* SoundEssenceCompression */ | |
335 desc->codec_type = CODEC_TYPE_AUDIO; | |
336 get_buffer(pb, desc->essence_compression, 16); | |
337 break; | |
338 case 0x3D07: | |
339 desc->channels = get_be32(pb); | |
340 break; | |
341 case 0x3D01: | |
342 desc->bits_per_sample = get_be32(pb); | |
343 break; | |
344 default: | |
345 url_fskip(pb, size); | |
346 } | |
347 bytes_read += size + 4; | |
348 } | |
349 return bytes_read; | |
350 } | |
351 | |
352 /* SMPTE RP224 http://www.smpte-ra.org/mdd/index.html */ | |
353 static const CodecTag mxf_sound_essence_labels[] = { | |
354 { CODEC_ID_PCM_S16LE, 0x01000000 },/* Uncompressed Sound Coding */ | |
355 { CODEC_ID_PCM_S16LE, 0x017F0000 },/* Uncompressed Sound Coding */ | |
356 { CODEC_ID_PCM_S16BE, 0x017E0000 },/* Uncompressed Sound Coding Big Endian*/ | |
357 { CODEC_ID_PCM_ALAW, 0x02030101 }, | |
358 { CODEC_ID_AC3, 0x02030201 }, | |
359 //{ CODEC_ID_MP1, 0x02030104 }, | |
360 { CODEC_ID_MP2, 0x02030105 },/* MP2 or MP3 */ | |
361 //{ CODEC_ID_MP2, 0x02030106 },/* MPEG-2 Layer 1 */ | |
362 //{ CODEC_ID_???, 0x0203010C },/* Dolby E */ | |
363 //{ CODEC_ID_???, 0x02030301 },/* MPEG-2 AAC */ | |
364 { 0, 0 }, | |
365 }; | |
366 | |
367 static const CodecTag mxf_picture_essence_labels[] = { | |
368 { CODEC_ID_RAWVIDEO, 0x0100 }, | |
369 { CODEC_ID_MPEG2VIDEO, 0x0201 }, | |
370 { CODEC_ID_DVVIDEO, 0x0202 }, | |
371 //{ CODEC_ID_???, 0x0207 },/* D-11 HDCAM */ | |
372 { 0, 0 }, | |
373 }; | |
374 | |
375 static const CodecTag mxf_container_picture_labels[] = { | |
376 { CODEC_ID_MPEG2VIDEO, 0x0201 }, /* D-10 Mapping */ | |
377 { CODEC_ID_DVVIDEO, 0x0202 }, /* DV Mapping */ | |
378 //{ CODEC_ID_???, 0x0203 }, /* HDCAM D-11 Mapping */ | |
379 { CODEC_ID_MPEG2VIDEO, 0x0204 }, /* MPEG ES Mapping */ | |
380 }; | |
381 | |
382 static const CodecTag mxf_container_sound_labels[] = { | |
383 //{ CODEC_ID_PCM_S16??, 0x0201 }, /* D-10 Mapping */ | |
384 { CODEC_ID_MP2, 0x0204 }, /* MPEG ES Mapping */ | |
385 { CODEC_ID_PCM_S16LE, 0x0206 }, /* AES BWF Mapping */ | |
386 { CODEC_ID_PCM_ALAW, 0x020A }, | |
387 { 0, 0 }, | |
388 }; | |
389 | |
390 static void mxf_resolve_track_descriptor(MXFContext *mxf) | |
391 { | |
392 uint32_t container_label; | |
393 uint32_t essence_label; | |
394 int i, j; | |
395 | |
396 for (i = 0; i < mxf->descriptors_count; i++) { | |
397 for (j = 0; j < mxf->tracks_count; j++) { | |
398 AVStream *st = mxf->tracks[j].stream; | |
399 MXFDescriptor *desc = &mxf->descriptors[i]; | |
400 | |
401 if ((desc->linked_track_id == -1 && st->codec->codec_type == desc->codec_type) | |
402 || desc->linked_track_id == mxf->tracks[j].track_id) { | |
403 if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
404 st->codec->channels = desc->channels; | |
405 st->codec->bits_per_sample = desc->bits_per_sample; | |
406 st->codec->block_align = desc->block_align; | |
407 st->codec->sample_rate = desc->sample_rate.num / desc->sample_rate.den; | |
408 | |
409 container_label = BE_16(desc->essence_container + 12); | |
410 essence_label = BE_32(desc->essence_compression + 11); | |
411 st->codec->codec_id = codec_get_id(mxf_sound_essence_labels, essence_label); | |
412 if (st->codec->codec_id == CODEC_ID_PCM_S16LE) { | |
413 if (desc->bits_per_sample == 24) | |
414 st->codec->codec_id = CODEC_ID_PCM_S24LE; | |
415 else if (desc->bits_per_sample == 32) | |
416 st->codec->codec_id = CODEC_ID_PCM_S32LE; | |
417 } | |
418 if (st->codec->codec_id == CODEC_ID_PCM_S16BE) { | |
419 if (desc->bits_per_sample == 24) | |
420 st->codec->codec_id = CODEC_ID_PCM_S24BE; | |
421 else if (desc->bits_per_sample == 32) | |
422 st->codec->codec_id = CODEC_ID_PCM_S32BE; | |
423 } | |
424 if (!st->codec->codec_id) | |
425 st->codec->codec_id = codec_get_id(mxf_container_sound_labels, container_label); | |
426 | |
427 } else if (st->codec->codec_type == CODEC_TYPE_VIDEO) { | |
428 st->codec->width = desc->width; | |
429 st->codec->height = desc->height; | |
430 | |
431 container_label = BE_16(desc->essence_container + 12); | |
432 essence_label = BE_16(desc->essence_compression + 11); | |
433 st->codec->codec_id = codec_get_id(mxf_picture_essence_labels, essence_label); | |
434 if (!st->codec->codec_id) | |
435 st->codec->codec_id = codec_get_id(mxf_container_picture_labels, container_label); | |
436 } | |
437 } | |
438 } | |
439 } | |
440 } | |
441 | |
442 static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
443 { | |
444 MXFContext *mxf = s->priv_data; | |
445 KLVPacket klv; | |
446 int ret = 0; | |
447 | |
448 mxf->fc = s; | |
449 while (!url_feof(&s->pb)) { | |
450 if (klv_read_packet(&klv, &s->pb) < 0) | |
451 return -1; | |
452 if (IS_KLV_KEY(klv.key, mxf_metadata_track_key)) | |
453 ret = mxf_read_metadata_track(mxf, &klv); | |
454 else if (IS_KLV_KEY(klv.key, mxf_metadata_source_package_key)) | |
455 ret = mxf_read_metadata_source_package(mxf, &klv); | |
456 else if (IS_KLV_KEY(klv.key, mxf_metadata_sequence_key)) | |
457 ret = mxf_read_metadata_sequence(mxf, &klv); | |
458 else if (IS_KLV_KEY(klv.key, mxf_metadata_wave_descriptor_key)) | |
459 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
460 else if (IS_KLV_KEY(klv.key, mxf_metadata_mpegvideo_descriptor_key)) | |
461 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
462 else if (IS_KLV_KEY(klv.key, mxf_metadata_cdci_descriptor_key)) | |
463 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
464 else if (IS_KLV_KEY(klv.key, mxf_metadata_generic_sound_descriptor_key)) | |
465 ret = mxf_read_metadata_descriptor(mxf, &klv); | |
466 else if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
467 /* FIXME avoid seek */ | |
468 url_fseek(&s->pb, klv.offset, SEEK_SET); | |
469 break; | |
470 } else | |
471 url_fskip(&s->pb, klv.length); | |
472 if (ret < 0) | |
473 return ret; | |
474 } | |
475 mxf_resolve_track_descriptor(mxf); | |
476 return 0; | |
477 } | |
478 | |
479 static int mxf_read_close(AVFormatContext *s) | |
480 { | |
481 MXFContext *mxf = s->priv_data; | |
482 | |
483 av_freep(&mxf->tracks); | |
484 av_freep(&mxf->descriptors); | |
485 return 0; | |
486 } | |
487 | |
488 static int mxf_probe(AVProbeData *p) { | |
489 /* KLV packet describing MXF header partition pack */ | |
490 if (p->buf_size < sizeof(mxf_header_partition_pack_key)) | |
491 return 0; | |
492 | |
493 if (IS_KLV_KEY(p->buf, mxf_header_partition_pack_key)) | |
494 return AVPROBE_SCORE_MAX; | |
495 else | |
496 return 0; | |
497 } | |
498 | |
499 | |
500 AVInputFormat mxf_demuxer = { | |
501 "mxf", | |
502 "MXF format", | |
503 sizeof(MXFContext), | |
504 mxf_probe, | |
505 mxf_read_header, | |
506 mxf_read_packet, | |
507 mxf_read_close, | |
508 NULL, | |
509 }; |