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

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++) {