Mercurial > libavformat.hg
comparison mxfenc.c @ 4440:64f62c9643c3 libavformat
write body partitions
author | bcoudurier |
---|---|
date | Tue, 10 Feb 2009 09:02:29 +0000 |
parents | 4bc3b8687ec2 |
children | 0fd16041ac29 |
comparison
equal
deleted
inserted
replaced
4439:4bc3b8687ec2 | 4440:64f62c9643c3 |
---|---|
42 #include "mxf.h" | 42 #include "mxf.h" |
43 | 43 |
44 static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 }; | 44 static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 }; |
45 static const int PAL_samples_per_frame[] = { 1920, 0 }; | 45 static const int PAL_samples_per_frame[] = { 1920, 0 }; |
46 | 46 |
47 #define MXF_INDEX_CLUSTER_SIZE 4096 | 47 #define EDIT_UNITS_PER_BODY 250 |
48 #define KAG_SIZE 512 | 48 #define KAG_SIZE 512 |
49 | 49 |
50 typedef struct { | 50 typedef struct { |
51 int local_tag; | 51 int local_tag; |
52 UID uid; | 52 UID uid; |
117 int header_written; | 117 int header_written; |
118 MXFIndexEntry *index_entries; | 118 MXFIndexEntry *index_entries; |
119 unsigned edit_units_count; | 119 unsigned edit_units_count; |
120 uint64_t timestamp; ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8) | 120 uint64_t timestamp; ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8) |
121 uint8_t slice_count; ///< index slice count minus 1 (1 if no audio, 0 otherwise) | 121 uint8_t slice_count; ///< index slice count minus 1 (1 if no audio, 0 otherwise) |
122 int last_indexed_edit_unit; | |
123 uint64_t first_edit_unit_offset; | |
124 uint64_t *body_partition_offset; | |
125 unsigned body_partitions_count; | |
126 int last_key_index; ///< index of last key frame | |
127 uint64_t body_offset; | |
122 } MXFContext; | 128 } MXFContext; |
123 | 129 |
124 static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; | 130 static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; |
125 static const uint8_t umid_base[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13,0x00,0x00,0x00 }; | 131 static const uint8_t umid_base[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13,0x00,0x00,0x00 }; |
126 | 132 |
133 static const uint8_t index_table_segment_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }; | 139 static const uint8_t index_table_segment_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }; |
134 static const uint8_t random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; | 140 static const uint8_t random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; |
135 static const uint8_t header_open_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }; // OpenIncomplete | 141 static const uint8_t header_open_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }; // OpenIncomplete |
136 static const uint8_t header_closed_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }; // ClosedComplete | 142 static const uint8_t header_closed_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }; // ClosedComplete |
137 static const uint8_t klv_fill_key[] = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 }; | 143 static const uint8_t klv_fill_key[] = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 }; |
144 static const uint8_t body_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }; // ClosedComplete | |
138 | 145 |
139 /** | 146 /** |
140 * partial key for header metadata | 147 * partial key for header metadata |
141 */ | 148 */ |
142 static const uint8_t header_metadata_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01 }; | 149 static const uint8_t header_metadata_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01 }; |
873 { | 880 { |
874 MXFContext *mxf = s->priv_data; | 881 MXFContext *mxf = s->priv_data; |
875 ByteIOContext *pb = s->pb; | 882 ByteIOContext *pb = s->pb; |
876 int i, j; | 883 int i, j; |
877 int temporal_reordering = 0; | 884 int temporal_reordering = 0; |
878 int last_key_index = 0, key_index = 0; | 885 int key_index = 0; |
879 | 886 |
880 av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count); | 887 av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count); |
888 | |
889 if (!mxf->edit_units_count) | |
890 return; | |
881 | 891 |
882 put_buffer(pb, index_table_segment_key, 16); | 892 put_buffer(pb, index_table_segment_key, 16); |
883 klv_encode_ber_length(pb, 109 + (s->nb_streams+1)*6 + | 893 klv_encode_ber_length(pb, 109 + (s->nb_streams+1)*6 + |
884 mxf->edit_units_count*(11+mxf->slice_count*4)); | 894 mxf->edit_units_count*(11+mxf->slice_count*4)); |
885 | 895 |
892 put_be32(pb, mxf->time_base.num); | 902 put_be32(pb, mxf->time_base.num); |
893 put_be32(pb, mxf->time_base.den); | 903 put_be32(pb, mxf->time_base.den); |
894 | 904 |
895 // index start position | 905 // index start position |
896 mxf_write_local_tag(pb, 8, 0x3F0C); | 906 mxf_write_local_tag(pb, 8, 0x3F0C); |
897 put_be64(pb, 0); | 907 put_be64(pb, mxf->last_indexed_edit_unit); |
898 | 908 |
899 // index duration | 909 // index duration |
900 mxf_write_local_tag(pb, 8, 0x3F0D); | 910 mxf_write_local_tag(pb, 8, 0x3F0D); |
901 put_be64(pb, mxf->edit_units_count); | 911 put_be64(pb, mxf->edit_units_count); |
902 | 912 |
963 } | 973 } |
964 put_byte(pb, temporal_offset); | 974 put_byte(pb, temporal_offset); |
965 } else | 975 } else |
966 put_byte(pb, 0); | 976 put_byte(pb, 0); |
967 if (!(mxf->index_entries[i].flags & 0x33)) { // I frame | 977 if (!(mxf->index_entries[i].flags & 0x33)) { // I frame |
968 last_key_index = key_index; | 978 mxf->last_key_index = key_index; |
969 key_index = i; | 979 key_index = i; |
970 } | 980 } |
971 if (mxf->index_entries[i].flags & 0x10 && // backward prediction | 981 if (mxf->index_entries[i].flags & 0x10 && // backward prediction |
972 !(mxf->index_entries[key_index].flags & 0x80)) { // open gop | 982 !(mxf->index_entries[key_index].flags & 0x80)) { // open gop |
973 put_byte(pb, last_key_index - i); | 983 put_byte(pb, mxf->last_key_index - i); |
974 } else { | 984 } else { |
975 put_byte(pb, key_index - i); // key frame offset | 985 put_byte(pb, key_index - i); // key frame offset |
976 if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward | 986 if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward |
977 last_key_index = key_index; | 987 mxf->last_key_index = key_index; |
978 } | 988 } |
979 put_byte(pb, mxf->index_entries[i].flags); | 989 put_byte(pb, mxf->index_entries[i].flags); |
980 // stream offset | 990 // stream offset |
981 put_be64(pb, mxf->index_entries[i].offset - mxf->index_entries[0].offset); | 991 put_be64(pb, mxf->index_entries[i].offset - mxf->first_edit_unit_offset); |
982 if (s->nb_streams > 1) | 992 if (s->nb_streams > 1) |
983 put_be32(pb, mxf->index_entries[i].slice_offset); | 993 put_be32(pb, mxf->index_entries[i].slice_offset); |
984 } | 994 } |
995 | |
996 mxf->last_indexed_edit_unit += mxf->edit_units_count; | |
997 mxf->edit_units_count = 0; | |
985 } | 998 } |
986 | 999 |
987 static void mxf_write_klv_fill(AVFormatContext *s) | 1000 static void mxf_write_klv_fill(AVFormatContext *s) |
988 { | 1001 { |
989 unsigned pad = klv_fill_size(url_ftell(s->pb)); | 1002 unsigned pad = klv_fill_size(url_ftell(s->pb)); |
1013 index_byte_count = 109 + (s->nb_streams+1)*6 + | 1026 index_byte_count = 109 + (s->nb_streams+1)*6 + |
1014 mxf->edit_units_count*(11+mxf->slice_count*4); | 1027 mxf->edit_units_count*(11+mxf->slice_count*4); |
1015 // add encoded ber length | 1028 // add encoded ber length |
1016 index_byte_count += 16 + klv_ber_length(index_byte_count); | 1029 index_byte_count += 16 + klv_ber_length(index_byte_count); |
1017 index_byte_count += klv_fill_size(index_byte_count); | 1030 index_byte_count += klv_fill_size(index_byte_count); |
1031 | |
1032 mxf->body_offset += url_ftell(pb) - mxf->index_entries[0].offset; | |
1033 } | |
1034 | |
1035 if (!memcmp(key, body_partition_key, 16)) { | |
1036 mxf->body_partition_offset = | |
1037 av_realloc(mxf->body_partition_offset, | |
1038 (mxf->body_partitions_count+1)* | |
1039 sizeof(*mxf->body_partition_offset)); | |
1040 mxf->body_partition_offset[mxf->body_partitions_count++] = url_ftell(pb); | |
1018 } | 1041 } |
1019 | 1042 |
1020 // write klv | 1043 // write klv |
1021 put_buffer(pb, key, 16); | 1044 put_buffer(pb, key, 16); |
1022 | 1045 |
1026 put_be16(pb, 1); // majorVersion | 1049 put_be16(pb, 1); // majorVersion |
1027 put_be16(pb, 2); // minorVersion | 1050 put_be16(pb, 2); // minorVersion |
1028 put_be32(pb, KAG_SIZE); // KAGSize | 1051 put_be32(pb, KAG_SIZE); // KAGSize |
1029 | 1052 |
1030 put_be64(pb, url_ftell(pb) - 25); // thisPartition | 1053 put_be64(pb, url_ftell(pb) - 25); // thisPartition |
1031 put_be64(pb, 0); // previousPartition | 1054 |
1055 if (!memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1) | |
1056 put_be64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition | |
1057 else if (!memcmp(key, footer_partition_key, 16)) | |
1058 put_be64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition | |
1059 else | |
1060 put_be64(pb, 0); | |
1032 | 1061 |
1033 put_be64(pb, mxf->footer_partition_offset); // footerPartition | 1062 put_be64(pb, mxf->footer_partition_offset); // footerPartition |
1034 | 1063 |
1035 // set offset | 1064 // set offset |
1036 header_byte_count_offset = url_ftell(pb); | 1065 header_byte_count_offset = url_ftell(pb); |
1037 put_be64(pb, 0); // headerByteCount, update later | 1066 put_be64(pb, 0); // headerByteCount, update later |
1038 | 1067 |
1039 // indexTable | 1068 // indexTable |
1040 put_be64(pb, index_byte_count); // indexByteCount | 1069 put_be64(pb, index_byte_count); // indexByteCount |
1041 put_be32(pb, index_byte_count ? indexsid : 0); // indexSID | 1070 put_be32(pb, index_byte_count ? indexsid : 0); // indexSID |
1042 put_be64(pb, 0); // bodyOffset | 1071 |
1072 // BodyOffset | |
1073 if (bodysid) put_be64(pb, mxf->body_offset); | |
1074 else put_be64(pb, 0); | |
1043 | 1075 |
1044 put_be32(pb, bodysid); // bodySID | 1076 put_be32(pb, bodysid); // bodySID |
1045 | 1077 |
1046 // operational pattern | 1078 // operational pattern |
1047 if (s->nb_streams > 1) { | 1079 if (s->nb_streams > 1) { |
1309 ByteIOContext *pb = s->pb; | 1341 ByteIOContext *pb = s->pb; |
1310 AVStream *st = s->streams[pkt->stream_index]; | 1342 AVStream *st = s->streams[pkt->stream_index]; |
1311 MXFStreamContext *sc = st->priv_data; | 1343 MXFStreamContext *sc = st->priv_data; |
1312 int flags = 0; | 1344 int flags = 0; |
1313 | 1345 |
1314 if (!(mxf->edit_units_count % MXF_INDEX_CLUSTER_SIZE)) { | 1346 if (!(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) { |
1315 mxf->index_entries = av_realloc(mxf->index_entries, | 1347 mxf->index_entries = av_realloc(mxf->index_entries, |
1316 (mxf->edit_units_count + MXF_INDEX_CLUSTER_SIZE)* | 1348 (mxf->edit_units_count + EDIT_UNITS_PER_BODY)*sizeof(*mxf->index_entries)); |
1317 sizeof(*mxf->index_entries)); | |
1318 if (!mxf->index_entries) { | 1349 if (!mxf->index_entries) { |
1319 av_log(s, AV_LOG_ERROR, "could not allocate index entries\n"); | 1350 av_log(s, AV_LOG_ERROR, "could not allocate index entries\n"); |
1320 return -1; | 1351 return -1; |
1321 } | 1352 } |
1322 } | 1353 } |
1327 return -1; | 1358 return -1; |
1328 } | 1359 } |
1329 } | 1360 } |
1330 | 1361 |
1331 if (!mxf->header_written) { | 1362 if (!mxf->header_written) { |
1332 mxf_write_partition(s, 1, 0, header_open_partition_key, 1); | 1363 mxf_write_partition(s, 0, 0, header_open_partition_key, 1); |
1333 mxf->header_written = 1; | 1364 mxf->header_written = 1; |
1334 } | 1365 } |
1335 | 1366 |
1336 if (st->index == 0) { | 1367 if (st->index == 0) { |
1368 if ((!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) && | |
1369 !(flags & 0x33)) { // I frame, Gop start | |
1370 mxf_write_klv_fill(s); | |
1371 mxf_write_partition(s, 1, 2, body_partition_key, 0); | |
1372 | |
1373 mxf_write_klv_fill(s); | |
1374 mxf_write_index_table_segment(s); | |
1375 } | |
1376 | |
1337 mxf_write_klv_fill(s); | 1377 mxf_write_klv_fill(s); |
1338 mxf->index_entries[mxf->edit_units_count].offset = url_ftell(pb); | 1378 mxf->index_entries[mxf->edit_units_count].offset = url_ftell(pb); |
1339 mxf->index_entries[mxf->edit_units_count].flags = flags; | 1379 mxf->index_entries[mxf->edit_units_count].flags = flags; |
1380 if (!mxf->first_edit_unit_offset) | |
1381 mxf->first_edit_unit_offset = mxf->index_entries[0].offset; | |
1340 mxf_write_system_item(s); | 1382 mxf_write_system_item(s); |
1341 | 1383 |
1342 mxf->edit_units_count++; | 1384 mxf->edit_units_count++; |
1343 } else if (st->index == 1) { | 1385 } else if (st->index == 1) { |
1344 mxf->index_entries[mxf->edit_units_count-1].slice_offset = | 1386 mxf->index_entries[mxf->edit_units_count-1].slice_offset = |
1359 static void mxf_write_random_index_pack(AVFormatContext *s) | 1401 static void mxf_write_random_index_pack(AVFormatContext *s) |
1360 { | 1402 { |
1361 MXFContext *mxf = s->priv_data; | 1403 MXFContext *mxf = s->priv_data; |
1362 ByteIOContext *pb = s->pb; | 1404 ByteIOContext *pb = s->pb; |
1363 uint64_t pos = url_ftell(pb); | 1405 uint64_t pos = url_ftell(pb); |
1406 int i; | |
1364 | 1407 |
1365 put_buffer(pb, random_index_pack_key, 16); | 1408 put_buffer(pb, random_index_pack_key, 16); |
1366 klv_encode_ber_length(pb, 28); | 1409 klv_encode_ber_length(pb, 28 + 12*mxf->body_partitions_count); |
1367 | 1410 |
1368 put_be32(pb, 1); // BodySID of header partition | 1411 put_be32(pb, 0); // BodySID of header partition |
1369 put_be64(pb, 0); // offset of header partition | 1412 put_be64(pb, 0); // offset of header partition |
1413 | |
1414 for (i = 0; i < mxf->body_partitions_count; i++) { | |
1415 put_be32(pb, 1); // BodySID | |
1416 put_be64(pb, mxf->body_partition_offset[i]); | |
1417 } | |
1370 | 1418 |
1371 put_be32(pb, 0); // BodySID of footer partition | 1419 put_be32(pb, 0); // BodySID of footer partition |
1372 put_be64(pb, mxf->footer_partition_offset); | 1420 put_be64(pb, mxf->footer_partition_offset); |
1373 | 1421 |
1374 put_be32(pb, url_ftell(pb) - pos + 4); | 1422 put_be32(pb, url_ftell(pb) - pos + 4); |
1389 mxf_write_klv_fill(s); | 1437 mxf_write_klv_fill(s); |
1390 mxf_write_random_index_pack(s); | 1438 mxf_write_random_index_pack(s); |
1391 | 1439 |
1392 if (!url_is_streamed(s->pb)) { | 1440 if (!url_is_streamed(s->pb)) { |
1393 url_fseek(pb, 0, SEEK_SET); | 1441 url_fseek(pb, 0, SEEK_SET); |
1394 mxf_write_partition(s, 1, 0, header_closed_partition_key, 1); | 1442 mxf_write_partition(s, 0, 0, header_closed_partition_key, 1); |
1395 } | 1443 } |
1396 | 1444 |
1397 ff_audio_interleave_close(s); | 1445 ff_audio_interleave_close(s); |
1398 | 1446 |
1399 av_freep(&mxf->index_entries); | 1447 av_freep(&mxf->index_entries); |
1448 av_freep(&mxf->body_partition_offset); | |
1400 | 1449 |
1401 mxf_free(s); | 1450 mxf_free(s); |
1402 return 0; | 1451 return 0; |
1403 } | 1452 } |
1404 | 1453 |