From: thomas.ff@spin-digital.com
To: ffmpeg-devel@ffmpeg.org
Cc: Thomas Siedel <thomas.ff@spin-digital.com>
Subject: [FFmpeg-devel] [PATCH v1 07/11] avformat: add muxer support for H266/VVC
Date: Wed, 19 Oct 2022 09:25:04 +0200
Message-ID: <20221019072508.23460-8-thomas.ff@spin-digital.com> (raw)
In-Reply-To: <20221019072508.23460-1-thomas.ff@spin-digital.com>
From: Thomas Siedel <thomas.ff@spin-digital.com>
Add muxer for vvcc byte stream format.
Add AV_CODEC_ID_VVC to ff_mp4_obj_type
Add AV_CODEC_ID_VVC to ISO Media codec (VvcConfigurationBox vvi1, vvc1 defined in ISO/IEC 14496-15:2021)
Add VvcConfigurationBox vvcC which extends FullBox type in ISO/IEC 14496-15:2021
Add ff_vvc_muxer to RAW muxers
Signed-off-by: Thomas Siedel <thomas.ff@spin-digital.com>
---
libavformat/Makefile | 7 ++++---
libavformat/allformats.c | 1 +
libavformat/isom.c | 1 +
libavformat/isom_tags.c | 3 +++
libavformat/mov.c | 6 ++++++
libavformat/movenc.c | 41 +++++++++++++++++++++++++++++++++++++++-
libavformat/rawenc.c | 23 ++++++++++++++++++++++
7 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 00ab4ded89..9ee2526eef 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -336,7 +336,7 @@ OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \
oggparsevorbis.o vorbiscomment.o \
qtpalette.o replaygain.o dovi_isom.o
OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \
- av1.o avc.o hevc.o \
+ av1.o avc.o hevc.o vvc.o\
flacenc_header.o avlanguage.o \
vorbiscomment.o wv.o dovi_isom.o
OBJS-$(CONFIG_MCA_DEMUXER) += mca.o
@@ -358,7 +358,7 @@ OBJS-$(CONFIG_MODS_DEMUXER) += mods.o
OBJS-$(CONFIG_MOFLEX_DEMUXER) += moflex.o
OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \
qtpalette.o replaygain.o dovi_isom.o
-OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \
+OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vvc.o vpcc.o \
movenchint.o mov_chan.o rtp.o \
movenccenc.o movenc_ttml.o rawutils.o \
dovi_isom.o
@@ -508,7 +508,7 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \
rtpenc_vp8.o \
rtpenc_vp9.o \
rtpenc_xiph.o \
- avc.o hevc.o
+ avc.o hevc.o vvc.o
OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o \
urldecode.o
OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o \
@@ -596,6 +596,7 @@ OBJS-$(CONFIG_VPK_DEMUXER) += vpk.o
OBJS-$(CONFIG_VPLAYER_DEMUXER) += vplayerdec.o subtitles.o
OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o
OBJS-$(CONFIG_VVC_DEMUXER) += vvcdec.o rawdec.o
+OBJS-$(CONFIG_VVC_MUXER) += rawenc.o
OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o
OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o
OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index a4e3822681..006a7dc125 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -475,6 +475,7 @@ extern const AVInputFormat ff_vpk_demuxer;
extern const AVInputFormat ff_vplayer_demuxer;
extern const AVInputFormat ff_vqf_demuxer;
extern const AVInputFormat ff_vvc_demuxer;
+extern const AVOutputFormat ff_vvc_muxer;
extern const AVInputFormat ff_w64_demuxer;
extern const AVOutputFormat ff_w64_muxer;
extern const AVInputFormat ff_wav_demuxer;
diff --git a/libavformat/isom.c b/libavformat/isom.c
index 6d019881e5..9fbccd4437 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -36,6 +36,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
{ AV_CODEC_ID_MPEG4 , 0x20 },
{ AV_CODEC_ID_H264 , 0x21 },
{ AV_CODEC_ID_HEVC , 0x23 },
+ { AV_CODEC_ID_VVC , 0x33 },
{ AV_CODEC_ID_AAC , 0x40 },
{ AV_CODEC_ID_MP4ALS , 0x40 }, /* 14496-3 ALS */
{ AV_CODEC_ID_MPEG2VIDEO , 0x61 }, /* MPEG-2 Main */
diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c
index e2b80405cc..ec93bdc363 100644
--- a/libavformat/isom_tags.c
+++ b/libavformat/isom_tags.c
@@ -123,6 +123,9 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
{ AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', 'e') }, /* HEVC-based Dolby Vision derived from hev1 */
/* dvh1 is handled within mov.c */
+ { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') }, /* VVC/H.266 which indicates parameter sets may be in ES */
+ { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') }, /* VVC/H.266 which indicates parameter shall not be in ES */
+
{ AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
{ AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '2') },
{ AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 1f436e21d6..52719c9d9a 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1962,6 +1962,11 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if ((uint64_t)atom.size > (1<<30))
return AVERROR_INVALIDDATA;
+ if (atom.type == MKTAG('v','v','c','C')) {
+ avio_rb32(pb);
+ atom.size -= 4;
+ }
+
if (atom.size >= 10) {
// Broken files created by legacy versions of libavformat will
// wrap a whole fiel atom inside of a glbl atom.
@@ -7730,6 +7735,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('s','g','p','d'), mov_read_sgpd },
{ MKTAG('s','b','g','p'), mov_read_sbgp },
{ MKTAG('h','v','c','C'), mov_read_glbl },
+{ MKTAG('v','v','c','C'), mov_read_glbl },
{ MKTAG('u','u','i','d'), mov_read_uuid },
{ MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
{ MKTAG('f','r','e','e'), mov_read_free },
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 754f95912a..3d412d0079 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -59,6 +59,7 @@
#include "libavutil/color_utils.h"
#include "libavutil/uuid.h"
#include "hevc.h"
+#include "vvc.h"
#include "rtpenc.h"
#include "mov_chan.h"
#include "movenc_ttml.h"
@@ -1392,6 +1393,23 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
return update_size(pb, pos);
}
+static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
+{
+ int64_t pos = avio_tell(pb);
+
+ avio_wb32(pb, 0);
+ ffio_wfourcc(pb, "vvcC");
+
+ avio_w8 (pb, 0); /* version */
+ avio_wb24(pb, 0); /* flags */
+
+ if (track->tag == MKTAG('v','v','i','1'))
+ ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 1);
+ else
+ ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 0);
+ return update_size(pb, pos);
+}
+
/* also used by all avid codecs (dv, imx, meridien) and their variants */
static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
{
@@ -2286,6 +2304,8 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
avid = 1;
} else if (track->par->codec_id == AV_CODEC_ID_HEVC)
mov_write_hvcc_tag(pb, track);
+ else if (track->par->codec_id == AV_CODEC_ID_VVC)
+ mov_write_vvcc_tag(pb, track);
else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
mov_write_avcc_tag(pb, track);
if (track->mode == MODE_IPOD)
@@ -6033,6 +6053,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
if ((par->codec_id == AV_CODEC_ID_DNXHD ||
par->codec_id == AV_CODEC_ID_H264 ||
par->codec_id == AV_CODEC_ID_HEVC ||
+ par->codec_id == AV_CODEC_ID_VVC ||
par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
!TAG_IS_AVCI(trk->tag)) {
/* copy frame to create needed atoms */
@@ -6096,6 +6117,18 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
}
}
+ } else if (par->codec_id == AV_CODEC_ID_VVC && trk->vos_len > 6 &&
+ (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
+ /* extradata is Annex B, assume the bitstream is too and convert it */
+ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
+ ret = ff_vvc_annexb2mp4_buf(pkt->data, &reformatted_data,
+ &size, 0, NULL);
+ if (ret < 0)
+ return ret;
+ avio_write(pb, reformatted_data, size);
+ } else {
+ size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
+ }
} else if (par->codec_id == AV_CODEC_ID_AV1) {
if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
@@ -6142,6 +6175,9 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
} else if(par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 21) {
int nal_size_length = (par->extradata[21] & 0x3) + 1;
ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
+ } else if(par->codec_id == AV_CODEC_ID_VVC && par->extradata_size > 21) {
+ int nal_size_length = (par->extradata[21] & 0x3) + 1;
+ ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
} else {
ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
}
@@ -7224,7 +7260,8 @@ static int mov_init(AVFormatContext *s)
if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
- (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC),
+ (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
+ track->par->codec_id == AV_CODEC_ID_VVC),
s->flags & AVFMT_FLAG_BITEXACT);
if (ret)
return ret;
@@ -7692,6 +7729,8 @@ static const AVCodecTag codec_mp4_tags[] = {
{ AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') },
{ AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') },
{ AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') },
+ { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') },
+ { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') },
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
{ AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
{ AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') },
diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
index 267fce252d..7770d63d10 100644
--- a/libavformat/rawenc.c
+++ b/libavformat/rawenc.c
@@ -401,6 +401,29 @@ const AVOutputFormat ff_hevc_muxer = {
};
#endif
+#if CONFIG_VVC_MUXER
+static int vvc_check_bitstream(AVFormatContext *s, AVStream *st,
+ const AVPacket *pkt)
+{
+ if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
+ AV_RB24(pkt->data) != 0x000001)
+ return ff_stream_add_bitstream_filter(st, "vvc_mp4toannexb", NULL);
+ return 1;
+}
+
+const AVOutputFormat ff_vvc_muxer = {
+ .name = "vvc",
+ .long_name = NULL_IF_CONFIG_SMALL("raw VVC video"),
+ .extensions = "vvc,h266,266",
+ .audio_codec = AV_CODEC_ID_NONE,
+ .video_codec = AV_CODEC_ID_VVC,
+ .init = force_one_stream,
+ .write_packet = ff_raw_write_packet,
+ .check_bitstream = vvc_check_bitstream,
+ .flags = AVFMT_NOTIMESTAMPS,
+};
+#endif
+
#if CONFIG_M4V_MUXER
const AVOutputFormat ff_m4v_muxer = {
.name = "m4v",
--
2.25.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-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-10-19 7:28 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-19 7:24 [FFmpeg-devel] [PATCH v1 00/11] Add " thomas.ff
2022-10-19 7:24 ` [FFmpeg-devel] [PATCH v1 01/11] avcodec: add enum types " thomas.ff
2022-10-19 7:24 ` [FFmpeg-devel] [PATCH v1 02/11] avcodec: add cbs " thomas.ff
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 03/11] avcodec: enable " thomas.ff
2022-10-19 23:07 ` James Almer
2022-10-24 14:23 ` Thomas Siedel
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 04/11] avcodec: add bitstream parser " thomas.ff
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 05/11] avcodec: add MP4 to annexb support " thomas.ff
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 06/11] avformat: add demuxer and probe " thomas.ff
2022-10-19 12:06 ` Michael Niedermayer
2022-10-24 14:19 ` Thomas Siedel
2022-10-19 7:25 ` thomas.ff [this message]
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 08/11] avcodec: add external decoder libvvdec " thomas.ff
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 09/11] avcodec: add external encoder libvvenc " thomas.ff
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 10/11] avformat: add ts stream types " thomas.ff
2022-10-19 7:25 ` [FFmpeg-devel] [PATCH v1 11/11] avcodec: increase minor version " thomas.ff
2022-12-13 6:19 ` [FFmpeg-devel] [PATCH v1 00/11] Add support " Nuo Mi
2022-12-15 9:11 ` Thomas Siedel
2023-01-03 14:02 ` Thomas Siedel
2023-01-10 2:56 ` Nuo Mi
2023-01-10 11:08 ` mypopy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221019072508.23460-8-thomas.ff@spin-digital.com \
--to=thomas.ff@spin-digital.com \
--cc=ffmpeg-devel@ffmpeg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git