--- libavformat/mxf.c | 17 ++++ libavformat/mxf.h | 1 + libavformat/mxfenc.c | 181 +++++++++++++++++++++++++++++++++---------- 3 files changed, 156 insertions(+), 43 deletions(-)
diff --git a/libavformat/mxf.c b/libavformat/mxf.c index 36d662b58c..677d69e3ab 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -81,6 +81,8 @@ const MXFCodecUL ff_mxf_codec_uls[] = { const MXFCodecUL ff_mxf_pixel_format_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x01 }, 16, AV_PIX_FMT_UYVY422 }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x02 }, 16, AV_PIX_FMT_YUYV422 }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x03 }, 16, AV_PIX_FMT_YUV422P }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x03,0x01,0x02 }, 16, AV_PIX_FMT_YUV420P }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_PIX_FMT_NONE }, }; @@ -183,6 +185,21 @@ int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat * return -1; } +int ff_mxf_find_pixel_layout(const char** pixel_layout, const enum AVPixelFormat pix_fmt) +{ + int x; + *pixel_layout = NULL; + + for(x = 0; x < num_pixel_layouts; x++) { + if(ff_mxf_pixel_layouts[x].pix_fmt == pix_fmt) { + *pixel_layout = ff_mxf_pixel_layouts[x].data; + return 0; + } + } + + return -1; +} + /** * See SMPTE 326M-2000 Section 7.2 Content package rate * MXFContentPackageRate->rate is bits b5..b0. diff --git a/libavformat/mxf.h b/libavformat/mxf.h index fe9c52732c..fa4a4eb0d2 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -114,6 +114,7 @@ extern const MXFCodecUL ff_mxf_color_trc_uls[]; extern const MXFCodecUL ff_mxf_color_space_uls[]; int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt); +int ff_mxf_find_pixel_layout(const char** pixel_layout, const enum AVPixelFormat pix_fmt); int ff_mxf_get_content_package_rate(AVRational time_base); diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 5ec619675b..a2ec7b89d7 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -127,6 +127,8 @@ enum ULIndex { INDEX_H264, INDEX_S436M, INDEX_PRORES, + INDEX_RAWVIDEO, + INDEX_V210 }; static const struct { @@ -141,6 +143,8 @@ static const struct { { AV_CODEC_ID_JPEG2000, INDEX_JPEG2000 }, { AV_CODEC_ID_H264, INDEX_H264 }, { AV_CODEC_ID_PRORES, INDEX_PRORES }, + { AV_CODEC_ID_RAWVIDEO, INDEX_RAWVIDEO }, + { AV_CODEC_ID_V210, INDEX_V210 }, { AV_CODEC_ID_NONE } }; @@ -148,6 +152,7 @@ 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_or_rgba_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); @@ -205,6 +210,16 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { { 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 }, + // RawVideo + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, // MXF-GC Uncompressed Pictures + { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 }, // GC Picture Essence + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, // Uncompressed + mxf_write_cdci_or_rgba_desc }, + // V210 + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, // MXF-GC Uncompressed Pictures + { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 }, // GC Picture Essence + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x02,0x01 }, // V210 + 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 }, @@ -346,6 +361,8 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = { { 0x3304, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x03,0x03,0x00,0x00,0x00}}, /* Black Ref level */ { 0x3305, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x03,0x04,0x00,0x00,0x00}}, /* White Ref level */ { 0x3306, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x03,0x05,0x00,0x00,0x00}}, /* Color Range */ + // RGBA Picture Essence Descriptor + { 0x3401, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x03,0x06,0x00,0x00,0x00}}, /* Pixel Layout */ // Generic Sound Essence Descriptor { 0x3D02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Locked/Unlocked */ { 0x3D03, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x01,0x01,0x01,0x00,0x00}}, /* Audio sampling rate */ @@ -1047,7 +1064,7 @@ static void mxf_write_multi_descriptor(AVFormatContext *s) mxf_write_uuid(pb, SubDescriptor, i); } -static int64_t mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key) +static int64_t mxf_write_file_desc(AVFormatContext *s, AVStream *st, const UID key) { MXFContext *mxf = s->priv_data; MXFStreamContext *sc = st->priv_data; @@ -1090,6 +1107,7 @@ static const UID mxf_mpegvideo_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53, 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 }; 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_rgba_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x29,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 }; @@ -1104,7 +1122,7 @@ static inline uint32_t rescale_mastering_luma(AVRational q) return av_rescale(q.num, FF_MXF_MASTERING_LUMA_DEN, q.den); } -static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key) +static int64_t mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UID key) { MXFStreamContext *sc = st->priv_data; AVIOContext *pb = s->pb; @@ -1115,7 +1133,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID const MXFCodecUL *color_primaries_ul; const MXFCodecUL *color_trc_ul; const MXFCodecUL *color_space_ul; - int64_t pos = mxf_write_generic_desc(s, st, key); + int64_t pos = mxf_write_file_desc(s, st, key); uint8_t *side_data; color_primaries_ul = mxf_get_codec_ul_by_id(ff_mxf_color_primaries_uls, st->codecpar->color_primaries); @@ -1131,6 +1149,8 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID if (!stored_width) stored_width = (st->codecpar->width+15)/16*16; + // TODO: V210 ==> Stored Width shall be a multiple of 48. + mxf_write_local_tag(s, 4, 0x3203); avio_wb32(pb, stored_width); @@ -1194,43 +1214,6 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID avio_wb32(pb, -((st->codecpar->height - display_height)&1)); } - // component depth - mxf_write_local_tag(s, 4, 0x3301); - avio_wb32(pb, sc->component_depth); - - // horizontal subsampling - mxf_write_local_tag(s, 4, 0x3302); - avio_wb32(pb, sc->h_chroma_sub_sample); - - // vertical subsampling - mxf_write_local_tag(s, 4, 0x3308); - avio_wb32(pb, sc->v_chroma_sub_sample); - - // color siting - mxf_write_local_tag(s, 1, 0x3303); - avio_w8(pb, sc->color_siting); - - // Padding Bits - mxf_write_local_tag(s, 2, 0x3307); - avio_wb16(pb, 0); - - if (st->codecpar->color_range != AVCOL_RANGE_UNSPECIFIED) { - int black = 0, - white = (1<<sc->component_depth) - 1, - color = (1<<sc->component_depth); - if (st->codecpar->color_range == AVCOL_RANGE_MPEG) { - black = 1 << (sc->component_depth - 4); - white = 235 << (sc->component_depth - 8); - color = (14 << (sc->component_depth - 4)) + 1; - } - mxf_write_local_tag(s, 4, 0x3304); - avio_wb32(pb, black); - mxf_write_local_tag(s, 4, 0x3305); - avio_wb32(pb, white); - mxf_write_local_tag(s, 4, 0x3306); - avio_wb32(pb, color); - } - if (sc->signal_standard) { mxf_write_local_tag(s, 1, 0x3215); avio_w8(pb, sc->signal_standard); @@ -1256,7 +1239,6 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID f1 *= 2; } - mxf_write_local_tag(s, 16, 0x320D); avio_wb32(pb, 2); avio_wb32(pb, 4); @@ -1328,6 +1310,52 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID return pos; } +static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key) +{ + MXFStreamContext *sc = st->priv_data; + AVIOContext *pb = s->pb; + int64_t pos = mxf_write_generic_desc(s, st, key); + + // component depth + mxf_write_local_tag(s, 4, 0x3301); + avio_wb32(pb, sc->component_depth); + + // horizontal subsampling + mxf_write_local_tag(s, 4, 0x3302); + avio_wb32(pb, sc->h_chroma_sub_sample); + + // vertical subsampling + mxf_write_local_tag(s, 4, 0x3308); + avio_wb32(pb, sc->v_chroma_sub_sample); + + // color siting + mxf_write_local_tag(s, 1, 0x3303); + avio_w8(pb, sc->color_siting); + + // Padding Bits + mxf_write_local_tag(s, 2, 0x3307); + avio_wb16(pb, 0); + + if (st->codecpar->color_range != AVCOL_RANGE_UNSPECIFIED) { + int black = 0, + white = (1<<sc->component_depth) - 1, + color = (1<<sc->component_depth); + if (st->codecpar->color_range == AVCOL_RANGE_MPEG) { + black = 1 << (sc->component_depth - 4); + white = 235 << (sc->component_depth - 8); + color = (14 << (sc->component_depth - 4)) + 1; + } + mxf_write_local_tag(s, 4, 0x3304); + avio_wb32(pb, black); + mxf_write_local_tag(s, 4, 0x3305); + avio_wb32(pb, white); + mxf_write_local_tag(s, 4, 0x3306); + avio_wb32(pb, color); + } + + return pos; +} + static void mxf_update_klv_size(AVIOContext *pb, int64_t pos) { int64_t cur_pos = avio_tell(pb); @@ -1361,6 +1389,32 @@ static void mxf_write_avc_subdesc(AVFormatContext *s, AVStream *st) mxf_update_klv_size(s->pb, pos); } +static void mxf_write_cdci_or_rgba_desc(AVFormatContext *s, AVStream *st) +{ + AVIOContext *pb = s->pb; + const char* pixelLayoutData = NULL; + int64_t pos; + + if(ff_mxf_find_pixel_layout(&pixelLayoutData, st->codecpar->format) >= 0) + { + pos = mxf_write_generic_desc(s, st, mxf_rgba_descriptor_key); + + // pixel layout + mxf_write_local_tag(s, 16, 0x3401); + avio_write(pb, pixelLayoutData, 16); + + mxf_update_klv_size(s->pb, pos); + return; + } + + 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_cdci_desc(AVFormatContext *s, AVStream *st) { int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key); @@ -1385,7 +1439,7 @@ static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st) 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); + int64_t pos = mxf_write_file_desc(s, st, mxf_s436m_anc_descriptor_key); mxf_update_klv_size(s->pb, pos); } @@ -1432,7 +1486,7 @@ static int64_t mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, AVIOContext *pb = s->pb; MXFContext *mxf = s->priv_data; int show_warnings = !mxf->footer_partition_offset; - int64_t pos = mxf_write_generic_desc(s, st, key); + int64_t pos = mxf_write_file_desc(s, st, key); if (s->oformat == &ff_mxf_opatom_muxer) { mxf_write_local_tag(s, 8, 0x3002); @@ -2348,6 +2402,42 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, return 1; } +static int mxf_parse_raw_frame(AVFormatContext *s, AVStream *st, + AVPacket *pkt, MXFIndexEntry *e) +{ + MXFContext *mxf = s->priv_data; + MXFStreamContext *sc = st->priv_data; + const MXFCodecUL* uls = ff_mxf_pixel_format_uls; + const char* pixelLayoutData = NULL; + int format; + + if (mxf->header_written) + return 1; + + format = st->codecpar->format; + + if(ff_mxf_find_pixel_layout(&pixelLayoutData, format) < 0) + { + while (uls->uid[0]) { + if (format == uls->id) { + sc->codec_ul = &uls->uid; + break; + } + uls++; + } + + if (!uls->uid[0]) + { + av_log(s, AV_LOG_ERROR, "no codec ul available for pixel format %s\n", av_get_pix_fmt_name(format)); + return 0; + } + } + + sc->frame_size = pkt->size; + + return 1; +} + static const UID mxf_mpeg2_codec_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP @@ -2929,6 +3019,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "could not get h264 profile\n"); return -1; } + } else if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { + if (!mxf_parse_raw_frame(s, st, pkt, &ie)) { + av_log(s, AV_LOG_ERROR, "could not get raw profile\n"); + return -1; + } } if (mxf->cbr_index) { -- 2.20.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".