Commit 6a8a3bfb authored by Mark Reid's avatar Mark Reid Committed by Michael Niedermayer

libavformat/mxfenc.c: added mxf opatom muxer

Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 7c148f30
...@@ -206,6 +206,7 @@ void av_register_all(void) ...@@ -206,6 +206,7 @@ void av_register_all(void)
REGISTER_DEMUXER (MVI, mvi); REGISTER_DEMUXER (MVI, mvi);
REGISTER_MUXDEMUX(MXF, mxf); REGISTER_MUXDEMUX(MXF, mxf);
REGISTER_MUXER (MXF_D10, mxf_d10); REGISTER_MUXER (MXF_D10, mxf_d10);
REGISTER_MUXER (MXF_OPATOM, mxf_opatom);
REGISTER_DEMUXER (MXG, mxg); REGISTER_DEMUXER (MXG, mxg);
REGISTER_DEMUXER (NC, nc); REGISTER_DEMUXER (NC, nc);
REGISTER_DEMUXER (NISTSPHERE, nistsphere); REGISTER_DEMUXER (NISTSPHERE, nistsphere);
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "config.h" #include "config.h"
extern AVOutputFormat ff_mxf_d10_muxer; extern AVOutputFormat ff_mxf_d10_muxer;
extern AVOutputFormat ff_mxf_opatom_muxer;
#define EDIT_UNITS_PER_BODY 250 #define EDIT_UNITS_PER_BODY 250
#define KAG_SIZE 512 #define KAG_SIZE 512
...@@ -320,6 +321,7 @@ static const uint8_t umid_ul[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x ...@@ -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 * 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 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 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 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 }; 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) ...@@ -483,6 +485,12 @@ static void klv_encode_ber4_length(AVIOContext *pb, int len)
avio_wb24(pb, 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 * Get essence container ul index
*/ */
...@@ -601,6 +609,9 @@ static void mxf_write_preface(AVFormatContext *s) ...@@ -601,6 +609,9 @@ static void mxf_write_preface(AVFormatContext *s)
// operational pattern // operational pattern
mxf_write_local_tag(pb, 16, 0x3B09); mxf_write_local_tag(pb, 16, 0x3B09);
if (s->oformat == &ff_mxf_opatom_muxer)
avio_write(pb, opatom_ul, 16);
else
avio_write(pb, op1a_ul, 16); avio_write(pb, op1a_ul, 16);
// write essence_container_refs // write essence_container_refs
...@@ -1362,7 +1373,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1362,7 +1373,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
index_byte_count += klv_fill_size(index_byte_count); 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, if ((err = av_reallocp_array(&mxf->body_partition_offset, mxf->body_partitions_count + 1,
sizeof(*mxf->body_partition_offset))) < 0) { sizeof(*mxf->body_partition_offset))) < 0) {
mxf->body_partitions_count = 0; mxf->body_partitions_count = 0;
...@@ -1372,7 +1383,11 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1372,7 +1383,11 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
} }
// write klv // write klv
if (key)
avio_write(pb, key, 16); 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)); klv_encode_ber_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
// write partition value // write partition value
...@@ -1382,9 +1397,9 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1382,9 +1397,9 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
avio_wb64(pb, partition_offset); // ThisPartition 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 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 avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition
else else
avio_wb64(pb, 0); avio_wb64(pb, 0);
...@@ -1400,14 +1415,17 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1400,14 +1415,17 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID
// BodyOffset // 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); avio_wb64(pb, mxf->body_offset);
} else else
avio_wb64(pb, 0); avio_wb64(pb, 0);
avio_wb32(pb, bodysid); // bodySID avio_wb32(pb, bodysid); // bodySID
// operational pattern // operational pattern
if (s->oformat == &ff_mxf_opatom_muxer)
avio_write(pb, opatom_ul, 16);
else
avio_write(pb, op1a_ul, 16); avio_write(pb, op1a_ul, 16);
// essence container // essence container
...@@ -1431,6 +1449,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, ...@@ -1431,6 +1449,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
avio_seek(pb, pos, SEEK_SET); avio_seek(pb, pos, SEEK_SET);
} }
if(key)
avio_flush(pb); avio_flush(pb);
return 0; return 0;
...@@ -1498,6 +1517,11 @@ AVPacket *pkt) ...@@ -1498,6 +1517,11 @@ AVPacket *pkt)
sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul; sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
sc->aspect_ratio = (AVRational){ 16, 9 }; 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; mxf->edit_unit_byte_count = KAG_SIZE;
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i]; AVStream *st = s->streams[i];
...@@ -1568,6 +1592,11 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) ...@@ -1568,6 +1592,11 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
sc->index = ul_index + 16; sc->index = ul_index + 16;
sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul; 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; mxf->edit_unit_byte_count = KAG_SIZE;
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i]; AVStream *st = s->streams[i];
...@@ -1803,6 +1832,11 @@ static int mxf_write_header(AVFormatContext *s) ...@@ -1803,6 +1832,11 @@ static int mxf_write_header(AVFormatContext *s)
if (!s->nb_streams) if (!s->nb_streams)
return -1; 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++) { for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i]; AVStream *st = s->streams[i];
MXFStreamContext *sc = av_mallocz(sizeof(*sc)); MXFStreamContext *sc = av_mallocz(sizeof(*sc));
...@@ -1901,7 +1935,7 @@ static int mxf_write_header(AVFormatContext *s) ...@@ -1901,7 +1935,7 @@ static int mxf_write_header(AVFormatContext *s)
present[sc->index]++; 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; mxf->essence_container_count = 1;
} }
...@@ -2046,6 +2080,60 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke ...@@ -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) static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
{ {
MXFContext *mxf = s->priv_data; MXFContext *mxf = s->priv_data;
...@@ -2086,6 +2174,9 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -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->header_written) {
if (mxf->edit_unit_byte_count) { if (mxf->edit_unit_byte_count) {
if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0) 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) ...@@ -2153,7 +2244,7 @@ static void mxf_write_random_index_pack(AVFormatContext *s)
avio_write(pb, random_index_pack_key, 16); avio_write(pb, random_index_pack_key, 16);
klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count); 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 avio_wb32(pb, 1); // BodySID of header partition
else else
avio_wb32(pb, 0); avio_wb32(pb, 0);
...@@ -2180,7 +2271,7 @@ static int mxf_write_footer(AVFormatContext *s) ...@@ -2180,7 +2271,7 @@ static int mxf_write_footer(AVFormatContext *s)
mxf_write_klv_fill(s); mxf_write_klv_fill(s);
mxf->footer_partition_offset = avio_tell(pb); 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) if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0)
return err; return err;
} else { } else {
...@@ -2194,8 +2285,15 @@ static int mxf_write_footer(AVFormatContext *s) ...@@ -2194,8 +2285,15 @@ static int mxf_write_footer(AVFormatContext *s)
mxf_write_random_index_pack(s); mxf_write_random_index_pack(s);
if (s->pb->seekable) { 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); 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) if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0)
return err; return err;
mxf_write_klv_fill(s); mxf_write_klv_fill(s);
...@@ -2330,3 +2428,18 @@ AVOutputFormat ff_mxf_d10_muxer = { ...@@ -2330,3 +2428,18 @@ AVOutputFormat ff_mxf_d10_muxer = {
.interleave_packet = mxf_interleave, .interleave_packet = mxf_interleave,
.priv_class = &mxf_d10_muxer_class, .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,
};
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