comparison mxfenc.c @ 4448:587ce9359a9b libavformat

write timecode track
author bcoudurier
date Wed, 11 Feb 2009 07:18:00 +0000
parents efe78f986bec
children aaae79b414f3
comparison
equal deleted inserted replaced
4447:1fb8c4a56366 4448:587ce9359a9b
61 typedef struct { 61 typedef struct {
62 AudioInterleaveContext aic; 62 AudioInterleaveContext aic;
63 UID track_essence_element_key; 63 UID track_essence_element_key;
64 int index; ///< index in mxf_essence_container_uls table 64 int index; ///< index in mxf_essence_container_uls table
65 const UID *codec_ul; 65 const UID *codec_ul;
66 int64_t duration;
67 int order; ///< interleaving order if dts are equal 66 int order; ///< interleaving order if dts are equal
68 int interlaced; ///< wether picture is interlaced 67 int interlaced; ///< wether picture is interlaced
69 int temporal_reordering; 68 int temporal_reordering;
70 } MXFStreamContext; 69 } MXFStreamContext;
71 70
122 int last_indexed_edit_unit; 121 int last_indexed_edit_unit;
123 uint64_t first_edit_unit_offset; 122 uint64_t first_edit_unit_offset;
124 uint64_t *body_partition_offset; 123 uint64_t *body_partition_offset;
125 unsigned body_partitions_count; 124 unsigned body_partitions_count;
126 int last_key_index; ///< index of last key frame 125 int last_key_index; ///< index of last key frame
126 uint64_t duration;
127 AVStream *timecode_track;
128 int timecode_base; ///< rounded time code base (25 or 30)
129 int timecode_start; ///< value from mpeg-2 essence gop header
130 int timecode_drop_frame; ///< time code use drop frame method frop mpeg-2 essence gop header
127 } MXFContext; 131 } MXFContext;
128 132
129 static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; 133 static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
130 static const uint8_t umid_base[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13,0x00,0x00,0x00 }; 134 static const uint8_t umid_base[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13,0x00,0x00,0x00 };
131 135
192 { 0x1001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x09,0x00,0x00}}, /* Structural Components reference array */ 196 { 0x1001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x09,0x00,0x00}}, /* Structural Components reference array */
193 // Source Clip 197 // Source Clip
194 { 0x1201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x04,0x00,0x00}}, /* Start position */ 198 { 0x1201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x04,0x00,0x00}}, /* Start position */
195 { 0x1101, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x01,0x00,0x00,0x00}}, /* SourcePackageID */ 199 { 0x1101, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x01,0x00,0x00,0x00}}, /* SourcePackageID */
196 { 0x1102, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x02,0x00,0x00,0x00}}, /* SourceTrackID */ 200 { 0x1102, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x02,0x00,0x00,0x00}}, /* SourceTrackID */
201 // Timecode Component
202 { 0x1501, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x05,0x00,0x00}}, /* Start Time Code */
203 { 0x1502, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x04,0x01,0x01,0x02,0x06,0x00,0x00}}, /* Rounded Time Code Base */
204 { 0x1503, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x04,0x01,0x01,0x05,0x00,0x00,0x00}}, /* Drop Frame */
197 // File Descriptor 205 // File Descriptor
198 { 0x3F01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x04,0x06,0x0B,0x00,0x00}}, /* Sub Descriptors reference array */ 206 { 0x3F01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x04,0x06,0x0B,0x00,0x00}}, /* Sub Descriptors reference array */
199 { 0x3006, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x06,0x01,0x01,0x03,0x05,0x00,0x00,0x00}}, /* Linked Track ID */ 207 { 0x3006, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x06,0x01,0x01,0x03,0x05,0x00,0x00,0x00}}, /* Linked Track ID */
200 { 0x3001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x00,0x00,0x00,0x00}}, /* SampleRate */ 208 { 0x3001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x00,0x00,0x00,0x00}}, /* SampleRate */
201 { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* Essence Container */ 209 { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* Essence Container */
520 // write sequence refs 528 // write sequence refs
521 mxf_write_local_tag(pb, 16, 0x4803); 529 mxf_write_local_tag(pb, 16, 0x4803);
522 mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); 530 mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index);
523 } 531 }
524 532
525 static void mxf_write_common_fields(ByteIOContext *pb, AVStream *st) 533 static const uint8_t smpte_12m_timecode_track_data_ul[] = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x01,0x01,0x00,0x00,0x00 };
526 { 534
527 const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type); 535 static void mxf_write_common_fields(AVFormatContext *s, AVStream *st)
528 MXFStreamContext *sc = st->priv_data; 536 {
537 MXFContext *mxf = s->priv_data;
538 ByteIOContext *pb = s->pb;
529 539
530 // find data define uls 540 // find data define uls
531 mxf_write_local_tag(pb, 16, 0x0201); 541 mxf_write_local_tag(pb, 16, 0x0201);
532 put_buffer(pb, data_def_ul->uid, 16); 542 if (st == mxf->timecode_track)
543 put_buffer(pb, smpte_12m_timecode_track_data_ul, 16);
544 else {
545 const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
546 put_buffer(pb, data_def_ul->uid, 16);
547 }
533 548
534 // write duration 549 // write duration
535 mxf_write_local_tag(pb, 8, 0x0202); 550 mxf_write_local_tag(pb, 8, 0x0202);
536 put_be64(pb, sc->duration); 551 put_be64(pb, mxf->duration);
537 } 552 }
538 553
539 static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) 554 static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
540 { 555 {
541 ByteIOContext *pb = s->pb; 556 MXFContext *mxf = s->priv_data;
557 ByteIOContext *pb = s->pb;
558 enum MXFMetadataSetType component;
542 559
543 mxf_write_metadata_key(pb, 0x010f00); 560 mxf_write_metadata_key(pb, 0x010f00);
544 PRINT_KEY(s, "sequence key", pb->buf_ptr - 16); 561 PRINT_KEY(s, "sequence key", pb->buf_ptr - 16);
545 klv_encode_ber_length(pb, 80); 562 klv_encode_ber_length(pb, 80);
546 563
547 mxf_write_local_tag(pb, 16, 0x3C0A); 564 mxf_write_local_tag(pb, 16, 0x3C0A);
548 mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); 565 mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index);
549 566
550 PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16); 567 PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
551 mxf_write_common_fields(pb, st); 568 mxf_write_common_fields(s, st);
552 569
553 // write structural component 570 // write structural component
554 mxf_write_local_tag(pb, 16 + 8, 0x1001); 571 mxf_write_local_tag(pb, 16 + 8, 0x1001);
555 mxf_write_refs_count(pb, 1); 572 mxf_write_refs_count(pb, 1);
556 mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index); 573 if (st == mxf->timecode_track)
574 component = TimecodeComponent;
575 else if (type == MaterialPackage)
576 component = SourceClip;
577 else
578 component = SourceClip+TypeBottom;
579 mxf_write_uuid(pb, component, st->index);
580 }
581
582 static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st)
583 {
584 MXFContext *mxf = s->priv_data;
585 ByteIOContext *pb = s->pb;
586
587 mxf_write_metadata_key(pb, 0x011400);
588 klv_encode_ber_length(pb, 75);
589
590 // UID
591 mxf_write_local_tag(pb, 16, 0x3C0A);
592 mxf_write_uuid(pb, TimecodeComponent, st->index);
593
594 mxf_write_common_fields(s, st);
595
596 // Start Time Code
597 mxf_write_local_tag(pb, 8, 0x1501);
598 put_be64(pb, mxf->timecode_start);
599
600 // Rounded Time Code Base
601 mxf_write_local_tag(pb, 2, 0x1502);
602 put_be16(pb, mxf->timecode_base);
603
604 // Drop Frame
605 mxf_write_local_tag(pb, 1, 0x1503);
606 put_byte(pb, mxf->timecode_drop_frame);
557 } 607 }
558 608
559 static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) 609 static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type)
560 { 610 {
561 ByteIOContext *pb = s->pb; 611 ByteIOContext *pb = s->pb;
568 // write uid 618 // write uid
569 mxf_write_local_tag(pb, 16, 0x3C0A); 619 mxf_write_local_tag(pb, 16, 0x3C0A);
570 mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index); 620 mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index);
571 621
572 PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16); 622 PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
573 mxf_write_common_fields(pb, st); 623 mxf_write_common_fields(s, st);
574 624
575 // write start_position 625 // write start_position
576 mxf_write_local_tag(pb, 8, 0x1201); 626 mxf_write_local_tag(pb, 8, 0x1201);
577 put_be64(pb, 0); 627 put_be64(pb, 0);
578 628
771 821
772 static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type) 822 static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type)
773 { 823 {
774 MXFContext *mxf = s->priv_data; 824 MXFContext *mxf = s->priv_data;
775 ByteIOContext *pb = s->pb; 825 ByteIOContext *pb = s->pb;
776 int i; 826 int i, track_count;
777 827
778 if (type == MaterialPackage) { 828 if (type == MaterialPackage) {
829 track_count = s->nb_streams + 1; // add timecode track
779 mxf_write_metadata_key(pb, 0x013600); 830 mxf_write_metadata_key(pb, 0x013600);
780 PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16); 831 PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
781 klv_encode_ber_length(pb, 92 + 16 * s->nb_streams); 832 klv_encode_ber_length(pb, 92 + 16*track_count);
782 } else { 833 } else {
834 track_count = s->nb_streams;
783 mxf_write_metadata_key(pb, 0x013700); 835 mxf_write_metadata_key(pb, 0x013700);
784 PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16); 836 PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
785 klv_encode_ber_length(pb, 112 + 16 * s->nb_streams); // 20 bytes length for descriptor reference 837 klv_encode_ber_length(pb, 112 + 16*track_count); // 20 bytes length for descriptor reference
786 } 838 }
787 839
788 // write uid 840 // write uid
789 mxf_write_local_tag(pb, 16, 0x3C0A); 841 mxf_write_local_tag(pb, 16, 0x3C0A);
790 mxf_write_uuid(pb, type, 0); 842 mxf_write_uuid(pb, type, 0);
803 // package modified date 855 // package modified date
804 mxf_write_local_tag(pb, 8, 0x4404); 856 mxf_write_local_tag(pb, 8, 0x4404);
805 put_be64(pb, mxf->timestamp); 857 put_be64(pb, mxf->timestamp);
806 858
807 // write track refs 859 // write track refs
808 mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x4403); 860 mxf_write_local_tag(pb, track_count*16 + 8, 0x4403);
809 mxf_write_refs_count(pb, s->nb_streams); 861 mxf_write_refs_count(pb, track_count);
810 for (i = 0; i < s->nb_streams; i++) 862 for (i = 0; i < s->nb_streams; i++)
811 mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, i); 863 mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, i);
864 if (type == MaterialPackage)
865 mxf_write_uuid(pb, Track, s->nb_streams); // timecode track
812 866
813 // write multiple descriptor reference 867 // write multiple descriptor reference
814 if (type == SourcePackage) { 868 if (type == SourcePackage) {
815 mxf_write_local_tag(pb, 16, 0x4701); 869 mxf_write_local_tag(pb, 16, 0x4701);
816 if (s->nb_streams > 1) { 870 if (s->nb_streams > 1) {
817 mxf_write_uuid(pb, MultipleDescriptor, 0); 871 mxf_write_uuid(pb, MultipleDescriptor, 0);
818 mxf_write_multi_descriptor(s); 872 mxf_write_multi_descriptor(s);
819 } else 873 } else
820 mxf_write_uuid(pb, SubDescriptor, 0); 874 mxf_write_uuid(pb, SubDescriptor, 0);
875 } else {
876 // write timecode track
877 mxf_write_track(s, mxf->timecode_track, type);
878 mxf_write_sequence(s, mxf->timecode_track, type);
879 mxf_write_timecode_component(s, mxf->timecode_track);
821 } 880 }
822 881
823 for (i = 0; i < s->nb_streams; i++) { 882 for (i = 0; i < s->nb_streams; i++) {
824 AVStream *st = s->streams[i]; 883 AVStream *st = s->streams[i];
825 mxf_write_track(s, st, type); 884 mxf_write_track(s, st, type);
1218 return -1; 1277 return -1;
1219 } 1278 }
1220 if (fabs(av_q2d(st->codec->time_base) - 1/25.0) < 0.0001) { 1279 if (fabs(av_q2d(st->codec->time_base) - 1/25.0) < 0.0001) {
1221 samples_per_frame = PAL_samples_per_frame; 1280 samples_per_frame = PAL_samples_per_frame;
1222 mxf->time_base = (AVRational){ 1, 25 }; 1281 mxf->time_base = (AVRational){ 1, 25 };
1282 mxf->timecode_base = 25;
1223 } else if (fabs(av_q2d(st->codec->time_base) - 1001/30000.0) < 0.0001) { 1283 } else if (fabs(av_q2d(st->codec->time_base) - 1001/30000.0) < 0.0001) {
1224 samples_per_frame = NTSC_samples_per_frame; 1284 samples_per_frame = NTSC_samples_per_frame;
1225 mxf->time_base = (AVRational){ 1001, 30000 }; 1285 mxf->time_base = (AVRational){ 1001, 30000 };
1286 mxf->timecode_base = 30;
1226 } else { 1287 } else {
1227 av_log(s, AV_LOG_ERROR, "unsupported video frame rate\n"); 1288 av_log(s, AV_LOG_ERROR, "unsupported video frame rate\n");
1228 return -1; 1289 return -1;
1229 } 1290 }
1230 av_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den); 1291 av_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
1234 return -1; 1295 return -1;
1235 } 1296 }
1236 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 1297 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
1237 mxf->slice_count = 1; 1298 mxf->slice_count = 1;
1238 } 1299 }
1239 sc->duration = -1;
1240 1300
1241 sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id); 1301 sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id);
1242 if (sc->index == -1) { 1302 if (sc->index == -1) {
1243 av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, " 1303 av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, "
1244 "codec not currently supported in container\n", i); 1304 "codec not currently supported in container\n", i);
1263 sc->track_essence_element_key[13] = present[sc->index]; 1323 sc->track_essence_element_key[13] = present[sc->index];
1264 sc->order = AV_RB32(sc->track_essence_element_key+12); 1324 sc->order = AV_RB32(sc->track_essence_element_key+12);
1265 } 1325 }
1266 1326
1267 mxf->timestamp = mxf_parse_timestamp(s->timestamp); 1327 mxf->timestamp = mxf_parse_timestamp(s->timestamp);
1328 mxf->duration = -1;
1329
1330 mxf->timecode_track = av_mallocz(sizeof(*mxf->timecode_track));
1331 if (!mxf->timecode_track)
1332 return AVERROR(ENOMEM);
1333 mxf->timecode_track->priv_data = av_mallocz(sizeof(MXFStreamContext));
1334 if (!mxf->timecode_track->priv_data)
1335 return AVERROR(ENOMEM);
1336 mxf->timecode_track->index = s->nb_streams;
1268 1337
1269 if (!samples_per_frame) 1338 if (!samples_per_frame)
1270 samples_per_frame = PAL_samples_per_frame; 1339 samples_per_frame = PAL_samples_per_frame;
1271 1340
1272 if (ff_audio_interleave_init(s, samples_per_frame, mxf->time_base) < 0) 1341 if (ff_audio_interleave_init(s, samples_per_frame, mxf->time_base) < 0)
1298 1367
1299 static void mxf_write_system_item(AVFormatContext *s) 1368 static void mxf_write_system_item(AVFormatContext *s)
1300 { 1369 {
1301 MXFContext *mxf = s->priv_data; 1370 MXFContext *mxf = s->priv_data;
1302 ByteIOContext *pb = s->pb; 1371 ByteIOContext *pb = s->pb;
1303 unsigned fps, frame; 1372 unsigned frame;
1304 uint32_t time_code; 1373 uint32_t time_code;
1305 1374
1306 frame = mxf->last_indexed_edit_unit + mxf->edit_units_count; 1375 frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
1307 1376
1308 // write system metadata pack 1377 // write system metadata pack
1319 put_buffer(pb, mxf_essence_container_uls[mxf->essence_containers_indices[0]].container_ul, 16); 1388 put_buffer(pb, mxf_essence_container_uls[mxf->essence_containers_indices[0]].container_ul, 16);
1320 put_byte(pb, 0); 1389 put_byte(pb, 0);
1321 put_be64(pb, 0); 1390 put_be64(pb, 0);
1322 put_be64(pb, 0); // creation date/time stamp 1391 put_be64(pb, 0); // creation date/time stamp
1323 1392
1324 // XXX drop frame
1325 if (mxf->time_base.den == 30000) fps = 30;
1326 else fps = 25;
1327
1328 put_byte(pb, 0x81); // SMPTE 12M time code 1393 put_byte(pb, 0x81); // SMPTE 12M time code
1329 time_code = ff_framenum_to_12m_time_code(frame, 0, fps); 1394 time_code = ff_framenum_to_12m_time_code(frame, mxf->timecode_drop_frame, mxf->timecode_base);
1330 put_be32(pb, time_code); 1395 put_be32(pb, time_code);
1331 put_be32(pb, 0); // binary group data 1396 put_be32(pb, 0); // binary group data
1332 put_be64(pb, 0); 1397 put_be64(pb, 0);
1333 1398
1334 // write system metadata package set 1399 // write system metadata package set
1394 mxf_write_klv_fill(s); 1459 mxf_write_klv_fill(s);
1395 put_buffer(pb, sc->track_essence_element_key, 16); // write key 1460 put_buffer(pb, sc->track_essence_element_key, 16); // write key
1396 klv_encode_ber_length(pb, pkt->size); // write length 1461 klv_encode_ber_length(pb, pkt->size); // write length
1397 put_buffer(pb, pkt->data, pkt->size); // write value 1462 put_buffer(pb, pkt->data, pkt->size); // write value
1398 1463
1399 sc->duration = FFMAX(pkt->pts + pkt->duration, sc->duration);
1400
1401 put_flush_packet(pb); 1464 put_flush_packet(pb);
1402 return 0; 1465 return 0;
1403 } 1466 }
1404 1467
1405 static void mxf_write_random_index_pack(AVFormatContext *s) 1468 static void mxf_write_random_index_pack(AVFormatContext *s)
1429 static int mxf_write_footer(AVFormatContext *s) 1492 static int mxf_write_footer(AVFormatContext *s)
1430 { 1493 {
1431 MXFContext *mxf = s->priv_data; 1494 MXFContext *mxf = s->priv_data;
1432 ByteIOContext *pb = s->pb; 1495 ByteIOContext *pb = s->pb;
1433 1496
1497 mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count;
1498
1434 mxf_write_klv_fill(s); 1499 mxf_write_klv_fill(s);
1435 mxf->footer_partition_offset = url_ftell(pb); 1500 mxf->footer_partition_offset = url_ftell(pb);
1436 mxf_write_partition(s, 0, 2, footer_partition_key, 0); 1501 mxf_write_partition(s, 0, 2, footer_partition_key, 0);
1437 1502
1438 mxf_write_klv_fill(s); 1503 mxf_write_klv_fill(s);
1448 1513
1449 ff_audio_interleave_close(s); 1514 ff_audio_interleave_close(s);
1450 1515
1451 av_freep(&mxf->index_entries); 1516 av_freep(&mxf->index_entries);
1452 av_freep(&mxf->body_partition_offset); 1517 av_freep(&mxf->body_partition_offset);
1518 av_freep(&mxf->timecode_track->priv_data);
1519 av_freep(&mxf->timecode_track);
1453 1520
1454 mxf_free(s); 1521 mxf_free(s);
1455 return 0; 1522 return 0;
1456 } 1523 }
1457 1524