When muxing to Matroska, write the Block Additional Mapping if there is AV_PKT_DATA_DOVI_CONF side data present. Most of the code was implemented by Plex developers.
Since the type (dvcC/dvvC) can change depending on the caller, the logic was separated from ff_isom_put_dvcc_dvvc. In this case, movenc uses MKTAG while matroskaenc uses MKBETAG. This would allow refactoring movenc in the future. Signed-off-by: quietvoid <tcchlis...@gmail.com> --- libavformat/Makefile | 2 +- libavformat/dovi_isom.c | 40 ++++++++++++++++++++++++++++++++++++ libavformat/dovi_isom.h | 6 ++++++ libavformat/matroskaenc.c | 43 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 61a1fecf6c..680030014d 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -317,7 +317,7 @@ OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ av1.o avc.o hevc.o isom_tags.o \ flacenc_header.o avlanguage.o \ - vorbiscomment.o wv.o + vorbiscomment.o wv.o dovi_isom.o OBJS-$(CONFIG_MCA_DEMUXER) += mca.o OBJS-$(CONFIG_MCC_DEMUXER) += mccdec.o subtitles.o OBJS-$(CONFIG_MD5_MUXER) += hashenc.o diff --git a/libavformat/dovi_isom.c b/libavformat/dovi_isom.c index 2c0a49c993..747ffc8b2c 100644 --- a/libavformat/dovi_isom.c +++ b/libavformat/dovi_isom.c @@ -21,6 +21,8 @@ #include "libavutil/dovi_meta.h" +#include "libavcodec/put_bits.h" + #include "avformat.h" #include "dovi_isom.h" @@ -78,3 +80,41 @@ int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf return 0; } + +int ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], uint64_t size, + AVDOVIDecoderConfigurationRecord *dovi) +{ + PutBitContext pb; + init_put_bits(&pb, out, size); + + if (size < ISOM_DVCC_DVVC_SIZE) + return AVERROR(EINVAL); + + put_bits(&pb, 8, dovi->dv_version_major); + put_bits(&pb, 8, dovi->dv_version_minor); + put_bits(&pb, 7, dovi->dv_profile); + put_bits(&pb, 6, dovi->dv_level); + put_bits(&pb, 1, dovi->rpu_present_flag); + put_bits(&pb, 1, dovi->el_present_flag); + put_bits(&pb, 1, dovi->bl_present_flag); + put_bits(&pb, 4, dovi->dv_bl_signal_compatibility_id); + + put_bits(&pb, 28, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + flush_put_bits(&pb); + + av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_profile > 7 ? "dvvC" : "dvcC", + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); + + return put_bytes_output(&pb); +} diff --git a/libavformat/dovi_isom.h b/libavformat/dovi_isom.h index 4c313046a7..8ff59ef495 100644 --- a/libavformat/dovi_isom.h +++ b/libavformat/dovi_isom.h @@ -22,8 +22,14 @@ #ifndef AVFORMAT_DOVI_ISOM_H #define AVFORMAT_DOVI_ISOM_H +#include "libavutil/dovi_meta.h" + #include "avformat.h" +#define ISOM_DVCC_DVVC_SIZE 24 + int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size); +int ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], uint64_t size, + AVDOVIDecoderConfigurationRecord *dovi); #endif /* AVFORMAT_DOVI_ISOM_H */ diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 039f20988a..067474d8ed 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -54,6 +54,8 @@ #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" +#include "libavformat/dovi_isom.h" + /* Level 1 elements we create a SeekHead entry for: * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */ #define MAX_SEEKHEAD_ENTRIES 7 @@ -1115,6 +1117,41 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; } +static int mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) +{ + int ret; + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) + av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); + + if (dovi) { + ebml_master mapping; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + uint32_t type; + + uint64_t size; + uint64_t expected_size = (2 + 1 + (sizeof("Dolby Vision configuration") - 1)) + + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE); + + if ((ret = ff_isom_put_dvcc_dvvc(s, buf, sizeof(buf), dovi)) < 0) + return ret; + + size = ret; + + if (dovi->dv_profile > 7) + type = MKBETAG('d', 'v', 'v', 'C'); + else + type = MKBETAG('d', 'v', 'c', 'C'); + + mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, expected_size); + put_ebml_string(pb, MATROSKA_ID_BLKADDIDNAME, "Dolby Vision configuration"); + put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type); + put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, size); + end_ebml_master(pb, mapping); + } + + return 0; +} + static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, AVStream *st, mkv_track *track, AVIOContext *pb, int is_default) @@ -1314,6 +1351,12 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, mkv_write_video_projection(s, pb, st); end_ebml_master(pb, subinfo); + + if (mkv->mode != MODE_WEBM) { + if ((ret = mkv_write_dovi(s, pb, st)) < 0) + return ret; + } + break; case AVMEDIA_TYPE_AUDIO: -- 2.33.0 _______________________________________________ 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".