From ba0ef0860f0018c6e8fda7b378d69b011575fdaf Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Aug 2024 13:56:48 -0300 Subject: [PATCH] avformat: add an LCEVC stream group Signed-off-by: James Almer --- doc/APIchanges | 5 +++++ libavformat/avformat.c | 5 +++++ libavformat/avformat.h | 27 +++++++++++++++++++++++++++ libavformat/dump.c | 27 +++++++++++++++++++++++++++ libavformat/options.c | 29 ++++++++++++++++++++++++++++- libavformat/version.h | 4 ++-- 6 files changed, 94 insertions(+), 3 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 33288862ae..174c44a03f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,11 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-09-18 - xxxxxxxxxx - lavf 61.5.100 - avformat.h + Add AVStreamGroupLCEVC + Add AV_STREAM_GROUP_PARAMS_LCEVC + Add AVStreamGroup.params.lcevc + 2024-09-18 - xxxxxxxxxx - lavc 61.16.100 - avcodec.h Add AV_CODEC_ID_LCEVC. diff --git a/libavformat/avformat.c b/libavformat/avformat.c index b4f20502fb..06dcde0565 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -104,6 +104,10 @@ void ff_free_stream_group(AVStreamGroup **pstg) av_freep(&stg->params.tile_grid->offsets); av_freep(&stg->params.tile_grid); break; + case AV_STREAM_GROUP_PARAMS_LCEVC: + av_opt_free(stg->params.lcevc); + av_freep(&stg->params.lcevc); + break; default: break; } @@ -327,6 +331,7 @@ const char *avformat_stream_group_name(enum AVStreamGroupParamsType type) case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: return "IAMF Audio Element"; case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: return "IAMF Mix Presentation"; case AV_STREAM_GROUP_PARAMS_TILE_GRID: return "Tile Grid"; + case AV_STREAM_GROUP_PARAMS_LCEVC: return "LCEVC (Split video and enhancement)"; } return NULL; } diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 4a3fb00529..56c1c80289 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1084,11 +1084,37 @@ typedef struct AVStreamGroupTileGrid { int height; } AVStreamGroupTileGrid; +/** + * AVStreamGroupLCEVC is meant to define the relation between video streams + * and a data stream containing LCEVC enhancement layer NALUs. + * + * No more than one stream of @ref AVCodecParameters.codec_type "codec_type" + * AVMEDIA_TYPE_DATA shall be present, and it must be of + * @ref AVCodecParameters.codec_id "codec_id" AV_CODEC_ID_LCEVC. + */ +typedef struct AVStreamGroupLCEVC { + const AVClass *av_class; + + /** + * Index of the LCEVC data stream in AVStreamGroup. + */ + unsigned int lcevc_index; + /** + * Width of the final stream for presentation. + */ + int width; + /** + * Height of the final image for presentation. + */ + int height; +} AVStreamGroupLCEVC; + enum AVStreamGroupParamsType { AV_STREAM_GROUP_PARAMS_NONE, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION, AV_STREAM_GROUP_PARAMS_TILE_GRID, + AV_STREAM_GROUP_PARAMS_LCEVC, }; struct AVIAMFAudioElement; @@ -1130,6 +1156,7 @@ typedef struct AVStreamGroup { struct AVIAMFAudioElement *iamf_audio_element; struct AVIAMFMixPresentation *iamf_mix_presentation; struct AVStreamGroupTileGrid *tile_grid; + struct AVStreamGroupLCEVC *lcevc; } params; /** diff --git a/libavformat/dump.c b/libavformat/dump.c index 5e1f367742..f20c2c4953 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -789,6 +789,33 @@ static void dump_stream_group(const AVFormatContext *ic, uint8_t *printed, } break; } + case AV_STREAM_GROUP_PARAMS_LCEVC: { + const AVStreamGroupLCEVC *lcevc = stg->params.lcevc; + AVCodecContext *avctx = avcodec_alloc_context3(NULL); + const char *ptr = NULL; + av_log(NULL, AV_LOG_INFO, " LCEVC:"); + if (avctx && stg->nb_streams && !avcodec_parameters_to_context(avctx, stg->streams[0]->codecpar)) { + avctx->width = lcevc->width; + avctx->height = lcevc->height; + avctx->coded_width = lcevc->width; + avctx->coded_height = lcevc->height; + if (ic->dump_separator) + av_opt_set(avctx, "dump_separator", ic->dump_separator, 0); + buf[0] = 0; + avcodec_string(buf, sizeof(buf), avctx, is_output); + ptr = av_stristr(buf, " "); + } + avcodec_free_context(&avctx); + if (ptr) + av_log(NULL, AV_LOG_INFO, "%s", ptr); + av_log(NULL, AV_LOG_INFO, "\n"); + for (int i = 0; i < stg->nb_streams; i++) { + const AVStream *st = stg->streams[i]; + dump_stream_format(ic, st->index, i, index, is_output, AV_LOG_VERBOSE); + printed[st->index] = 1; + } + break; + } default: break; } diff --git a/libavformat/options.c b/libavformat/options.c index 485265df52..039f1eea42 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -348,7 +348,6 @@ static const AVOption tile_grid_options[] = { { "vertical_offset", NULL, OFFSET(vertical_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { NULL }, }; -#undef FLAGS #undef OFFSET static const AVClass tile_grid_class = { @@ -357,6 +356,20 @@ static const AVClass tile_grid_class = { .option = tile_grid_options, }; +#define OFFSET(x) offsetof(AVStreamGroupLCEVC, x) +static const AVOption lcevc_options[] = { + { "video_size", "size of video after LCEVC enhancement has been applied", OFFSET(width), + AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, INT_MAX, FLAGS }, + { NULL }, +}; +#undef OFFSET + +static const AVClass lcevc_class = { + .class_name = "AVStreamGroupLCEVC", + .version = LIBAVUTIL_VERSION_INT, + .option = lcevc_options, +}; + static void *stream_group_child_next(void *obj, void *prev) { AVStreamGroup *stg = obj; @@ -368,6 +381,8 @@ static void *stream_group_child_next(void *obj, void *prev) return stg->params.iamf_mix_presentation; case AV_STREAM_GROUP_PARAMS_TILE_GRID: return stg->params.tile_grid; + case AV_STREAM_GROUP_PARAMS_LCEVC: + return stg->params.lcevc; default: break; } @@ -375,6 +390,8 @@ static void *stream_group_child_next(void *obj, void *prev) return NULL; } +#undef FLAGS + static const AVClass *stream_group_child_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; @@ -393,6 +410,9 @@ static const AVClass *stream_group_child_iterate(void **opaque) case AV_STREAM_GROUP_PARAMS_TILE_GRID: ret = &tile_grid_class; break; + case AV_STREAM_GROUP_PARAMS_LCEVC: + ret = &lcevc_class; + break; default: break; } @@ -462,6 +482,13 @@ AVStreamGroup *avformat_stream_group_create(AVFormatContext *s, stg->params.tile_grid->av_class = &tile_grid_class; av_opt_set_defaults(stg->params.tile_grid); break; + case AV_STREAM_GROUP_PARAMS_LCEVC: + stg->params.lcevc = av_mallocz(sizeof(*stg->params.lcevc)); + if (!stg->params.lcevc) + goto fail; + stg->params.lcevc->av_class = &lcevc_class; + av_opt_set_defaults(stg->params.lcevc); + break; default: goto fail; } diff --git a/libavformat/version.h b/libavformat/version.h index 384cbd49cc..4bde82abb4 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,8 +31,8 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 5 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 6 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \