|
|
|
@ -39,6 +39,7 @@ |
|
|
|
|
#include "libavutil/random_seed.h" |
|
|
|
|
#include "libavutil/timecode.h" |
|
|
|
|
#include "libavcodec/bytestream.h" |
|
|
|
|
#include "libavcodec/dnxhddata.h" |
|
|
|
|
#include "audiointerleave.h" |
|
|
|
|
#include "avformat.h" |
|
|
|
|
#include "internal.h" |
|
|
|
@ -75,6 +76,7 @@ typedef struct { |
|
|
|
|
int order; ///< interleaving order if dts are equal
|
|
|
|
|
int interlaced; ///< whether picture is interlaced
|
|
|
|
|
int field_dominance; ///< tff=1, bff=2
|
|
|
|
|
int component_depth; |
|
|
|
|
int temporal_reordering; |
|
|
|
|
AVRational aspect_ratio; ///< display aspect ratio
|
|
|
|
|
int closed_gop; ///< gop is closed, used in mpeg-2 frame parsing
|
|
|
|
@ -95,6 +97,7 @@ static const struct { |
|
|
|
|
{ CODEC_ID_PCM_S24LE, 1 }, |
|
|
|
|
{ CODEC_ID_PCM_S16LE, 1 }, |
|
|
|
|
{ CODEC_ID_DVVIDEO, 15 }, |
|
|
|
|
{ CODEC_ID_DNXHD, 24 }, |
|
|
|
|
{ CODEC_ID_NONE } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -216,6 +219,56 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { |
|
|
|
|
{ 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
|
|
|
|
|
{ { 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,0x01,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,0x01,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,0x01,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,0x01,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,0x01,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,0x01,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,0x01,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,0x01,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,0x01,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,0x01,0x04,0x01,0x02,0x02,0x71,0x13,0x00,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 }, |
|
|
|
@ -865,7 +918,7 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke |
|
|
|
|
|
|
|
|
|
// component depth
|
|
|
|
|
mxf_write_local_tag(pb, 4, 0x3301); |
|
|
|
|
avio_wb32(pb, 8); |
|
|
|
|
avio_wb32(pb, sc->component_depth); |
|
|
|
|
|
|
|
|
|
// horizontal subsampling
|
|
|
|
|
mxf_write_local_tag(pb, 4, 0x3302); |
|
|
|
@ -1338,6 +1391,83 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, |
|
|
|
|
avio_flush(pb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
uint8_t* header_cid; |
|
|
|
|
unsigned int frame_size = 0; |
|
|
|
|
|
|
|
|
|
if (mxf->header_written) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
if (pkt->size < 43) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
header_cid = pkt->data + 0x28; |
|
|
|
|
cid = header_cid[0] << 24 | header_cid[1] << 16 | header_cid[2] << 8 | header_cid[3]; |
|
|
|
|
|
|
|
|
|
if ((i = ff_dnxhd_get_cid_table(cid)) < 0) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
switch (cid) { |
|
|
|
|
case 1235: |
|
|
|
|
sc->index = 24; |
|
|
|
|
sc->component_depth = 10; |
|
|
|
|
break; |
|
|
|
|
case 1237: |
|
|
|
|
sc->index = 25; |
|
|
|
|
break; |
|
|
|
|
case 1238: |
|
|
|
|
sc->index = 26; |
|
|
|
|
break; |
|
|
|
|
case 1241: |
|
|
|
|
sc->index = 27; |
|
|
|
|
sc->component_depth = 10; |
|
|
|
|
break; |
|
|
|
|
case 1242: |
|
|
|
|
sc->index = 28; |
|
|
|
|
break; |
|
|
|
|
case 1243: |
|
|
|
|
sc->index = 29; |
|
|
|
|
break; |
|
|
|
|
case 1250: |
|
|
|
|
sc->index = 30; |
|
|
|
|
sc->component_depth = 10; |
|
|
|
|
break; |
|
|
|
|
case 1251: |
|
|
|
|
sc->index = 31; |
|
|
|
|
break; |
|
|
|
|
case 1252: |
|
|
|
|
sc->index = 32; |
|
|
|
|
break; |
|
|
|
|
case 1253: |
|
|
|
|
sc->index = 33; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
frame_size = ff_dnxhd_cid_table[i].frame_size; |
|
|
|
|
|
|
|
|
|
mxf->edit_unit_byte_count = KAG_SIZE; |
|
|
|
|
for (i = 0; i < s->nb_streams; i++) { |
|
|
|
|
AVStream *st = s->streams[i]; |
|
|
|
|
MXFStreamContext *sc = st->priv_data; |
|
|
|
|
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
|
|
|
|
mxf->edit_unit_byte_count += 16 + 4 + sc->aic.samples[0]*sc->aic.sample_size; |
|
|
|
|
mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count); |
|
|
|
|
} else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
|
|
|
|
mxf->edit_unit_byte_count += 16 + 4 + frame_size; |
|
|
|
|
mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) |
|
|
|
|
{ |
|
|
|
|
MXFContext *mxf = s->priv_data; |
|
|
|
@ -1551,6 +1681,8 @@ static int mxf_write_header(AVFormatContext *s) |
|
|
|
|
|
|
|
|
|
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
|
|
|
|
AVRational rate; |
|
|
|
|
// Default component depth to 8
|
|
|
|
|
sc->component_depth = 8; |
|
|
|
|
if (fabs(av_q2d(st->codec->time_base) - 1/25.0) < 0.0001) { |
|
|
|
|
samples_per_frame = PAL_samples_per_frame; |
|
|
|
|
mxf->time_base = (AVRational){ 1, 25 }; |
|
|
|
@ -1811,6 +1943,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} else if (st->codec->codec_id == CODEC_ID_DNXHD) { |
|
|
|
|
if (!mxf_parse_dnxhd_frame(s, st, pkt)) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} else if (st->codec->codec_id == CODEC_ID_DVVIDEO) { |
|
|
|
|
if (!mxf_parse_dv_frame(s, st, pkt)) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, "could not get dv profile\n"); |
|
|
|
|