libavformat/mxfenc.c: added mxf opatom muxer
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
7c148f30f3
commit
6a8a3bfb87
@ -206,6 +206,7 @@ void av_register_all(void)
|
||||
REGISTER_DEMUXER (MVI, mvi);
|
||||
REGISTER_MUXDEMUX(MXF, mxf);
|
||||
REGISTER_MUXER (MXF_D10, mxf_d10);
|
||||
REGISTER_MUXER (MXF_OPATOM, mxf_opatom);
|
||||
REGISTER_DEMUXER (MXG, mxg);
|
||||
REGISTER_DEMUXER (NC, nc);
|
||||
REGISTER_DEMUXER (NISTSPHERE, nistsphere);
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "config.h"
|
||||
|
||||
extern AVOutputFormat ff_mxf_d10_muxer;
|
||||
extern AVOutputFormat ff_mxf_opatom_muxer;
|
||||
|
||||
#define EDIT_UNITS_PER_BODY 250
|
||||
#define KAG_SIZE 512
|
||||
@ -320,6 +321,7 @@ static const uint8_t umid_ul[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x
|
||||
* complete key for operation pattern, partitions, and primer pack
|
||||
*/
|
||||
static const uint8_t op1a_ul[] = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x01,0x09,0x00 };
|
||||
static const uint8_t opatom_ul[] = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x02,0x01,0x10,0x03,0x00,0x00 };
|
||||
static const uint8_t footer_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }; // ClosedComplete
|
||||
static const uint8_t primer_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x05,0x01,0x00 };
|
||||
static const uint8_t index_table_segment_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 };
|
||||
@ -483,6 +485,12 @@ static void klv_encode_ber4_length(AVIOContext *pb, int len)
|
||||
avio_wb24(pb, len);
|
||||
}
|
||||
|
||||
static void klv_encode_ber9_length(AVIOContext *pb, uint64_t len)
|
||||
{
|
||||
avio_w8(pb, 0x80 + 8);
|
||||
avio_wb64(pb, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get essence container ul index
|
||||
*/
|
||||
@ -601,7 +609,10 @@ static void mxf_write_preface(AVFormatContext *s)
|
||||
|
||||
// operational pattern
|
||||
mxf_write_local_tag(pb, 16, 0x3B09);
|
||||
avio_write(pb, op1a_ul, 16);
|
||||
if (s->oformat == &ff_mxf_opatom_muxer)
|
||||
avio_write(pb, opatom_ul, 16);
|
||||
else
|
||||
avio_write(pb, op1a_ul, 16);
|
||||
|
||||
// write essence_container_refs
|
||||
mxf_write_local_tag(pb, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A);
|
||||
@ -1362,7 +1373,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
|
||||
index_byte_count += klv_fill_size(index_byte_count);
|
||||
}
|
||||
|
||||
if (!memcmp(key, body_partition_key, 16)) {
|
||||
if (key && !memcmp(key, body_partition_key, 16)) {
|
||||
if ((err = av_reallocp_array(&mxf->body_partition_offset, mxf->body_partitions_count + 1,
|
||||
sizeof(*mxf->body_partition_offset))) < 0) {
|
||||
mxf->body_partitions_count = 0;
|
||||
@ -1372,7 +1383,11 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
|
||||
}
|
||||
|
||||
// write klv
|
||||
avio_write(pb, key, 16);
|
||||
if (key)
|
||||
avio_write(pb, key, 16);
|
||||
else
|
||||
avio_write(pb, body_partition_key, 16);
|
||||
|
||||
klv_encode_ber_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
|
||||
|
||||
// write partition value
|
||||
@ -1382,9 +1397,9 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
|
||||
|
||||
avio_wb64(pb, partition_offset); // ThisPartition
|
||||
|
||||
if (!memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
|
||||
if (key && !memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)
|
||||
avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition
|
||||
else if (!memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
|
||||
else if (key && !memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)
|
||||
avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
|
||||
else
|
||||
avio_wb64(pb, 0);
|
||||
@ -1400,15 +1415,18 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
|
||||
avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
|
||||
|
||||
// BodyOffset
|
||||
if (bodysid && mxf->edit_units_count && mxf->body_partitions_count) {
|
||||
if (bodysid && mxf->edit_units_count && mxf->body_partitions_count && s->oformat != &ff_mxf_opatom_muxer)
|
||||
avio_wb64(pb, mxf->body_offset);
|
||||
} else
|
||||
else
|
||||
avio_wb64(pb, 0);
|
||||
|
||||
avio_wb32(pb, bodysid); // bodySID
|
||||
|
||||
// operational pattern
|
||||
avio_write(pb, op1a_ul, 16);
|
||||
if (s->oformat == &ff_mxf_opatom_muxer)
|
||||
avio_write(pb, opatom_ul, 16);
|
||||
else
|
||||
avio_write(pb, op1a_ul, 16);
|
||||
|
||||
// essence container
|
||||
mxf_write_essence_container_refs(s);
|
||||
@ -1431,7 +1449,8 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
|
||||
avio_seek(pb, pos, SEEK_SET);
|
||||
}
|
||||
|
||||
avio_flush(pb);
|
||||
if(key)
|
||||
avio_flush(pb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1498,6 +1517,11 @@ AVPacket *pkt)
|
||||
sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
|
||||
sc->aspect_ratio = (AVRational){ 16, 9 };
|
||||
|
||||
if(s->oformat == &ff_mxf_opatom_muxer){
|
||||
mxf->edit_unit_byte_count = frame_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
mxf->edit_unit_byte_count = KAG_SIZE;
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
@ -1568,6 +1592,11 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
||||
sc->index = ul_index + 16;
|
||||
sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
|
||||
|
||||
if(s->oformat == &ff_mxf_opatom_muxer) {
|
||||
mxf->edit_unit_byte_count = frame_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
mxf->edit_unit_byte_count = KAG_SIZE;
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
@ -1803,6 +1832,11 @@ static int mxf_write_header(AVFormatContext *s)
|
||||
if (!s->nb_streams)
|
||||
return -1;
|
||||
|
||||
if (s->oformat == &ff_mxf_opatom_muxer && s->nb_streams !=1){
|
||||
av_log(s, AV_LOG_ERROR, "there must be exactly one stream for mxf opatom\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
MXFStreamContext *sc = av_mallocz(sizeof(*sc));
|
||||
@ -1901,7 +1935,7 @@ static int mxf_write_header(AVFormatContext *s)
|
||||
present[sc->index]++;
|
||||
}
|
||||
|
||||
if (s->oformat == &ff_mxf_d10_muxer) {
|
||||
if (s->oformat == &ff_mxf_d10_muxer || s->oformat == &ff_mxf_opatom_muxer) {
|
||||
mxf->essence_container_count = 1;
|
||||
}
|
||||
|
||||
@ -2046,6 +2080,60 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke
|
||||
}
|
||||
}
|
||||
|
||||
static int mxf_write_opatom_body_partition(AVFormatContext *s)
|
||||
{
|
||||
MXFContext *mxf = s->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
AVStream *st = s->streams[0];
|
||||
MXFStreamContext *sc = st->priv_data;
|
||||
const uint8_t *key = NULL;
|
||||
|
||||
int err;
|
||||
|
||||
if (!mxf->header_written)
|
||||
key = body_partition_key;
|
||||
|
||||
if ((err = mxf_write_partition(s, 1, 0, key, 0)) < 0)
|
||||
return err;
|
||||
mxf_write_klv_fill(s);
|
||||
avio_write(pb, sc->track_essence_element_key, 16);
|
||||
klv_encode_ber9_length(pb, mxf->body_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxf_write_opatom_packet(AVFormatContext *s, AVPacket *pkt, MXFIndexEntry *ie)
|
||||
{
|
||||
MXFContext *mxf = s->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
AVStream *st = s->streams[pkt->stream_index];
|
||||
MXFStreamContext *sc = st->priv_data;
|
||||
|
||||
int err;
|
||||
|
||||
if (!mxf->header_written) {
|
||||
if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0)
|
||||
return err;
|
||||
mxf_write_klv_fill(s);
|
||||
|
||||
if ((err = mxf_write_opatom_body_partition(s)) < 0)
|
||||
return err;
|
||||
mxf->header_written = 1;
|
||||
}
|
||||
|
||||
if (!mxf->edit_unit_byte_count) {
|
||||
mxf->index_entries[mxf->edit_units_count].offset = mxf->body_offset;
|
||||
mxf->index_entries[mxf->edit_units_count].flags = ie->flags;
|
||||
mxf->index_entries[mxf->edit_units_count].temporal_ref = ie->temporal_ref;
|
||||
}
|
||||
mxf->edit_units_count++;
|
||||
avio_write(pb, pkt->data, pkt->size);
|
||||
mxf->body_offset += pkt->size;
|
||||
|
||||
avio_flush(pb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
MXFContext *mxf = s->priv_data;
|
||||
@ -2086,6 +2174,9 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
}
|
||||
}
|
||||
|
||||
if (s->oformat == &ff_mxf_opatom_muxer)
|
||||
return mxf_write_opatom_packet(s, pkt, &ie);
|
||||
|
||||
if (!mxf->header_written) {
|
||||
if (mxf->edit_unit_byte_count) {
|
||||
if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0)
|
||||
@ -2153,7 +2244,7 @@ static void mxf_write_random_index_pack(AVFormatContext *s)
|
||||
avio_write(pb, random_index_pack_key, 16);
|
||||
klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count);
|
||||
|
||||
if (mxf->edit_unit_byte_count)
|
||||
if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer)
|
||||
avio_wb32(pb, 1); // BodySID of header partition
|
||||
else
|
||||
avio_wb32(pb, 0);
|
||||
@ -2180,7 +2271,7 @@ static int mxf_write_footer(AVFormatContext *s)
|
||||
|
||||
mxf_write_klv_fill(s);
|
||||
mxf->footer_partition_offset = avio_tell(pb);
|
||||
if (mxf->edit_unit_byte_count) { // no need to repeat index
|
||||
if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { // no need to repeat index
|
||||
if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0)
|
||||
return err;
|
||||
} else {
|
||||
@ -2194,8 +2285,15 @@ static int mxf_write_footer(AVFormatContext *s)
|
||||
mxf_write_random_index_pack(s);
|
||||
|
||||
if (s->pb->seekable) {
|
||||
if (s->oformat == &ff_mxf_opatom_muxer){
|
||||
/* rewrite body partition to update lengths */
|
||||
avio_seek(pb, mxf->body_partition_offset[0], SEEK_SET);
|
||||
if ((err = mxf_write_opatom_body_partition(s)) < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
avio_seek(pb, 0, SEEK_SET);
|
||||
if (mxf->edit_unit_byte_count) {
|
||||
if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) {
|
||||
if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0)
|
||||
return err;
|
||||
mxf_write_klv_fill(s);
|
||||
@ -2330,3 +2428,18 @@ AVOutputFormat ff_mxf_d10_muxer = {
|
||||
.interleave_packet = mxf_interleave,
|
||||
.priv_class = &mxf_d10_muxer_class,
|
||||
};
|
||||
|
||||
AVOutputFormat ff_mxf_opatom_muxer = {
|
||||
.name = "mxf_opatom",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) Operational Pattern Atom"),
|
||||
.mime_type = "application/mxf",
|
||||
.extensions = "mxf",
|
||||
.priv_data_size = sizeof(MXFContext),
|
||||
.audio_codec = AV_CODEC_ID_PCM_S16LE,
|
||||
.video_codec = AV_CODEC_ID_DNXHD,
|
||||
.write_header = mxf_write_header,
|
||||
.write_packet = mxf_write_packet,
|
||||
.write_trailer = mxf_write_footer,
|
||||
.flags = AVFMT_NOTIMESTAMPS,
|
||||
.interleave_packet = mxf_interleave,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user