mirror of
https://mirror.skon.top/https://github.com/FFmpeg/FFmpeg
synced 2026-04-20 12:50:49 +08:00
avformat/mpegts: add support for LCEVC streams
As defined in ITU-T H.222.0 v9, LCEVC streams use the "Byte stream format" defined in Annex B of ISO/IEC 23094-2:2021. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
@@ -29,6 +29,7 @@ version <next>:
|
||||
- ffprobe: only show refs field in stream section when reading frames
|
||||
- ProRes Vulkan encoder
|
||||
- LCEVC parser
|
||||
- LCEVC enhancement layer exporting in MPEG-TS
|
||||
|
||||
|
||||
version 8.0:
|
||||
|
||||
@@ -816,6 +816,7 @@ static const StreamType ISO_types[] = {
|
||||
{ STREAM_TYPE_VIDEO_JPEG2000, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000 },
|
||||
{ STREAM_TYPE_VIDEO_HEVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
|
||||
{ STREAM_TYPE_VIDEO_JPEGXS, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEGXS },
|
||||
{ STREAM_TYPE_VIDEO_LCEVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_LCEVC },
|
||||
{ STREAM_TYPE_VIDEO_VVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VVC },
|
||||
{ STREAM_TYPE_VIDEO_CAVS, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS },
|
||||
{ STREAM_TYPE_VIDEO_DIRAC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC },
|
||||
@@ -1834,9 +1835,10 @@ static const uint8_t opus_channel_map[8][8] = {
|
||||
{ 0,6,1,2,3,4,5,7 },
|
||||
};
|
||||
|
||||
static int parse_mpeg2_extension_descriptor(AVFormatContext *fc, AVStream *st,
|
||||
static int parse_mpeg2_extension_descriptor(AVFormatContext *fc, AVStream *st, int prg_id,
|
||||
const uint8_t **pp, const uint8_t *desc_end)
|
||||
{
|
||||
MpegTSContext *ts = fc->priv_data;
|
||||
int ext_tag = get8(pp, desc_end);
|
||||
|
||||
switch (ext_tag) {
|
||||
@@ -1913,6 +1915,88 @@ static int parse_mpeg2_extension_descriptor(AVFormatContext *fc, AVStream *st,
|
||||
st->codecpar->color_space = matrix_coefficients;
|
||||
}
|
||||
break;
|
||||
case LCEVC_VIDEO_DESCRIPTOR:
|
||||
{
|
||||
AVStreamGroup *stg = NULL;
|
||||
int lcevc_stream_tag = get8(pp, desc_end);
|
||||
int ret, i;
|
||||
|
||||
if (!get_program(ts, prg_id))
|
||||
return 0;
|
||||
|
||||
if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
for (i = 0; i < fc->nb_stream_groups; i++) {
|
||||
stg = fc->stream_groups[i];
|
||||
if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC)
|
||||
continue;
|
||||
if (stg->id == lcevc_stream_tag)
|
||||
break;
|
||||
}
|
||||
if (i == fc->nb_stream_groups)
|
||||
stg = avformat_stream_group_create(fc, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
|
||||
if (!stg)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
stg->id = lcevc_stream_tag;
|
||||
for (i = 0; i < stg->nb_streams; i++) {
|
||||
if (stg->streams[i]->codecpar->codec_id == AV_CODEC_ID_LCEVC)
|
||||
break;
|
||||
}
|
||||
if (i == stg->nb_streams) {
|
||||
ret = avformat_stream_group_add_stream(stg, st);
|
||||
av_assert0(ret != AVERROR(EEXIST));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else
|
||||
stg->streams[i] = st;
|
||||
|
||||
av_assert0(i < stg->nb_streams);
|
||||
stg->params.lcevc->lcevc_index = i;
|
||||
}
|
||||
break;
|
||||
case LCEVC_LINKAGE_DESCRIPTOR:
|
||||
{
|
||||
int num_lcevc_stream_tags = get8(pp, desc_end);
|
||||
|
||||
if (!get_program(ts, prg_id))
|
||||
return 0;
|
||||
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_LCEVC)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
for (int i = 0; i < num_lcevc_stream_tags; i++) {
|
||||
AVStreamGroup *stg = NULL;
|
||||
int lcevc_stream_tag = get8(pp, desc_end);;
|
||||
int ret, j;
|
||||
|
||||
for (j = 0; j < fc->nb_stream_groups; j++) {
|
||||
stg = fc->stream_groups[j];
|
||||
if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC)
|
||||
continue;
|
||||
if (stg->id == lcevc_stream_tag)
|
||||
break;
|
||||
}
|
||||
if (j == fc->nb_stream_groups)
|
||||
stg = avformat_stream_group_create(fc, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
|
||||
if (!stg)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
stg->id = lcevc_stream_tag;
|
||||
for (j = 0; j < stg->nb_streams; j++) {
|
||||
if (stg->streams[j]->index == st->index)
|
||||
break;
|
||||
}
|
||||
if (j == stg->nb_streams) {
|
||||
ret = avformat_stream_group_add_stream(stg, st);
|
||||
av_assert0(ret != AVERROR(EEXIST));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1920,7 +2004,7 @@ static int parse_mpeg2_extension_descriptor(AVFormatContext *fc, AVStream *st,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type,
|
||||
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, int prg_id,
|
||||
const uint8_t **pp, const uint8_t *desc_list_end,
|
||||
Mp4Descr *mp4_descr, int mp4_descr_count, int pid,
|
||||
MpegTSContext *ts)
|
||||
@@ -2354,7 +2438,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
|
||||
break;
|
||||
case EXTENSION_DESCRIPTOR: /* descriptor extension */
|
||||
{
|
||||
int ret = parse_mpeg2_extension_descriptor(fc, st, pp, desc_end);
|
||||
int ret = parse_mpeg2_extension_descriptor(fc, st, prg_id, pp, desc_end);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -2643,7 +2727,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
||||
if (desc_list_end > p_end)
|
||||
goto out;
|
||||
for (;;) {
|
||||
if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p,
|
||||
if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, h->id, &p,
|
||||
desc_list_end, mp4_descr,
|
||||
mp4_descr_count, pid, ts) < 0)
|
||||
break;
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
#define STREAM_TYPE_VIDEO_HEVC 0x24
|
||||
#define STREAM_TYPE_VIDEO_JPEGXS 0x32
|
||||
#define STREAM_TYPE_VIDEO_VVC 0x33
|
||||
#define STREAM_TYPE_VIDEO_LCEVC 0x36
|
||||
#define STREAM_TYPE_VIDEO_CAVS 0x42
|
||||
#define STREAM_TYPE_VIDEO_AVS2 0xd2
|
||||
#define STREAM_TYPE_VIDEO_AVS3 0xd4
|
||||
@@ -208,6 +209,8 @@ https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/
|
||||
|
||||
/* ISO/IEC 13818-1 Table 2-109 */
|
||||
#define JXS_VIDEO_DESCRIPTOR 0x14 /* JPEG-XS descriptor */
|
||||
#define LCEVC_VIDEO_DESCRIPTOR 0x17 /* LCEVC video descriptor */
|
||||
#define LCEVC_LINKAGE_DESCRIPTOR 0x18 /* LCEVC linkage descriptor */
|
||||
|
||||
/* DVB descriptor tag values [0x40, 0x7F] from
|
||||
ETSI EN 300 468 Table 12: Possible locations of descriptors */
|
||||
@@ -288,7 +291,7 @@ typedef struct DVBAC3Descriptor {
|
||||
* @param desc_list_end End of buffer
|
||||
* @return <0 to stop processing
|
||||
*/
|
||||
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type,
|
||||
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, int prg_id,
|
||||
const uint8_t **pp, const uint8_t *desc_list_end,
|
||||
Mp4Descr *mp4_descr, int mp4_descr_count, int pid,
|
||||
MpegTSContext *ts);
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
|
||||
#include "version_major.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MINOR 10
|
||||
#define LIBAVFORMAT_VERSION_MICRO 101
|
||||
#define LIBAVFORMAT_VERSION_MINOR 11
|
||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
|
||||
@@ -852,7 +852,7 @@ static int parse_chunks(AVFormatContext *s, int mode, int64_t seekts, int *len_p
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
consumed += buf_size;
|
||||
ff_parse_mpeg2_descriptor(s, st, 0, &pbuf, buf + buf_size, NULL, 0, 0, NULL);
|
||||
ff_parse_mpeg2_descriptor(s, st, 0, -1, &pbuf, buf + buf_size, NULL, 0, 0, NULL);
|
||||
}
|
||||
} else if (!ff_guidcmp(g, EVENTID_AudioTypeSpanningEvent)) {
|
||||
int stream_index = ff_find_stream_index(s, sid);
|
||||
|
||||
Reference in New Issue
Block a user