INDEX_DV100_1080_50,
INDEX_DV100_720_60,
INDEX_DV100_720_50,
- INDEX_DNXHD_1080p_10bit_HIGH,
- INDEX_DNXHD_1080p_8bit_MEDIUM,
- INDEX_DNXHD_1080p_8bit_HIGH,
- INDEX_DNXHD_1080i_10bit_HIGH,
- INDEX_DNXHD_1080i_8bit_MEDIUM,
- INDEX_DNXHD_1080i_8bit_HIGH,
- INDEX_DNXHD_720p_10bit,
- INDEX_DNXHD_720p_8bit_HIGH,
- INDEX_DNXHD_720p_8bit_MEDIUM,
- INDEX_DNXHD_720p_8bit_LOW,
- INDEX_DNXHR_LB,
- INDEX_DNXHR_SQ,
- INDEX_DNXHR_HQ,
- INDEX_DNXHR_HQX,
- INDEX_DNXHR_444,
+ INDEX_DNXHD,
INDEX_JPEG2000,
INDEX_H264,
+ INDEX_S436M,
+ INDEX_PRORES,
};
static const struct {
{ AV_CODEC_ID_PCM_S24LE, INDEX_AES3 },
{ AV_CODEC_ID_PCM_S16LE, INDEX_AES3 },
{ AV_CODEC_ID_DVVIDEO, INDEX_DV },
- { AV_CODEC_ID_DNXHD, INDEX_DNXHD_1080p_10bit_HIGH },
+ { AV_CODEC_ID_DNXHD, INDEX_DNXHD },
{ AV_CODEC_ID_JPEG2000, INDEX_JPEG2000 },
{ AV_CODEC_ID_H264, INDEX_H264 },
+ { AV_CODEC_ID_PRORES, INDEX_PRORES },
{ AV_CODEC_ID_NONE }
};
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
+static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st);
static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 },
{ 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x08,0x00 },
mxf_write_cdci_desc },
- // DNxHD 1080p 10bit high
+ // DNxHD
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
{ 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 },
mxf_write_cdci_desc },
- // DNxHD 1080p 8bit medium
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 1080p 8bit high
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 1080i 10bit high
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 1080i 8bit medium
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 1080i 8bit high
- { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 720p 10bit
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 720p 8bit high
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 720p 8bit medium
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHD 720p 8bit low
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHR LB - CID 1274
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHR SQ - CID 1273
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHR HQ - CID 1272
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHR HQX - CID 1271
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 },
- mxf_write_cdci_desc },
- // DNxHR 444 - CID 1270
- { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
- { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 },
- mxf_write_cdci_desc },
// JPEG2000
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 },
{ 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x08,0x00 },
{ 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
mxf_write_mpegvideo_desc },
+ // S436M ANC
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 },
+ { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x17,0x01,0x02,0x00 },
+ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x01,0x5C,0x00 },
+ mxf_write_s436m_anc_desc },
+ // ProRes
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x1c,0x01,0x00 },
+ { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x17,0x00 },
+ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x03,0x00 },
+ mxf_write_cdci_desc },
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
mxf_write_refs_count(pb, DESCRIPTOR_COUNT(c->essence_container_count));
av_log(s,AV_LOG_DEBUG, "essence container count:%d\n", c->essence_container_count);
- for (i = 0; i < c->essence_container_count; i++) {
+ for (i = 0; i < s->nb_streams; i++) {
MXFStreamContext *sc = s->streams[i]->priv_data;
+ // check first track of essence container type and only write it once
+ if (sc->track_essence_element_key[15] != 0)
+ continue;
avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
+ if (c->essence_container_count == 1)
+ break;
}
if (c->essence_container_count > 1)
return pos;
}
+static const UID mxf_s436m_anc_descriptor_key = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 };
static const UID mxf_mpegvideo_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 };
static const UID mxf_wav_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 };
static const UID mxf_aes3_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 };
default: f1 = 0; f2 = 0; break;
}
- if (!sc->interlaced) {
+ if (!sc->interlaced && f2) {
f2 = 0;
f1 *= 2;
}
mxf_update_klv_size(s->pb, pos);
}
+static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st)
+{
+ int64_t pos = mxf_write_generic_desc(s, st, mxf_s436m_anc_descriptor_key);
+ mxf_update_klv_size(s->pb, pos);
+}
+
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
{
AVIOContext *pb = s->pb;
int i, j, temporal_reordering = 0;
int key_index = mxf->last_key_index;
int prev_non_b_picture = 0;
+ int audio_frame_size = 0;
int64_t pos;
av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count);
} else if (i == 0) { // video track
avio_w8(pb, 0); // slice number
avio_wb32(pb, KAG_SIZE); // system item size including klv fill
- } else { // audio track
- unsigned audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
- audio_frame_size += klv_fill_size(audio_frame_size);
+ } else { // audio or data track
+ if (!audio_frame_size) {
+ audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
+ audio_frame_size += klv_fill_size(audio_frame_size);
+ }
avio_w8(pb, 1);
avio_wb32(pb, (i-1)*audio_frame_size); // element delta
}
return 0;
}
-static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st,
-AVPacket *pkt)
+static const struct {
+ int profile;
+ UID codec_ul;
+} mxf_prores_codec_uls[] = {
+ { FF_PROFILE_PRORES_PROXY, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x01,0x00 } },
+ { FF_PROFILE_PRORES_LT, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x02,0x00 } },
+ { FF_PROFILE_PRORES_STANDARD, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x03,0x00 } },
+ { FF_PROFILE_PRORES_HQ, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x04,0x00 } },
+ { FF_PROFILE_PRORES_4444, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x05,0x00 } },
+ { FF_PROFILE_PRORES_XQ, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x06,0x00 } },
+};
+
+static int mxf_parse_prores_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
{
MXFContext *mxf = s->priv_data;
MXFStreamContext *sc = st->priv_data;
- int i, cid;
- uint8_t* header_cid;
- int frame_size = 0;
+ int i, profile;
+
+ if (mxf->header_written)
+ return 1;
+
+ sc->codec_ul = NULL;
+ profile = st->codecpar->profile;
+ for (i = 0; i < FF_ARRAY_ELEMS(mxf_prores_codec_uls); i++) {
+ if (profile == mxf_prores_codec_uls[i].profile) {
+ sc->codec_ul = &mxf_prores_codec_uls[i].codec_ul;
+ break;
+ }
+ }
+ if (!sc->codec_ul)
+ return 0;
+
+ sc->frame_size = pkt->size;
+
+ return 1;
+}
+
+static const struct {
+ int cid;
+ UID codec_ul;
+} mxf_dnxhd_codec_uls[] = {
+ { 1235, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 } }, // 1080p 10bit HIGH
+ { 1237, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 } }, // 1080p 8bit MED
+ { 1238, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 } }, // 1080p 8bit HIGH
+ { 1241, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 } }, // 1080i 10bit HIGH
+ { 1242, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 } }, // 1080i 8bit MED
+ { 1243, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 } }, // 1080i 8bit HIGH
+ { 1244, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x0a,0x00,0x00 } }, // 1080i 8bit TR
+ { 1250, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 } }, // 720p 10bit
+ { 1251, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 } }, // 720p 8bit HIGH
+ { 1252, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 } }, // 720p 8bit MED
+ { 1253, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 } }, // 720p 8bit LOW
+ { 1256, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x16,0x00,0x00 } }, // 1080p 10bit 444
+ { 1258, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x18,0x00,0x00 } }, // 720p 8bit TR
+ { 1259, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x19,0x00,0x00 } }, // 1080p 8bit TR
+ { 1260, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x1a,0x00,0x00 } }, // 1080i 8bit TR MBAFF
+ { 1270, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 } }, // DNXHR 444
+ { 1271, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 } }, // DNXHR HQX
+ { 1272, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 } }, // DNXHR HQ
+ { 1273, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 } }, // DNXHR SQ
+ { 1274, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 } }, // DNXHR LB
+};
+
+static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
+{
+ MXFContext *mxf = s->priv_data;
+ MXFStreamContext *sc = st->priv_data;
+ int i, cid, frame_size = 0;
if (mxf->header_written)
return 1;
if (pkt->size < 43)
- return -1;
+ return 0;
- header_cid = pkt->data + 0x28;
- cid = header_cid[0] << 24 | header_cid[1] << 16 | header_cid[2] << 8 | header_cid[3];
+ sc->codec_ul = NULL;
+ cid = AV_RB32(pkt->data + 0x28);
+ for (i = 0; i < FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls); i++) {
+ if (cid == mxf_dnxhd_codec_uls[i].cid) {
+ sc->codec_ul = &mxf_dnxhd_codec_uls[i].codec_ul;
+ break;
+ }
+ }
+ if (!sc->codec_ul)
+ return 0;
+
+ sc->component_depth = 0;
+ switch (pkt->data[0x21] >> 5) {
+ case 1: sc->component_depth = 8; break;
+ case 2: sc->component_depth = 10; break;
+ case 3: sc->component_depth = 12; break;
+ }
+ if (!sc->component_depth)
+ return 0;
if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) == DNXHD_VARIABLE) {
frame_size = avpriv_dnxhd_get_hr_frame_size(cid, st->codecpar->width, st->codecpar->height);
}
-
if (frame_size < 0)
- return -1;
+ return 0;
+
if ((sc->interlaced = avpriv_dnxhd_get_interlaced(cid)) < 0)
- return AVERROR_INVALIDDATA;
+ return 0;
- switch (cid) {
- case 1235:
- sc->index = INDEX_DNXHD_1080p_10bit_HIGH;
- sc->component_depth = 10;
- break;
- case 1237:
- sc->index = INDEX_DNXHD_1080p_8bit_MEDIUM;
- break;
- case 1238:
- sc->index = INDEX_DNXHD_1080p_8bit_HIGH;
- break;
- case 1241:
- sc->index = INDEX_DNXHD_1080i_10bit_HIGH;
- sc->component_depth = 10;
- break;
- case 1242:
- sc->index = INDEX_DNXHD_1080i_8bit_MEDIUM;
- break;
- case 1243:
- sc->index = INDEX_DNXHD_1080i_8bit_HIGH;
- break;
- case 1250:
- sc->index = INDEX_DNXHD_720p_10bit;
- sc->component_depth = 10;
- break;
- case 1251:
- sc->index = INDEX_DNXHD_720p_8bit_HIGH;
- break;
- case 1252:
- sc->index = INDEX_DNXHD_720p_8bit_MEDIUM;
- break;
- case 1253:
- sc->index = INDEX_DNXHD_720p_8bit_LOW;
- break;
- case 1274:
- sc->index = INDEX_DNXHR_LB;
- break;
- case 1273:
- sc->index = INDEX_DNXHR_SQ;
- break;
- case 1272:
- sc->index = INDEX_DNXHR_HQ;
- break;
- case 1271:
- sc->index = INDEX_DNXHR_HQX;
- sc->component_depth = st->codecpar->bits_per_raw_sample;
- break;
- case 1270:
- sc->index = INDEX_DNXHR_444;
- sc->component_depth = st->codecpar->bits_per_raw_sample;
- break;
- default:
- return -1;
+ if (cid >= 1270) { // RI raster
+ av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
+ st->codecpar->width, st->codecpar->height,
+ INT_MAX);
+ } else {
+ sc->aspect_ratio = (AVRational){ 16, 9 };
}
- sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul;
- sc->aspect_ratio = (AVRational){ 16, 9 };
sc->frame_size = pkt->size;
return 1;
MXFContext *mxf = s->priv_data;
MXFStreamContext *sc = st->priv_data;
uint8_t *vs_pack, *vsc_pack;
- int i, ul_index, frame_size, stype, pal;
+ int ul_index, stype, pal;
const AVDVProfile *profile;
if (mxf->header_written)
switch (stype) {
case 0x18: // DV100 720p
ul_index = INDEX_DV100_720_50 + pal;
- frame_size = pal ? 288000 : 240000;
if (sc->interlaced) {
av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n");
sc->interlaced = 0;
break;
case 0x14: // DV100 1080i
ul_index = INDEX_DV100_1080_50 + pal;
- frame_size = pal ? 576000 : 480000;
break;
case 0x04: // DV50
ul_index = INDEX_DV50_525_60 + pal;
- frame_size = pal ? 288000 : 240000;
break;
default: // DV25
if (profile && profile->pix_fmt == AV_PIX_FMT_YUV420P && pal) {
ul_index = INDEX_DV25_525_60_IEC + pal;
- frame_size = pal ? 144000 : 120000;
break;
}
ul_index = INDEX_DV25_525_60 + pal;
- frame_size = pal ? 144000 : 120000;
}
sc->index = ul_index;
return !!sc->codec_ul;
}
-static uint64_t mxf_parse_timestamp(time_t timestamp)
+static uint64_t mxf_parse_timestamp(int64_t timestamp64)
{
+ time_t timestamp = timestamp64 / 1000000;
struct tm tmbuf;
struct tm *time = gmtime_r(×tamp, &tmbuf);
if (!time)
(uint64_t) time->tm_mday << 32 |
time->tm_hour << 24 |
time->tm_min << 16 |
- time->tm_sec << 8;
+ time->tm_sec << 8 |
+ (timestamp64 % 1000000) / 4000;
}
static void mxf_gen_umid(AVFormatContext *s)
sc->v_chroma_sub_sample = 2;
sc->color_siting = 0xFF;
+ if (st->codecpar->sample_aspect_ratio.num && st->codecpar->sample_aspect_ratio.den) {
+ sc->aspect_ratio = av_mul_q(st->codecpar->sample_aspect_ratio,
+ av_make_q(st->codecpar->width, st->codecpar->height));
+ }
+
if (pix_desc) {
sc->component_depth = pix_desc->comp[0].depth;
sc->h_chroma_sub_sample = 1 << pix_desc->log2_chroma_w;
sc->frame_size = (st->codecpar->channels * spf[0].samples_per_frame[0] *
av_get_bits_per_sample(st->codecpar->codec_id)) / 8;
}
+ } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
+ AVDictionaryEntry *e = av_dict_get(st->metadata, "data_type", NULL, 0);
+ if (e && !strcmp(e->value, "vbi_vanc_smpte_436M")) {
+ sc->index = INDEX_S436M;
+ } else {
+ av_log(s, AV_LOG_ERROR, "track %d: unsupported data type\n", i);
+ return -1;
+ }
+ if (st->index != s->nb_streams - 1) {
+ av_log(s, AV_LOG_ERROR, "data track must be placed last\n");
+ return -1;
+ }
}
if (!sc->index) {
sc->order = AV_RB32(sc->track_essence_element_key+12);
}
- if (ff_parse_creation_time_metadata(s, ×tamp, 1) > 0)
+ if (ff_parse_creation_time_metadata(s, ×tamp, 0) > 0)
mxf->timestamp = mxf_parse_timestamp(timestamp);
mxf->duration = -1;
AVIOContext *pb = s->pb;
unsigned frame;
uint32_t time_code;
+ int i, system_item_bitmap = 0x58; // UL, user date/time stamp, picture present
frame = mxf->last_indexed_edit_unit + mxf->edit_units_count;
// write system metadata pack
avio_write(pb, system_metadata_pack_key, 16);
klv_encode_ber4_length(pb, 57);
- avio_w8(pb, 0x5c); // UL, user date/time stamp, picture and sound item present
+
+ for (i = 0; i < s->nb_streams; i++) {
+ if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+ system_item_bitmap |= 0x4;
+ else if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_DATA)
+ system_item_bitmap |= 0x2;
+ }
+ avio_w8(pb, system_item_bitmap);
avio_w8(pb, mxf->content_package_rate); // content package rate
avio_w8(pb, 0x00); // content package type
avio_wb16(pb, 0x00); // channel handle
av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
return -1;
}
+ } else if (st->codecpar->codec_id == AV_CODEC_ID_PRORES) {
+ if (!mxf_parse_prores_frame(s, st, pkt)) {
+ av_log(s, AV_LOG_ERROR, "could not get prores profile\n");
+ return -1;
+ }
} else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
if (!mxf_parse_dv_frame(s, st, pkt)) {
av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
}
#define MXF_COMMON_OPTIONS \
- { "signal_standard", "Force/set Sigal Standard",\
+ { "signal_standard", "Force/set Signal Standard",\
offsetof(MXFContext, signal_standard), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
{ "bt601", "ITU-R BT.601 and BT.656, also SMPTE 125M (525 and 625 line interlaced)",\
0, AV_OPT_TYPE_CONST, {.i64 = 1}, -1, 7, AV_OPT_FLAG_ENCODING_PARAM, "signal_standard"},\
{ "mxf_audio_edit_rate", "Audio edit rate for timecode",
offsetof(MXFContext, audio_edit_rate), AV_OPT_TYPE_RATIONAL, {.dbl=25}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
MXF_COMMON_OPTIONS
+ { "store_user_comments", "",
+ offsetof(MXFContext, store_user_comments), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ NULL },
};