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