# HG changeset patch # User bcoudurier # Date 1234256549 0 # Node ID 64f62c9643c38a272af087ca826e6b18d01ac446 # Parent 4bc3b8687ec215ed2aca0c908416261be736004e write body partitions diff -r 4bc3b8687ec2 -r 64f62c9643c3 mxfenc.c --- a/mxfenc.c Tue Feb 10 08:46:04 2009 +0000 +++ b/mxfenc.c Tue Feb 10 09:02:29 2009 +0000 @@ -44,7 +44,7 @@ static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 }; static const int PAL_samples_per_frame[] = { 1920, 0 }; -#define MXF_INDEX_CLUSTER_SIZE 4096 +#define EDIT_UNITS_PER_BODY 250 #define KAG_SIZE 512 typedef struct { @@ -119,6 +119,12 @@ unsigned edit_units_count; uint64_t timestamp; ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8) uint8_t slice_count; ///< index slice count minus 1 (1 if no audio, 0 otherwise) + int last_indexed_edit_unit; + uint64_t first_edit_unit_offset; + uint64_t *body_partition_offset; + unsigned body_partitions_count; + int last_key_index; ///< index of last key frame + uint64_t body_offset; } MXFContext; static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; @@ -135,6 +141,7 @@ 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 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 static const uint8_t klv_fill_key[] = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 }; +static const uint8_t body_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }; // ClosedComplete /** * partial key for header metadata @@ -875,10 +882,13 @@ ByteIOContext *pb = s->pb; int i, j; int temporal_reordering = 0; - int last_key_index = 0, key_index = 0; + int key_index = 0; av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count); + if (!mxf->edit_units_count) + return; + put_buffer(pb, index_table_segment_key, 16); klv_encode_ber_length(pb, 109 + (s->nb_streams+1)*6 + mxf->edit_units_count*(11+mxf->slice_count*4)); @@ -894,7 +904,7 @@ // index start position mxf_write_local_tag(pb, 8, 0x3F0C); - put_be64(pb, 0); + put_be64(pb, mxf->last_indexed_edit_unit); // index duration mxf_write_local_tag(pb, 8, 0x3F0D); @@ -965,23 +975,26 @@ } else put_byte(pb, 0); if (!(mxf->index_entries[i].flags & 0x33)) { // I frame - last_key_index = key_index; + mxf->last_key_index = key_index; key_index = i; } if (mxf->index_entries[i].flags & 0x10 && // backward prediction !(mxf->index_entries[key_index].flags & 0x80)) { // open gop - put_byte(pb, last_key_index - i); + put_byte(pb, mxf->last_key_index - i); } else { put_byte(pb, key_index - i); // key frame offset if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward - last_key_index = key_index; + mxf->last_key_index = key_index; } put_byte(pb, mxf->index_entries[i].flags); // stream offset - put_be64(pb, mxf->index_entries[i].offset - mxf->index_entries[0].offset); + put_be64(pb, mxf->index_entries[i].offset - mxf->first_edit_unit_offset); if (s->nb_streams > 1) put_be32(pb, mxf->index_entries[i].slice_offset); } + + mxf->last_indexed_edit_unit += mxf->edit_units_count; + mxf->edit_units_count = 0; } static void mxf_write_klv_fill(AVFormatContext *s) @@ -1015,6 +1028,16 @@ // add encoded ber length index_byte_count += 16 + klv_ber_length(index_byte_count); index_byte_count += klv_fill_size(index_byte_count); + + mxf->body_offset += url_ftell(pb) - mxf->index_entries[0].offset; + } + + if (!memcmp(key, body_partition_key, 16)) { + mxf->body_partition_offset = + av_realloc(mxf->body_partition_offset, + (mxf->body_partitions_count+1)* + sizeof(*mxf->body_partition_offset)); + mxf->body_partition_offset[mxf->body_partitions_count++] = url_ftell(pb); } // write klv @@ -1028,7 +1051,13 @@ put_be32(pb, KAG_SIZE); // KAGSize put_be64(pb, url_ftell(pb) - 25); // thisPartition - put_be64(pb, 0); // previousPartition + + if (!memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1) + put_be64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition + else if (!memcmp(key, footer_partition_key, 16)) + put_be64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition + else + put_be64(pb, 0); put_be64(pb, mxf->footer_partition_offset); // footerPartition @@ -1039,7 +1068,10 @@ // indexTable put_be64(pb, index_byte_count); // indexByteCount put_be32(pb, index_byte_count ? indexsid : 0); // indexSID - put_be64(pb, 0); // bodyOffset + + // BodyOffset + if (bodysid) put_be64(pb, mxf->body_offset); + else put_be64(pb, 0); put_be32(pb, bodysid); // bodySID @@ -1311,10 +1343,9 @@ MXFStreamContext *sc = st->priv_data; int flags = 0; - if (!(mxf->edit_units_count % MXF_INDEX_CLUSTER_SIZE)) { + if (!(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) { mxf->index_entries = av_realloc(mxf->index_entries, - (mxf->edit_units_count + MXF_INDEX_CLUSTER_SIZE)* - sizeof(*mxf->index_entries)); + (mxf->edit_units_count + EDIT_UNITS_PER_BODY)*sizeof(*mxf->index_entries)); if (!mxf->index_entries) { av_log(s, AV_LOG_ERROR, "could not allocate index entries\n"); return -1; @@ -1329,14 +1360,25 @@ } if (!mxf->header_written) { - mxf_write_partition(s, 1, 0, header_open_partition_key, 1); + mxf_write_partition(s, 0, 0, header_open_partition_key, 1); mxf->header_written = 1; } if (st->index == 0) { + if ((!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) && + !(flags & 0x33)) { // I frame, Gop start + mxf_write_klv_fill(s); + mxf_write_partition(s, 1, 2, body_partition_key, 0); + + mxf_write_klv_fill(s); + mxf_write_index_table_segment(s); + } + mxf_write_klv_fill(s); mxf->index_entries[mxf->edit_units_count].offset = url_ftell(pb); mxf->index_entries[mxf->edit_units_count].flags = flags; + if (!mxf->first_edit_unit_offset) + mxf->first_edit_unit_offset = mxf->index_entries[0].offset; mxf_write_system_item(s); mxf->edit_units_count++; @@ -1361,12 +1403,18 @@ MXFContext *mxf = s->priv_data; ByteIOContext *pb = s->pb; uint64_t pos = url_ftell(pb); + int i; put_buffer(pb, random_index_pack_key, 16); - klv_encode_ber_length(pb, 28); + klv_encode_ber_length(pb, 28 + 12*mxf->body_partitions_count); + + put_be32(pb, 0); // BodySID of header partition + put_be64(pb, 0); // offset of header partition - put_be32(pb, 1); // BodySID of header partition - put_be64(pb, 0); // offset of header partition + for (i = 0; i < mxf->body_partitions_count; i++) { + put_be32(pb, 1); // BodySID + put_be64(pb, mxf->body_partition_offset[i]); + } put_be32(pb, 0); // BodySID of footer partition put_be64(pb, mxf->footer_partition_offset); @@ -1391,12 +1439,13 @@ if (!url_is_streamed(s->pb)) { url_fseek(pb, 0, SEEK_SET); - mxf_write_partition(s, 1, 0, header_closed_partition_key, 1); + mxf_write_partition(s, 0, 0, header_closed_partition_key, 1); } ff_audio_interleave_close(s); av_freep(&mxf->index_entries); + av_freep(&mxf->body_partition_offset); mxf_free(s); return 0;