Commit 99b170f8 authored by Baptiste Coudurier's avatar Baptiste Coudurier

write body partitions

Originally committed as revision 17126 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 7524f46e
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 }; static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 };
static const int PAL_samples_per_frame[] = { 1920, 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 #define KAG_SIZE 512
typedef struct { typedef struct {
...@@ -119,6 +119,12 @@ typedef struct MXFContext { ...@@ -119,6 +119,12 @@ typedef struct MXFContext {
unsigned edit_units_count; unsigned edit_units_count;
uint64_t timestamp; ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8) 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) 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; } MXFContext;
static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; 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 random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02, ...@@ -135,6 +141,7 @@ static const uint8_t random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,
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_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 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 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 * partial key for header metadata
...@@ -875,10 +882,13 @@ static void mxf_write_index_table_segment(AVFormatContext *s) ...@@ -875,10 +882,13 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
ByteIOContext *pb = s->pb; ByteIOContext *pb = s->pb;
int i, j; int i, j;
int temporal_reordering = 0; 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); 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); put_buffer(pb, index_table_segment_key, 16);
klv_encode_ber_length(pb, 109 + (s->nb_streams+1)*6 + klv_encode_ber_length(pb, 109 + (s->nb_streams+1)*6 +
mxf->edit_units_count*(11+mxf->slice_count*4)); mxf->edit_units_count*(11+mxf->slice_count*4));
...@@ -894,7 +904,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s) ...@@ -894,7 +904,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
// index start position // index start position
mxf_write_local_tag(pb, 8, 0x3F0C); mxf_write_local_tag(pb, 8, 0x3F0C);
put_be64(pb, 0); put_be64(pb, mxf->last_indexed_edit_unit);
// index duration // index duration
mxf_write_local_tag(pb, 8, 0x3F0D); mxf_write_local_tag(pb, 8, 0x3F0D);
...@@ -965,23 +975,26 @@ static void mxf_write_index_table_segment(AVFormatContext *s) ...@@ -965,23 +975,26 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
} else } else
put_byte(pb, 0); put_byte(pb, 0);
if (!(mxf->index_entries[i].flags & 0x33)) { // I frame if (!(mxf->index_entries[i].flags & 0x33)) { // I frame
last_key_index = key_index; mxf->last_key_index = key_index;
key_index = i; key_index = i;
} }
if (mxf->index_entries[i].flags & 0x10 && // backward prediction if (mxf->index_entries[i].flags & 0x10 && // backward prediction
!(mxf->index_entries[key_index].flags & 0x80)) { // open gop !(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 { } else {
put_byte(pb, key_index - i); // key frame offset put_byte(pb, key_index - i); // key frame offset
if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward 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); put_byte(pb, mxf->index_entries[i].flags);
// stream offset // 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) if (s->nb_streams > 1)
put_be32(pb, mxf->index_entries[i].slice_offset); 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) static void mxf_write_klv_fill(AVFormatContext *s)
...@@ -1015,6 +1028,16 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1015,6 +1028,16 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
// add encoded ber length // add encoded ber length
index_byte_count += 16 + klv_ber_length(index_byte_count); index_byte_count += 16 + klv_ber_length(index_byte_count);
index_byte_count += klv_fill_size(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 // write klv
...@@ -1028,7 +1051,13 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1028,7 +1051,13 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
put_be32(pb, KAG_SIZE); // KAGSize put_be32(pb, KAG_SIZE); // KAGSize
put_be64(pb, url_ftell(pb) - 25); // thisPartition 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 put_be64(pb, mxf->footer_partition_offset); // footerPartition
...@@ -1039,7 +1068,10 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1039,7 +1068,10 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
// indexTable // indexTable
put_be64(pb, index_byte_count); // indexByteCount put_be64(pb, index_byte_count); // indexByteCount
put_be32(pb, index_byte_count ? indexsid : 0); // indexSID 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 put_be32(pb, bodysid); // bodySID
...@@ -1311,10 +1343,9 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1311,10 +1343,9 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
MXFStreamContext *sc = st->priv_data; MXFStreamContext *sc = st->priv_data;
int flags = 0; 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->index_entries = av_realloc(mxf->index_entries,
(mxf->edit_units_count + MXF_INDEX_CLUSTER_SIZE)* (mxf->edit_units_count + EDIT_UNITS_PER_BODY)*sizeof(*mxf->index_entries));
sizeof(*mxf->index_entries));
if (!mxf->index_entries) { if (!mxf->index_entries) {
av_log(s, AV_LOG_ERROR, "could not allocate index entries\n"); av_log(s, AV_LOG_ERROR, "could not allocate index entries\n");
return -1; return -1;
...@@ -1329,14 +1360,25 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1329,14 +1360,25 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
} }
if (!mxf->header_written) { 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; mxf->header_written = 1;
} }
if (st->index == 0) { 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_write_klv_fill(s);
mxf->index_entries[mxf->edit_units_count].offset = url_ftell(pb); mxf->index_entries[mxf->edit_units_count].offset = url_ftell(pb);
mxf->index_entries[mxf->edit_units_count].flags = flags; 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_write_system_item(s);
mxf->edit_units_count++; mxf->edit_units_count++;
...@@ -1361,13 +1403,19 @@ static void mxf_write_random_index_pack(AVFormatContext *s) ...@@ -1361,13 +1403,19 @@ static void mxf_write_random_index_pack(AVFormatContext *s)
MXFContext *mxf = s->priv_data; MXFContext *mxf = s->priv_data;
ByteIOContext *pb = s->pb; ByteIOContext *pb = s->pb;
uint64_t pos = url_ftell(pb); uint64_t pos = url_ftell(pb);
int i;
put_buffer(pb, random_index_pack_key, 16); 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, 1); // BodySID of header partition put_be32(pb, 0); // BodySID of header partition
put_be64(pb, 0); // offset 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_be32(pb, 0); // BodySID of footer partition
put_be64(pb, mxf->footer_partition_offset); put_be64(pb, mxf->footer_partition_offset);
...@@ -1391,12 +1439,13 @@ static int mxf_write_footer(AVFormatContext *s) ...@@ -1391,12 +1439,13 @@ static int mxf_write_footer(AVFormatContext *s)
if (!url_is_streamed(s->pb)) { if (!url_is_streamed(s->pb)) {
url_fseek(pb, 0, SEEK_SET); 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); ff_audio_interleave_close(s);
av_freep(&mxf->index_entries); av_freep(&mxf->index_entries);
av_freep(&mxf->body_partition_offset);
mxf_free(s); mxf_free(s);
return 0; return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment