|
|
|
@ -49,12 +49,14 @@ |
|
|
|
|
#include "libavcodec/bytestream.h" |
|
|
|
|
#include "libavcodec/dnxhddata.h" |
|
|
|
|
#include "libavcodec/dv_profile.h" |
|
|
|
|
#include "libavcodec/h264.h" |
|
|
|
|
#include "libavcodec/h264_ps.h" |
|
|
|
|
#include "libavcodec/golomb.h" |
|
|
|
|
#include "libavcodec/internal.h" |
|
|
|
|
#include "audiointerleave.h" |
|
|
|
|
#include "avformat.h" |
|
|
|
|
#include "avio_internal.h" |
|
|
|
|
#include "internal.h" |
|
|
|
|
#include "avc.h" |
|
|
|
|
#include "mxf.h" |
|
|
|
|
#include "config.h" |
|
|
|
|
|
|
|
|
@ -99,6 +101,7 @@ typedef struct MXFStreamContext { |
|
|
|
|
int max_gop; ///< maximum gop size, used by mpeg-2 descriptor
|
|
|
|
|
int b_picture_count; ///< maximum number of consecutive b pictures, used in mpeg-2 descriptor
|
|
|
|
|
int low_delay; ///< low delay, used in mpeg-2 descriptor
|
|
|
|
|
int avc_intra; |
|
|
|
|
} MXFStreamContext; |
|
|
|
|
|
|
|
|
|
typedef struct MXFContainerEssenceEntry { |
|
|
|
@ -167,6 +170,7 @@ static const struct { |
|
|
|
|
static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st); |
|
|
|
|
static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st); |
|
|
|
|
static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st); |
|
|
|
|
static void mxf_write_h264_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); |
|
|
|
@ -310,7 +314,7 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { |
|
|
|
|
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, |
|
|
|
|
{ 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 }, |
|
|
|
|
mxf_write_h264_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 }, |
|
|
|
@ -503,6 +507,13 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = { |
|
|
|
|
{ 0x3D0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x02,0x01,0x00,0x00,0x00}}, /* Block Align */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const MXFLocalTagPair mxf_avc_subdescriptor_local_tags[] = { |
|
|
|
|
{ 0x8100, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00}}, /* SubDescriptors */ |
|
|
|
|
{ 0x8200, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0E,0x00,0x00}}, /* AVC Decoding Delay */ |
|
|
|
|
{ 0x8201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0A,0x00,0x00}}, /* AVC Profile */ |
|
|
|
|
{ 0x8202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0D,0x00,0x00}}, /* AVC Level */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const MXFLocalTagPair mxf_user_comments_local_tag[] = { |
|
|
|
|
{ 0x4406, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0C,0x00,0x00,0x00}}, /* User Comments */ |
|
|
|
|
{ 0x5001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x09,0x01,0x00,0x00}}, /* Name */ |
|
|
|
@ -584,15 +595,33 @@ static int mxf_get_essence_container_ul_index(enum AVCodecID id) |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_local_tags(AVIOContext *pb, const MXFLocalTagPair *local_tags, int count) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
|
avio_wb16(pb, local_tags[i].local_tag); |
|
|
|
|
avio_write(pb, local_tags[i].uid, 16); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_primer_pack(AVFormatContext *s) |
|
|
|
|
{ |
|
|
|
|
MXFContext *mxf = s->priv_data; |
|
|
|
|
AVIOContext *pb = s->pb; |
|
|
|
|
int local_tag_number, i = 0; |
|
|
|
|
int avc_tags_count = 0; |
|
|
|
|
|
|
|
|
|
local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch); |
|
|
|
|
local_tag_number += mxf->store_user_comments * FF_ARRAY_ELEMS(mxf_user_comments_local_tag); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < s->nb_streams; i++) { |
|
|
|
|
MXFStreamContext *sc = s->streams[i]->priv_data; |
|
|
|
|
if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) { |
|
|
|
|
avc_tags_count = FF_ARRAY_ELEMS(mxf_avc_subdescriptor_local_tags); |
|
|
|
|
local_tag_number += avc_tags_count; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
avio_write(pb, primer_pack_key, 16); |
|
|
|
|
klv_encode_ber_length(pb, local_tag_number * 18 + 8); |
|
|
|
|
|
|
|
|
@ -608,6 +637,8 @@ static void mxf_write_primer_pack(AVFormatContext *s) |
|
|
|
|
avio_wb16(pb, mxf_user_comments_local_tag[i].local_tag); |
|
|
|
|
avio_write(pb, mxf_user_comments_local_tag[i].uid, 16); |
|
|
|
|
} |
|
|
|
|
if (avc_tags_count > 0) |
|
|
|
|
mxf_write_local_tags(pb, mxf_avc_subdescriptor_local_tags, avc_tags_count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_local_tag(AVIOContext *pb, int size, int tag) |
|
|
|
@ -1126,6 +1157,8 @@ static const UID mxf_aes3_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53, |
|
|
|
|
static const UID mxf_cdci_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }; |
|
|
|
|
static const UID mxf_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }; |
|
|
|
|
|
|
|
|
|
static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 }; |
|
|
|
|
|
|
|
|
|
static int get_trc(UID ul, enum AVColorTransferCharacteristic trc) |
|
|
|
|
{ |
|
|
|
|
switch (trc){ |
|
|
|
@ -1317,6 +1350,13 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID |
|
|
|
|
avio_w8(pb, sc->field_dominance); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) { |
|
|
|
|
// write avc sub descriptor ref
|
|
|
|
|
mxf_write_local_tag(pb, 8 + 16, 0x8100); |
|
|
|
|
mxf_write_refs_count(pb, 1); |
|
|
|
|
mxf_write_uuid(pb, AVCSubDescriptor, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return pos; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1329,10 +1369,50 @@ static void mxf_update_klv_size(AVIOContext *pb, int64_t pos) |
|
|
|
|
avio_seek(pb, cur_pos, SEEK_SET); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_avc_subdesc(AVFormatContext *s, AVStream *st) |
|
|
|
|
{ |
|
|
|
|
AVIOContext *pb = s->pb; |
|
|
|
|
int64_t pos; |
|
|
|
|
|
|
|
|
|
avio_write(pb, mxf_avc_subdescriptor_key, 16); |
|
|
|
|
klv_encode_ber4_length(pb, 0); |
|
|
|
|
pos = avio_tell(pb); |
|
|
|
|
|
|
|
|
|
mxf_write_local_tag(pb, 16, 0x3C0A); |
|
|
|
|
mxf_write_uuid(pb, AVCSubDescriptor, 0); |
|
|
|
|
|
|
|
|
|
mxf_write_local_tag(pb, 1, 0x8200); |
|
|
|
|
avio_w8(pb, 0xFF); // AVC Decoding Delay, unknown
|
|
|
|
|
|
|
|
|
|
mxf_write_local_tag(pb, 1, 0x8201); |
|
|
|
|
avio_w8(pb, st->codecpar->profile); // AVC Profile
|
|
|
|
|
|
|
|
|
|
mxf_write_local_tag(pb, 1, 0x8202); |
|
|
|
|
avio_w8(pb, st->codecpar->level); // AVC Level
|
|
|
|
|
|
|
|
|
|
mxf_update_klv_size(s->pb, pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st) |
|
|
|
|
{ |
|
|
|
|
int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key); |
|
|
|
|
mxf_update_klv_size(s->pb, pos); |
|
|
|
|
|
|
|
|
|
if (st->codecpar->codec_id == AV_CODEC_ID_H264) { |
|
|
|
|
mxf_write_avc_subdesc(s, st); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st) |
|
|
|
|
{ |
|
|
|
|
MXFStreamContext *sc = st->priv_data; |
|
|
|
|
if (sc->avc_intra) { |
|
|
|
|
mxf_write_mpegvideo_desc(s, st); |
|
|
|
|
} else { |
|
|
|
|
int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key); |
|
|
|
|
mxf_update_klv_size(s->pb, pos); |
|
|
|
|
mxf_write_avc_subdesc(s, st); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st) |
|
|
|
@ -2136,30 +2216,30 @@ static const struct { |
|
|
|
|
int frame_size; |
|
|
|
|
int profile; |
|
|
|
|
uint8_t interlaced; |
|
|
|
|
int long_gop; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored
|
|
|
|
|
int intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored
|
|
|
|
|
} mxf_h264_codec_uls[] = { |
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 0, 66, 0, -1 }, // AVC Baseline, Unconstrained Coding
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 0, 66, 0, -1 }, // AVC Baseline
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x20,0x01 }, 0, 77, 0, -1 }, // AVC Main
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x30,0x01 }, 0, 88, 0, -1 }, // AVC Extended
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x40,0x01 }, 0, 100, 0, -1 }, // AVC High
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01 }, 0, 110, 0, 1 }, // AVC High 10
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01 }, 0, 122, 0, 1 }, // AVC High 422
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01 }, 0, 244, 0, 1 }, // AVC High 444
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 }, 0, 110, 0, 0 }, // AVC High 10 Intra
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960, 0, 1, 0 }, // AVC Intra 50 1080i60
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088, 0, 1, 0 }, // AVC Intra 50 1080i50
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960, 0, 0, 0 }, // AVC Intra 50 1080p30
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 281088, 0, 0, 0 }, // AVC Intra 50 1080p25
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736, 0, 0, 0 }, // AVC Intra 50 720p60
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, 140800, 0, 0, 0 }, // AVC Intra 50 720p50
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 }, 0, 122, 0, 0 }, // AVC High 422 Intra
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576, 0, 1, 0 }, // AVC Intra 100 1080i60
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832, 0, 1, 0 }, // AVC Intra 100 1080i50
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576, 0, 0, 0 }, // AVC Intra 100 1080p30
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, 568832, 0, 0, 0 }, // AVC Intra 100 1080p25
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544, 0, 0, 0 }, // AVC Intra 100 720p60
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, 284672, 0, 0, 0 }, // AVC Intra 100 720p50
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01 }, 0, 244, 0, 0 }, // AVC High 444 Intra
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01 }, 0, 110, 0, 0 }, // AVC High 10
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01 }, 0, 122, 0, 0 }, // AVC High 422
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01 }, 0, 244, 0, 0 }, // AVC High 444
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 }, 0, 110, 0, 1 }, // AVC High 10 Intra
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960, 110, 1, 1 }, // AVC High 10 Intra RP2027 Class 50 1080/59.94i
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088, 110, 1, 1 }, // AVC High 10 Intra RP2027 Class 50 1080/50i
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960, 110, 0, 1 }, // AVC High 10 Intra RP2027 Class 50 1080/29.97p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 281088, 110, 0, 1 }, // AVC High 10 Intra RP2027 Class 50 1080/25p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736, 110, 0, 1 }, // AVC High 10 Intra RP2027 Class 50 720/59.94p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, 140800, 110, 0, 1 }, // AVC High 10 Intra RP2027 Class 50 720/50p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 }, 0, 122, 0, 1 }, // AVC High 422 Intra
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576, 122, 1, 1 }, // AVC High 422 Intra RP2027 Class 100 1080/59.94i
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832, 122, 1, 1 }, // AVC High 422 Intra RP2027 Class 100 1080/50i
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576, 122, 0, 1 }, // AVC High 422 Intra RP2027 Class 100 1080/29.97p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, 568832, 122, 0, 1 }, // AVC High 422 Intra RP2027 Class 100 1080/25p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544, 122, 0, 1 }, // AVC High 422 Intra RP2027 Class 100 720/59.94p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, 284672, 122, 0, 1 }, // AVC High 422 Intra RP2027 Class 100 720/50p
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01 }, 0, 244, 0, 1 }, // AVC High 444 Intra
|
|
|
|
|
{{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x50,0x01 }, 0, 44, 0, -1 }, // AVC CAVLC 444
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -2168,37 +2248,70 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, |
|
|
|
|
{ |
|
|
|
|
MXFContext *mxf = s->priv_data; |
|
|
|
|
MXFStreamContext *sc = st->priv_data; |
|
|
|
|
AVCodecParameters *par = st->codecpar; |
|
|
|
|
static const int mxf_h264_num_codec_uls = sizeof(mxf_h264_codec_uls) / sizeof(mxf_h264_codec_uls[0]); |
|
|
|
|
H264SequenceParameterSet *sps = NULL; |
|
|
|
|
GetBitContext gb; |
|
|
|
|
const uint8_t *buf = pkt->data; |
|
|
|
|
const uint8_t *buf_end = pkt->data + pkt->size; |
|
|
|
|
const uint8_t *nal_end; |
|
|
|
|
uint32_t state = -1; |
|
|
|
|
int long_gop = 0; // assume intra when there is no SPS header
|
|
|
|
|
int extra_size = 512; // support AVC Intra files without SPS/PPS header
|
|
|
|
|
int i, frame_size; |
|
|
|
|
uint8_t uid_found; |
|
|
|
|
|
|
|
|
|
if (pkt->size > extra_size) |
|
|
|
|
buf_end -= pkt->size - extra_size; // no need to parse beyond SPS/PPS header
|
|
|
|
|
int i, frame_size, slice_type, intra_only = 0; |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
buf = avpriv_find_start_code(buf, buf_end, &state); |
|
|
|
|
if (buf >= buf_end) |
|
|
|
|
break; |
|
|
|
|
--buf; |
|
|
|
|
|
|
|
|
|
switch (state & 0x1f) { |
|
|
|
|
case H264_NAL_SPS: |
|
|
|
|
par->profile = buf[1]; |
|
|
|
|
long_gop = buf[2] & 0x10 ? 0 : 1; // constraint_set3_flag signals intra
|
|
|
|
|
e->flags |= 0x40; |
|
|
|
|
|
|
|
|
|
if (mxf->header_written) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
nal_end = ff_avc_find_startcode(buf, buf_end); |
|
|
|
|
sps = ff_avc_decode_sps(buf, nal_end - buf); |
|
|
|
|
if (!sps) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, "error parsing sps\n"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sc->aspect_ratio.num = st->codecpar->width * sps->sar.num; |
|
|
|
|
sc->aspect_ratio.den = st->codecpar->height * sps->sar.den; |
|
|
|
|
av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, |
|
|
|
|
sc->aspect_ratio.num, sc->aspect_ratio.den, 1024*1024); |
|
|
|
|
intra_only = (sps->constraint_set_flags >> 3) & 1; |
|
|
|
|
sc->interlaced = !sps->frame_mbs_only_flag; |
|
|
|
|
sc->component_depth = sps->bit_depth_luma; |
|
|
|
|
|
|
|
|
|
buf = nal_end; |
|
|
|
|
break; |
|
|
|
|
case H264_NAL_PPS: |
|
|
|
|
if (e->flags & 0x40) { // sequence header present
|
|
|
|
|
e->flags |= 0x80; // random access
|
|
|
|
|
extra_size = 0; |
|
|
|
|
buf = buf_end; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case H264_NAL_IDR_SLICE: |
|
|
|
|
e->flags |= 0x04; // IDR Picture
|
|
|
|
|
buf = buf_end; |
|
|
|
|
break; |
|
|
|
|
case H264_NAL_SLICE: |
|
|
|
|
init_get_bits8(&gb, buf, buf_end - buf); |
|
|
|
|
get_ue_golomb_long(&gb); // skip first_mb_in_slice
|
|
|
|
|
slice_type = get_ue_golomb_31(&gb); |
|
|
|
|
switch (slice_type % 5) { |
|
|
|
|
case 0: |
|
|
|
|
e->flags |= 0x20; // P Picture
|
|
|
|
|
e->flags |= 0x06; // P Picture
|
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
e->flags |= 0x30; // B Picture
|
|
|
|
|
e->flags |= 0x03; // non-referenced B Picture
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
buf = buf_end; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -2207,27 +2320,37 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, |
|
|
|
|
if (mxf->header_written) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
|
|
|
|
|
sc->interlaced = par->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0; |
|
|
|
|
|
|
|
|
|
uid_found = 0; |
|
|
|
|
if (!sps) |
|
|
|
|
sc->interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0; |
|
|
|
|
sc->codec_ul = NULL; |
|
|
|
|
frame_size = pkt->size + extra_size; |
|
|
|
|
for (i = 0; i < mxf_h264_num_codec_uls; i++) { |
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(mxf_h264_codec_uls); i++) { |
|
|
|
|
if (frame_size == mxf_h264_codec_uls[i].frame_size && sc->interlaced == mxf_h264_codec_uls[i].interlaced) { |
|
|
|
|
sc->codec_ul = &mxf_h264_codec_uls[i].uid; |
|
|
|
|
sc->component_depth = 10; // AVC Intra is always 10 Bit
|
|
|
|
|
sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
|
|
|
|
|
st->codecpar->profile = mxf_h264_codec_uls[i].profile; |
|
|
|
|
sc->avc_intra = 1; |
|
|
|
|
mxf->cbr_index = 1; |
|
|
|
|
sc->frame_size = pkt->size; |
|
|
|
|
if (sc->interlaced) |
|
|
|
|
sc->field_dominance = 1; // top field first is mandatory for AVC Intra
|
|
|
|
|
return 1; |
|
|
|
|
} else if ((mxf_h264_codec_uls[i].profile == par->profile) && |
|
|
|
|
((mxf_h264_codec_uls[i].long_gop < 0) || |
|
|
|
|
(mxf_h264_codec_uls[i].long_gop == long_gop))) { |
|
|
|
|
break; |
|
|
|
|
} else if (sps && mxf_h264_codec_uls[i].frame_size == 0 && |
|
|
|
|
mxf_h264_codec_uls[i].profile == sps->profile_idc && |
|
|
|
|
(mxf_h264_codec_uls[i].intra_only < 0 || |
|
|
|
|
mxf_h264_codec_uls[i].intra_only == intra_only)) { |
|
|
|
|
sc->codec_ul = &mxf_h264_codec_uls[i].uid; |
|
|
|
|
uid_found = 1; |
|
|
|
|
st->codecpar->profile = sps->profile_idc; |
|
|
|
|
st->codecpar->level = sps->level_idc; |
|
|
|
|
// continue to check for avc intra
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!uid_found) { |
|
|
|
|
av_free(sps); |
|
|
|
|
|
|
|
|
|
if (!sc->codec_ul) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, "h264 profile not supported\n"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|