avformat/mpegts: add ts stream types for H266/VVC

Add transport stream stream type 0x33 for vvc.
Add STREAM_TYPE_VIDEO_VVC to MPEG-1/2 and MPEG-2 transport stream.
Add basic transport stream support for TS mux/demux.

Tested with:
ffmpeg -i NovosobornayaSquare_1920x1080.mp4 -c:v libvvenc test.ts && ffmpeg -i test.ts -f null -
ffmpeg -i NovosobornayaSquare_1920x1080.mp4 -c:v copy test.ts     && ffmpeg -i test.ts -f md5 -

Signed-off-by: Marton Balint <cus@passwd.hu>
Signed-off-by: Thomas Siedel <thomas.ff@spin-digital.com>
Co-Authored-By: Nuo Mi <nuomi2021@gmail.com>
This commit is contained in:
Thomas Siedel 2024-01-30 20:49:03 +08:00 committed by Nuo Mi
parent 11a57685cd
commit db6e360afb
6 changed files with 47 additions and 1 deletions

2
configure vendored
View File

@ -3552,7 +3552,7 @@ mp3_demuxer_select="mpegaudio_parser"
mp3_muxer_select="mpegaudioheader"
mp4_muxer_select="mov_muxer"
mpegts_demuxer_select="iso_media"
mpegts_muxer_select="ac3_parser adts_muxer latm_muxer h264_mp4toannexb_bsf hevc_mp4toannexb_bsf"
mpegts_muxer_select="ac3_parser adts_muxer latm_muxer h264_mp4toannexb_bsf hevc_mp4toannexb_bsf vvc_mp4toannexb_bsf"
mpegtsraw_demuxer_select="mpegts_demuxer"
mxf_muxer_select="pcm_rechunk_bsf rangecoder"
mxf_d10_muxer_select="mxf_muxer"

View File

@ -546,6 +546,9 @@ redo:
} else if (es_type == STREAM_TYPE_VIDEO_HEVC) {
codec_id = AV_CODEC_ID_HEVC;
type = AVMEDIA_TYPE_VIDEO;
} else if (es_type == STREAM_TYPE_VIDEO_VVC) {
codec_id = AV_CODEC_ID_VVC;
type = AVMEDIA_TYPE_VIDEO;
} else if (es_type == STREAM_TYPE_AUDIO_AC3) {
codec_id = AV_CODEC_ID_AC3;
type = AVMEDIA_TYPE_AUDIO;

View File

@ -56,6 +56,7 @@
#define STREAM_TYPE_VIDEO_MPEG4 0x10
#define STREAM_TYPE_VIDEO_H264 0x1b
#define STREAM_TYPE_VIDEO_HEVC 0x24
#define STREAM_TYPE_VIDEO_VVC 0x33
#define STREAM_TYPE_VIDEO_CAVS 0x42
#define STREAM_TYPE_AUDIO_AC3 0x81

View File

@ -812,6 +812,7 @@ static const StreamType ISO_types[] = {
{ 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 },
{ 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000 },
{ 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
{ 0x33, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VVC },
{ 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS },
{ 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC },
{ 0xd2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 },
@ -867,6 +868,7 @@ static const StreamType REGD_types[] = {
{ MKTAG('D', 'T', 'S', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS },
{ MKTAG('E', 'A', 'C', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 },
{ MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
{ MKTAG('V', 'V', 'C', ' '), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VVC },
{ MKTAG('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV },
{ MKTAG('V', 'A', 'N', 'C'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_2038 },
{ MKTAG('I', 'D', '3', ' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 },

View File

@ -128,6 +128,7 @@
#define STREAM_TYPE_METADATA 0x15
#define STREAM_TYPE_VIDEO_H264 0x1b
#define STREAM_TYPE_VIDEO_HEVC 0x24
#define STREAM_TYPE_VIDEO_VVC 0x33
#define STREAM_TYPE_VIDEO_CAVS 0x42
#define STREAM_TYPE_VIDEO_AVS2 0xd2
#define STREAM_TYPE_VIDEO_AVS3 0xd4

View File

@ -32,6 +32,7 @@
#include "libavcodec/defs.h"
#include "libavcodec/h264.h"
#include "libavcodec/hevc.h"
#include "libavcodec/vvc.h"
#include "libavcodec/startcode.h"
#include "avformat.h"
@ -369,6 +370,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st)
case AV_CODEC_ID_HEVC:
stream_type = STREAM_TYPE_VIDEO_HEVC;
break;
case AV_CODEC_ID_VVC:
stream_type = STREAM_TYPE_VIDEO_VVC;
break;
case AV_CODEC_ID_CAVS:
stream_type = STREAM_TYPE_VIDEO_CAVS;
break;
@ -1851,6 +1855,7 @@ static uint8_t *h26x_prefix_aud(const uint8_t *aud, const int aud_size,
#define H264_NAL_TYPE(state) (state & 0x1f)
#define HEVC_NAL_TYPE(state) ((state & 0x7e) >> 1)
#define VVC_NAL_TYPE(state) ((state >> 11) & 0x1f)
static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
{
AVStream *st = s->streams[pkt->stream_index];
@ -2022,6 +2027,39 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
if (!data)
return AVERROR(ENOMEM);
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_VVC) {
const uint8_t *p = buf, *buf_end = p + size;
uint32_t state = -1;
uint32_t nal_type = -1;
int extradd = (pkt->flags & AV_PKT_FLAG_KEY) ? st->codecpar->extradata_size : 0;
int ret = check_h26x_startcode(s, st, pkt, "vvc");
if (ret < 0)
return ret;
if (extradd && AV_RB24(st->codecpar->extradata) > 1)
extradd = 0;
do {
p = avpriv_find_start_code(p, buf_end, &state);
// state contains byte behind start code, p points 2 bytes behind start code
nal_type = VVC_NAL_TYPE(state);
av_log(s, AV_LOG_TRACE, "nal %"PRId32"\n", nal_type );
if (nal_type == VVC_VPS_NUT)
extradd = 0;
} while (p < buf_end && nal_type != VVC_AUD_NUT && nal_type >= VVC_OPI_NUT);
if (nal_type >= VVC_OPI_NUT)
extradd = 0;
if (nal_type != VVC_AUD_NUT) { // AUD NAL
const uint8_t aud[] = {
0, // forbidden_zero_bit, nuh_reserved_zero_bit, nuh_layer_id
(VVC_AUD_NUT << 3) | 1, // nal_unit_type, nuh_temporal_id_plus1(1)
(pkt->flags & AV_PKT_FLAG_KEY) << 7 | 0x28, // aud_irap_or_gdr_flag, aud_pic_type(2), rbsp_stop_one_bit
};
buf = data = h26x_prefix_aud(aud, FF_ARRAY_ELEMS(aud), st->codecpar->extradata, extradd, pkt, &size);
if (!data)
return AVERROR(ENOMEM);
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
if (pkt->size < 2) {
av_log(s, AV_LOG_ERROR, "Opus packet too short\n");
@ -2272,6 +2310,7 @@ static int mpegts_check_bitstream(AVFormatContext *s, AVStream *st,
} list[] = {
{ AV_CODEC_ID_H264, "h264_mp4toannexb", 0xff, 0x01 /* configurationVersion in AVCDecoderConfigurationRecord */},
{ AV_CODEC_ID_HEVC, "hevc_mp4toannexb", 0xff, 0x01 /* configurationVersion in HEVCDecoderConfigurationRecord */},
{ AV_CODEC_ID_VVC, "vvc_mp4toannexb", 0xf8, 0xf8 /* reserved '11111'b in VVCDecoderConfigurationRecord */},
};
for (int i = 0; i < FF_ARRAY_ELEMS(list); i++) {