mirror of https://git.ffmpeg.org/ffmpeg.git
write body partitions
Originally committed as revision 17126 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
7524f46e21
commit
99b170f896
|
@ -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 @@ typedef struct MXFContext {
|
|||
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 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_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 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
|
|||
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 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
|
|||
|
||||
// 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 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
|
|||
} 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 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
|
|||
// 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 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
|
|||
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 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
|
|||
// 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 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||
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 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||
}
|
||||
|
||||
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,13 +1403,19 @@ static void mxf_write_random_index_pack(AVFormatContext *s)
|
|||
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, 1); // BodySID of header partition
|
||||
put_be32(pb, 0); // 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 @@ static int mxf_write_footer(AVFormatContext *s)
|
|||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue