From df50370e1b10d39047fe92f7f4418094bb507eec Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Jan 2025 12:47:49 -0300 Subject: [PATCH] avformat/matroska: add support for VVC streams As defined in https://github.com/ietf-wg-cellar/matroska-specification/blob/master/codec_specs.md#v_mpegiisovvc Signed-off-by: James Almer --- Changelog | 1 + libavformat/matroska.c | 1 + libavformat/matroskaenc.c | 10 ++++++++-- libavformat/version.h | 2 +- tests/fate-run.sh | 4 ++-- tests/fate/lavf-container.mak | 24 +++++++++++++----------- tests/ref/lavf-fate/vvc.mkv | 3 +++ 7 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 tests/ref/lavf-fate/vvc.mkv diff --git a/Changelog b/Changelog index 7b26b8a3d1..7b6a09a833 100644 --- a/Changelog +++ b/Changelog @@ -10,6 +10,7 @@ version : - ADPCM IMA Xbox decoder - Enhanced FLV v2: Multitrack audio/video, modern codec support - Animated JPEG XL encoding (via libjxl) +- VVC in Matroska version 7.1: - Raw Captions with Time (RCWT) closed caption demuxer diff --git a/libavformat/matroska.c b/libavformat/matroska.c index d0ecfbeb6a..bbad9a7f54 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -90,6 +90,7 @@ const CodecTags ff_mkv_codec_tags[]={ {"V_MPEG4/ISO/SP" , AV_CODEC_ID_MPEG4}, {"V_MPEG4/ISO/AVC" , AV_CODEC_ID_H264}, {"V_MPEGH/ISO/HEVC" , AV_CODEC_ID_HEVC}, + {"V_MPEGI/ISO/VVC" , AV_CODEC_ID_VVC}, {"V_MPEG4/MS/V3" , AV_CODEC_ID_MSMPEG4V3}, {"V_PRORES" , AV_CODEC_ID_PRORES}, {"V_REAL/RV10" , AV_CODEC_ID_RV10}, diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 16f48e7864..3285735a7f 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -39,6 +39,7 @@ #include "riff.h" #include "version.h" #include "vorbiscomment.h" +#include "vvc.h" #include "wv.h" #include "libavutil/avstring.h" @@ -1141,6 +1142,9 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn case AV_CODEC_ID_HEVC: return ff_isom_write_hvcc(dyn_cp, extradata, extradata_size, 0, s); + case AV_CODEC_ID_VVC: + return ff_isom_write_vvcc(dyn_cp, extradata, + extradata_size, 0); case AV_CODEC_ID_ALAC: if (extradata_size < 36) { av_log(s, AV_LOG_ERROR, @@ -3441,8 +3445,10 @@ static int mkv_init(struct AVFormatContext *s) break; case AV_CODEC_ID_H264: case AV_CODEC_ID_HEVC: - if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 || - par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) && + case AV_CODEC_ID_VVC: + if (((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0) || + (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) || + (par->codec_id == AV_CODEC_ID_VVC && par->extradata_size >= 6)) && (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) track->reformat = mkv_reformat_h2645; break; diff --git a/libavformat/version.h b/libavformat/version.h index 4a2f9ab9cb..067277b10f 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFORMAT_VERSION_MINOR 9 -#define LIBAVFORMAT_VERSION_MICRO 105 +#define LIBAVFORMAT_VERSION_MICRO 106 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/tests/fate-run.sh b/tests/fate-run.sh index c61a4dc992..45dcb6e8dc 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -402,8 +402,8 @@ lavf_container_fate() cleanfiles="$cleanfiles $file" input="${target_samples}/$1" do_avconv $file -auto_conversion_filters $DEC_OPTS $2 -i "$input" \ - "$ENC_OPTS -metadata title=lavftest" -vcodec copy -acodec copy || return - do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $3 + "$ENC_OPTS -metadata title=lavftest" $3 -vcodec copy -acodec copy || return + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $4 } lavf_image(){ diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index bc202ee5f3..2b1c0fa19e 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -77,6 +77,7 @@ FATE_LAVF_CONTAINER_FATE-$(call ALLYES, EVC_DEMUXER EVC_PARSER MOV_MUXER) + FATE_LAVF_CONTAINER_FATE-$(call ALLYES, H264_DEMUXER H264_PARSER MOV_MUXER) += h264.mp4 FATE_LAVF_CONTAINER_FATE-$(call ALLYES, HEVC_DEMUXER HEVC_PARSER EXTRACT_EXTRADATA_BSF MOV_MUXER) += hevc.mp4 FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MOV_DEMUXER MOV_MUXER) += mv_hevc.mov +FATE_LAVF_CONTAINER_FATE-$(call ALLYES, VVC_DEMUXER VVC_PARSER SETTS_BSF MATROSKA_MUXER) += vvc.mkv FATE_LAVF_CONTAINER_FATE-$(call ALLYES, VVC_DEMUXER VVC_PARSER MOV_MUXER) += vvc.mp4 FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MATROSKA_DEMUXER OGG_MUXER) += vp3.ogg FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MATROSKA_DEMUXER OGV_MUXER) += vp8.ogg @@ -91,20 +92,21 @@ FATE_LAVF_CONTAINER_FATE = $(FATE_LAVF_CONTAINER_FATE-yes:%=fate-lavf-fate-%) $(FATE_LAVF_CONTAINER_FATE): REF = $(SRC_PATH)/tests/ref/lavf-fate/$(@:fate-lavf-fate-%=%) $(FATE_LAVF_CONTAINER_FATE): $(AREF) $(VREF) -fate-lavf-fate-av1.mp4: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "-c:v av1" "-c:v copy" -fate-lavf-fate-av1.mkv: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "-c:v av1" "-c:v copy" -fate-lavf-fate-evc.mp4: CMD = lavf_container_fate "evc/akiyo_cif.evc" "" "-c:v copy" -fate-lavf-fate-h264.mp4: CMD = lavf_container_fate "h264/intra_refresh.h264" "" "-c:v copy" -fate-lavf-fate-hevc.mp4: CMD = lavf_container_fate "hevc-conformance/HRD_A_Fujitsu_2.bit" "" "-c:v copy" -fate-lavf-fate-vvc.mp4: CMD = lavf_container_fate "vvc-conformance/VPS_A_3.bit" "" "-c:v copy" +fate-lavf-fate-av1.mp4: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "-c:v av1" "" "-c:v copy" +fate-lavf-fate-av1.mkv: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "-c:v av1" "" "-c:v copy" +fate-lavf-fate-evc.mp4: CMD = lavf_container_fate "evc/akiyo_cif.evc" "" "" "-c:v copy" +fate-lavf-fate-h264.mp4: CMD = lavf_container_fate "h264/intra_refresh.h264" "" "" "-c:v copy" +fate-lavf-fate-hevc.mp4: CMD = lavf_container_fate "hevc-conformance/HRD_A_Fujitsu_2.bit" "" "" "-c:v copy" +fate-lavf-fate-vvc.mkv: CMD = lavf_container_fate "vvc-conformance/VPS_A_3.bit" "" "-bsf:v setts=pts=DTS" "-c:v copy" +fate-lavf-fate-vvc.mp4: CMD = lavf_container_fate "vvc-conformance/VPS_A_3.bit" "" "" "-c:v copy" fate-lavf-fate-vp3.ogg: CMD = lavf_container_fate "vp3/coeff_level64.mkv" "-idct auto" -fate-lavf-fate-vp8.ogg: CMD = lavf_container_fate "vp8/RRSF49-short.webm" "" "-acodec copy" -fate-lavf-fate-latm: CMD = lavf_container_fate "aac/al04_44.mp4" "" "-acodec copy" -fate-lavf-fate-mv_hevc.mov: CMD = lavf_container_fate "hevc/multiview.mov" "" "-c:v copy" -fate-lavf-fate-mp3: CMD = lavf_container_fate "mp3-conformance/he_32khz.bit" "" "-acodec copy" +fate-lavf-fate-vp8.ogg: CMD = lavf_container_fate "vp8/RRSF49-short.webm" "" "" "-c:a copy" +fate-lavf-fate-latm: CMD = lavf_container_fate "aac/al04_44.mp4" "" "" "-c:a copy" +fate-lavf-fate-mv_hevc.mov: CMD = lavf_container_fate "hevc/multiview.mov" "" "" "-c:v copy" +fate-lavf-fate-mp3: CMD = lavf_container_fate "mp3-conformance/he_32khz.bit" "" "" "-c:a copy" fate-lavf-fate-qtrle_mace6.mov: CMD = lavf_container_fate "qtrle/Animation-16Greys.mov" "-idct auto" fate-lavf-fate-cram.avi: CMD = lavf_container_fate "cram/toon.avi" "-idct auto" -fate-lavf-fate-hevc.flv: CMD = lavf_container_fate "mkv/hdr10tags-both.mkv" "" "-c:v copy" +fate-lavf-fate-hevc.flv: CMD = lavf_container_fate "mkv/hdr10tags-both.mkv" "" "" "-c:v copy" FATE_SAMPLES_FFMPEG += $(FATE_LAVF_CONTAINER_FATE) fate-lavf-fate fate-lavf: $(FATE_LAVF_CONTAINER_FATE) diff --git a/tests/ref/lavf-fate/vvc.mkv b/tests/ref/lavf-fate/vvc.mkv new file mode 100644 index 0000000000..12936f1f58 --- /dev/null +++ b/tests/ref/lavf-fate/vvc.mkv @@ -0,0 +1,3 @@ +088fe4756b99c28031ba41d1a841a1cb *tests/data/lavf-fate/lavf.vvc.mkv +16351 tests/data/lavf-fate/lavf.vvc.mkv +tests/data/lavf-fate/lavf.vvc.mkv CRC=0x895790b1