mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-11-06 05:17:42 +00:00
avformat/mpegtsenc: add support for muxing LCEVC streams
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
1 parent
0b19c65afe
commit
bf43f4b3cf
3 files changed
+85
-3
No files matched your search
+16
-3
@@ -89,6 +89,7 @@ static int write_nalu(LCEVCDecoderConfigurationRecord *lvcc, AVIOContext *pb,
|
||||
|
||||
lvcc->profile_idc = get_bits(&gb, 4);
|
||||
lvcc->level_idc = get_bits(&gb, 4);
|
||||
lvcc->sublevel_idc = get_bits(&gb, 2);
|
||||
|
||||
avio_write(pb, raw_gbc.buffer, raw_block_size);
|
||||
nalu_length += raw_block_size;
|
||||
@@ -96,12 +97,11 @@ static int write_nalu(LCEVCDecoderConfigurationRecord *lvcc, AVIOContext *pb,
|
||||
break;
|
||||
case 1: {
|
||||
int resolution_type, bit_depth;
|
||||
int processed_planes_type_flag;
|
||||
|
||||
if (gc)
|
||||
break;
|
||||
|
||||
processed_planes_type_flag = get_bits1(&gb);
|
||||
lvcc->processed_planes_type_flag = get_bits1(&gb);
|
||||
resolution_type = get_bits(&gb, 6);
|
||||
|
||||
skip_bits1(&gb);
|
||||
@@ -126,7 +126,7 @@ static int write_nalu(LCEVCDecoderConfigurationRecord *lvcc, AVIOContext *pb,
|
||||
skip_bits(&gb, 4);
|
||||
tile_dimensions_type = get_bits(&gb, 2);
|
||||
skip_bits(&gb, 4);
|
||||
if (processed_planes_type_flag)
|
||||
if (lvcc->processed_planes_type_flag)
|
||||
skip_bits(&gb, 4);
|
||||
if (temporal_step_width_modifier_signalled_flag)
|
||||
skip_bits(&gb, 8);
|
||||
@@ -152,6 +152,19 @@ static int write_nalu(LCEVCDecoderConfigurationRecord *lvcc, AVIOContext *pb,
|
||||
gc = 1;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
int no_enhancement_bit_flag = get_bits1(&gb);
|
||||
|
||||
skip_bits(&gb, 4);
|
||||
lvcc->picture_type_bit_flag = get_bits1(&gb);
|
||||
skip_bits(&gb, 2);
|
||||
|
||||
if (!no_enhancement_bit_flag)
|
||||
skip_bits(&gb, 16);
|
||||
|
||||
lvcc->field_type_bit_flag = lvcc->picture_type_bit_flag ? get_bits1(&gb) : 0;
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
avio_write(pb, raw_gbc.buffer, raw_block_size);
|
||||
nalu_length += raw_block_size;
|
||||
|
||||
@@ -27,11 +27,15 @@
|
||||
typedef struct LCEVCDecoderConfigurationRecord {
|
||||
uint8_t profile_idc;
|
||||
uint8_t level_idc;
|
||||
uint8_t sublevel_idc;
|
||||
uint8_t chroma_format_idc;
|
||||
uint8_t bit_depth_luma_minus8;
|
||||
uint8_t bit_depth_chroma_minus8;
|
||||
uint32_t pic_width_in_luma_samples;
|
||||
uint32_t pic_height_in_luma_samples;
|
||||
uint8_t processed_planes_type_flag;
|
||||
uint8_t picture_type_bit_flag;
|
||||
uint8_t field_type_bit_flag;
|
||||
} LCEVCDecoderConfigurationRecord;
|
||||
|
||||
int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len, void *logctx);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "avformat.h"
|
||||
#include "avio_internal.h"
|
||||
#include "internal.h"
|
||||
#include "lcevc.h"
|
||||
#include "mpegts.h"
|
||||
#include "mux.h"
|
||||
|
||||
@@ -271,6 +272,9 @@ typedef struct MpegTSWriteStream {
|
||||
int opus_pending_trim_start;
|
||||
|
||||
DVBAC3Descriptor *dvb_ac3_desc;
|
||||
|
||||
int nb_stream_groups;
|
||||
AVStreamGroup **stream_groups;
|
||||
} MpegTSWriteStream;
|
||||
|
||||
static void mpegts_write_pat(AVFormatContext *s)
|
||||
@@ -379,6 +383,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st)
|
||||
case AV_CODEC_ID_VVC:
|
||||
stream_type = STREAM_TYPE_VIDEO_VVC;
|
||||
break;
|
||||
case AV_CODEC_ID_LCEVC:
|
||||
stream_type = STREAM_TYPE_VIDEO_LCEVC;
|
||||
break;
|
||||
case AV_CODEC_ID_CAVS:
|
||||
stream_type = STREAM_TYPE_VIDEO_CAVS;
|
||||
break;
|
||||
@@ -478,6 +485,9 @@ static int get_m2ts_stream_type(AVFormatContext *s, AVStream *st)
|
||||
case AV_CODEC_ID_HEVC:
|
||||
stream_type = STREAM_TYPE_VIDEO_HEVC;
|
||||
break;
|
||||
case AV_CODEC_ID_LCEVC:
|
||||
stream_type = STREAM_TYPE_VIDEO_LCEVC;
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_BLURAY:
|
||||
stream_type = STREAM_TYPE_BLURAY_AUDIO_PCM_BLURAY;
|
||||
break;
|
||||
@@ -815,6 +825,31 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
|
||||
} else if (stream_type == STREAM_TYPE_VIDEO_CAVS || stream_type == STREAM_TYPE_VIDEO_AVS2 ||
|
||||
stream_type == STREAM_TYPE_VIDEO_AVS3) {
|
||||
put_registration_descriptor(&q, MKTAG('A', 'V', 'S', 'V'));
|
||||
} else if (ts_st->nb_stream_groups) {
|
||||
if (stream_type == STREAM_TYPE_VIDEO_LCEVC) {
|
||||
LCEVCDecoderConfigurationRecord lvcc = { 0 };
|
||||
ff_lcvec_parse_config_record(&lvcc, st->codecpar->extradata,
|
||||
st->codecpar->extradata_size, s);
|
||||
*q++ = EXTENSION_DESCRIPTOR;
|
||||
*q++ = 5;
|
||||
*q++ = LCEVC_VIDEO_DESCRIPTOR;
|
||||
*q++ = st->id;
|
||||
*q++ = (lvcc.profile_idc << 4) | lvcc.level_idc;
|
||||
*q++ = (lvcc.sublevel_idc << 6) |
|
||||
(lvcc.processed_planes_type_flag << 5) |
|
||||
(lvcc.picture_type_bit_flag << 4) |
|
||||
(lvcc.field_type_bit_flag << 3);
|
||||
*q++ = 0xC0; // HDR_WCG_idc == 3, video_properties_tag == 0
|
||||
} else {
|
||||
*q++ = EXTENSION_DESCRIPTOR;
|
||||
*q++ = 2 + ts_st->nb_stream_groups;
|
||||
*q++ = LCEVC_LINKAGE_DESCRIPTOR;
|
||||
*q++ = ts_st->nb_stream_groups;
|
||||
for (int j = 0; j < ts_st->nb_stream_groups; j++) {
|
||||
AVStreamGroup *stg = ts_st->stream_groups[j];
|
||||
*q++ = stg->entries[stg->params.layered_video->el_index]->stream->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AVMEDIA_TYPE_DATA:
|
||||
@@ -1296,6 +1331,35 @@ static int mpegts_init(AVFormatContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < s->nb_stream_groups; i++) {
|
||||
AVStreamGroup *stg = s->stream_groups[i];
|
||||
|
||||
if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC)
|
||||
continue;
|
||||
|
||||
if (stg->nb_entries != 2) {
|
||||
av_log(s, AV_LOG_ERROR, "LCEVC Stream Group #%"PRId64" needs exactly two streams\n", stg->id);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
for (j = 0; j < stg->nb_entries; j++) {
|
||||
AVStreamGroupEntry *entry = stg->entries[j];
|
||||
AVStream *st;
|
||||
MpegTSWriteStream *ts_st;
|
||||
|
||||
if (entry->type != AV_STREAM_GROUP_ENTRY_STREAM) {
|
||||
av_log(s, AV_LOG_ERROR, "LCEVC Stream Group #%"PRId64" must only reference streams\n", stg->id);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
st = entry->stream;
|
||||
ts_st = st->priv_data;
|
||||
|
||||
av_dynarray_add((void *)&ts_st->stream_groups, &ts_st->nb_stream_groups, (void *)stg);
|
||||
if (!ts_st->nb_stream_groups)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
if (ts->copyts < 1)
|
||||
ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
|
||||
|
||||
@@ -2349,6 +2413,7 @@ static void mpegts_deinit(AVFormatContext *s)
|
||||
if (ts_st) {
|
||||
av_freep(&ts_st->dvb_ac3_desc);
|
||||
av_freep(&ts_st->payload);
|
||||
av_freep(&ts_st->stream_groups);
|
||||
if (ts_st->amux) {
|
||||
avformat_free_context(ts_st->amux);
|
||||
ts_st->amux = NULL;
|
||||
|
||||
Reference in new issue
Block a user