PR #23274 opened by James Almer (jamrial) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23274 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23274.patch
Reduces code duplication. The following step would be to make h2645_sei use these too. >From 98a7a2e933381f8d46c739f77b4c3d2105472758 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Fri, 29 May 2026 12:09:11 -0300 Subject: [PATCH 1/4] avcodec/itut35: add ITU-T T35 parsing helpers Signed-off-by: James Almer <[email protected]> --- libavcodec/itut35.c | 297 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/itut35.h | 90 ++++++++++++++ 2 files changed, 387 insertions(+) create mode 100644 libavcodec/itut35.c diff --git a/libavcodec/itut35.c b/libavcodec/itut35.c new file mode 100644 index 0000000000..d191b4ca73 --- /dev/null +++ b/libavcodec/itut35.c @@ -0,0 +1,297 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/buffer.h" +#include "libavutil/frame.h" +#include "libavutil/hdr_dynamic_metadata.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "atsc_a53.h" +#include "bytestream.h" +#include "decode.h" +#include "dovi_rpu.h" +#include "itut35.h" +#include "version.h" + +int ff_itut_t35_parse_buffer(FFITUTT35 *const itut_t35, const uint8_t *buf, + size_t buf_size, int flags) { + GetByteContext gb; + int provider_code, provider_oriented_code = 0, country_code; + + bytestream2_init(&gb, buf, buf_size); + + if (flags & FF_ITUT_T35_FLAG_COUNTRY_CODE) + country_code = itut_t35->country_code; + else { + country_code = bytestream2_get_byte(&gb); + if (country_code == 0xFF) { + if (bytestream2_get_bytes_left(&gb) < 3) + return AVERROR_INVALIDDATA; + + bytestream2_skipu(&gb, 1); // itu_t_t35_country_code_extension_byte + } + } + + switch (country_code) { + case ITU_T_T35_COUNTRY_CODE_US: + if (bytestream2_get_bytes_left(&gb) < 2) + return AVERROR_INVALIDDATA; + provider_code = bytestream2_get_be16u(&gb); + + switch (provider_code) { + case ITU_T_T35_PROVIDER_CODE_ATSC: { + provider_oriented_code = bytestream2_get_be32(&gb); + switch (provider_oriented_code) { + case MKBETAG('G', 'A', '9', '4'): { // closed captions + itut_t35->payload = gb.buffer; + itut_t35->payload_size = bytestream2_get_bytes_left(&gb); + break; + } + default: // ignore unsupported identifiers + return 0; + } + break; + } + case ITU_T_T35_PROVIDER_CODE_SAMSUNG: { + provider_oriented_code = bytestream2_get_be16(&gb); + int application_identifier = bytestream2_get_byte(&gb); + + if (provider_oriented_code != 1 || application_identifier != 4) + return 0; // ignore + + itut_t35->payload = gb.buffer; + itut_t35->payload_size = bytestream2_get_bytes_left(&gb); + break; + } + case ITU_T_T35_PROVIDER_CODE_DOLBY: { + provider_oriented_code = bytestream2_get_be32(&gb); + if (provider_oriented_code != 0x800) + return 0; // ignore + + itut_t35->payload = gb.buffer; + itut_t35->payload_size = bytestream2_get_bytes_left(&gb); + break; + } + case ITU_T_T35_PROVIDER_CODE_SMPTE: { + provider_oriented_code = bytestream2_get_be16(&gb); + if (provider_oriented_code != 1) + return 0; // ignore + + itut_t35->payload = gb.buffer; + itut_t35->payload_size = bytestream2_get_bytes_left(&gb); + break; + } + default: // ignore unsupported provider codes + return 0; + } + break; + case ITU_T_T35_COUNTRY_CODE_UK: + provider_oriented_code = bytestream2_get_byte(&gb); // t35_uk_country_code_second_octet + if (bytestream2_get_bytes_left(&gb) < 2) + return AVERROR_INVALIDDATA; + + provider_code = bytestream2_get_be16u(&gb); + switch (provider_code) { + case ITU_T_T35_PROVIDER_CODE_VNOVA: { + if (bytestream2_get_bytes_left(&gb) < 2) + return AVERROR_INVALIDDATA; + + itut_t35->payload = gb.buffer; + itut_t35->payload_size = bytestream2_get_bytes_left(&gb); + break; + } + default: // ignore unsupported provider codes + return 0; + } + break; + + default: // ignore unsupported country codes + return 0; + } + + itut_t35->country_code = country_code; + itut_t35->provider_code = provider_code; + itut_t35->provider_oriented_code = provider_oriented_code; + + return 1; +} + +int ff_itut_t35_parse_payload_to_struct(AVCodecContext *const avctx, FFITUTT35 *const itut_t35, + FFITUTT35Aux *const aux, FFITUTT35Meta *metadata) +{ + int ret; + + switch (itut_t35->country_code) { + case ITU_T_T35_COUNTRY_CODE_US: + switch (itut_t35->provider_code) { + case ITU_T_T35_PROVIDER_CODE_ATSC: { + switch (itut_t35->provider_oriented_code) { + case MKBETAG('G', 'A', '9', '4'): // closed captions + ret = ff_parse_a53_cc(&metadata->a53_cc, itut_t35->payload, itut_t35->payload_size); + if (ret < 0) + return ret; + + break; + default: // ignore unsupported identifiers + break; + } + break; + } + case ITU_T_T35_PROVIDER_CODE_SAMSUNG: { + size_t size; + AVDynamicHDRPlus *hdrplus = av_dynamic_hdr_plus_alloc(&size); + if (!hdrplus) + return AVERROR(ENOMEM); + + ret = av_dynamic_hdr_plus_from_t35(hdrplus, itut_t35->payload, + itut_t35->payload_size); + if (ret < 0) + return ret; + + metadata->hdrplus = av_buffer_create((uint8_t *)hdrplus, size, NULL, NULL, 0); + if (!metadata->hdrplus) { + av_free(hdrplus); + return AVERROR(ENOMEM); + } + + break; + } + case ITU_T_T35_PROVIDER_CODE_DOLBY: { + AVDOVIMetadata *dovi; + + if (!aux || !aux->dovi) + return 0; // ignore + + ret = ff_dovi_rpu_parse(aux->dovi, itut_t35->payload, itut_t35->payload_size, 0); + if (ret < 0) + av_log(avctx, AV_LOG_WARNING, "Error parsing DOVI OBU.\n"); + + ret = ff_dovi_get_metadata(aux->dovi, &dovi); + if (ret <= 0) + return ret; + + metadata->dovi = av_buffer_create((uint8_t *)dovi, ret, NULL, NULL, 0); + if (!metadata->dovi) { + av_free(dovi); + return AVERROR(ENOMEM); + } + + break; + } + case ITU_T_T35_PROVIDER_CODE_SMPTE: { + size_t size; + AVDynamicHDRSmpte2094App5 *hdr_smpte2094_app5 = av_dynamic_hdr_smpte2094_app5_alloc(&size); + if (!hdr_smpte2094_app5) + return AVERROR(ENOMEM); + + ret = av_dynamic_hdr_smpte2094_app5_from_t35(hdr_smpte2094_app5, itut_t35->payload, + itut_t35->payload_size); + if (ret < 0) + return ret; + + metadata->hdr_smpte2094_app5 = av_buffer_create((uint8_t *)hdr_smpte2094_app5, size, NULL, NULL, 0); + if (!metadata->hdr_smpte2094_app5) { + av_free(hdr_smpte2094_app5); + return AVERROR(ENOMEM); + } + + break; + } + default: + break; + } + break; + case ITU_T_T35_COUNTRY_CODE_UK: + switch (itut_t35->provider_code) { + case ITU_T_T35_PROVIDER_CODE_VNOVA: + metadata->lcevc = av_buffer_alloc(itut_t35->payload_size); + if (!metadata->lcevc) + return AVERROR(ENOMEM); + + memcpy(metadata->lcevc->data, itut_t35->payload, itut_t35->payload_size); + + break; + default: + break; + } + break; + + default: + // ignore unsupported provider codes + break; + } + + return 0; +} + +int ff_itut_t35_parse_payload_to_frame(AVCodecContext *const avctx, FFITUTT35 *const itut_t35, + FFITUTT35Aux *const aux, AVFrame *const frame) +{ + FFITUTT35Meta metadata = { 0 }; + int ret; + + ret = ff_itut_t35_parse_payload_to_struct(avctx, itut_t35, aux, &metadata); + if (ret < 0) + return ret; + + if (metadata.a53_cc) { + ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_A53_CC, &metadata.a53_cc); + if (ret < 0) + return ret; + +#if FF_API_CODEC_PROPS +FF_DISABLE_DEPRECATION_WARNINGS + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } + + if (metadata.hdrplus) { + ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + &metadata.hdrplus); + if (ret < 0) + return ret; + } + + if (metadata.dovi) { + AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOVI_METADATA, + metadata.dovi); + if (!sd) { + av_buffer_unref(&metadata.dovi); + return AVERROR(ENOMEM); + } + } + + if (metadata.hdr_smpte2094_app5) { + ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5, + &metadata.hdr_smpte2094_app5); + if (ret < 0) + return ret; + } + + if (metadata.lcevc) { + ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_LCEVC, + &metadata.lcevc); + if (ret < 0) + return ret; + } + + return 0; +} diff --git a/libavcodec/itut35.h b/libavcodec/itut35.h index 3820fcfec4..8725459ef1 100644 --- a/libavcodec/itut35.h +++ b/libavcodec/itut35.h @@ -19,6 +19,13 @@ #ifndef AVCODEC_ITUT35_H #define AVCODEC_ITUT35_H +#include <stdint.h> +#include <stddef.h> + +#include "libavutil/frame.h" +#include "avcodec.h" +#include "dovi_rpu.h" + #define ITU_T_T35_COUNTRY_CODE_CN 0x26 #define ITU_T_T35_COUNTRY_CODE_UK 0xB4 #define ITU_T_T35_COUNTRY_CODE_US 0xB5 @@ -39,4 +46,87 @@ #define ITU_T_T35_PROVIDER_CODE_SAMSUNG 0x003C #define ITU_T_T35_PROVIDER_CODE_SMPTE 0x0090 +typedef struct FFITUTT35 { + int country_code; + + int provider_code; + int provider_oriented_code; + + const uint8_t *payload; + size_t payload_size; +} FFITUTT35; + +typedef struct FFITUTT35Meta { + AVBufferRef *a53_cc; + AVBufferRef *lcevc; + AVBufferRef *hdrplus; + AVBufferRef *hdr_smpte2094_app5; + AVBufferRef *dovi; +} FFITUTT35Meta; + +typedef struct FFITUTT35Aux { + /** + * A DOVIContext. Must be set to a valid pointer in order to be parsed + * and filled. + */ + DOVIContext *dovi; +} FFITUTT35Aux; + +/** + * country_code is assumed to not be the first byte of the buffer and must + * be set by the caller beforehand. + */ +#define FF_ITUT_T35_FLAG_COUNTRY_CODE (1 << 0) + +/** + * Parse a raw ITU-T T35 buffer to get the country code, provider code, + * and set them plus the pointer and size in the FFITUTT35 struct to the + * start of the actual payload. + * + * @param itut35 The struct to fill + * @param buf The input buffer + * @param size Size of the input buffer + * @param flags A combination of FF_ITUT_T35_FLAG_* + * @return 0 if nothing was done (e.g. the payload is of an unsupported + * type), 1 on succes, or a negative AVERROR code on failure + * + * @note buf will remain owned by the caller, and no new allocations will + * be made. Any pointer in the resulting struct will be valid as long + * as buf is valid. + */ +int ff_itut_t35_parse_buffer(FFITUTT35 *itut35, const uint8_t *buf, + size_t size, int flags); + +/** + * Parse a pre-processed ITU-T T35 payload to fill the metadata struct. + * + * @param avctx Used for logging and to get certain user options like + * err_recognition + * @param itut35 The pre-filled struct + * @param metadata A metadata struct. All the allocated buffer references + * are owned by the caller and must be freed accordingly. + * @param aux A struct containing extra contexts required by certain + * payload types. Any pointer present is owned by the caller. + * May be NULL, in which case the relevant payloads will not + * be parsed. + * @return 0 on succes, or a negative AVERROR code on failure + */ +int ff_itut_t35_parse_payload_to_struct(AVCodecContext *avctx, FFITUTT35 *itut_t35, + FFITUTT35Aux *aux, FFITUTT35Meta *metadata); + +/** + * Parse a pre-processed ITU-T T35 payload to fill a frame's side data. + * + * @param avctx The context that generated the frame + * @param itut35 The pre-filled struct + * @param frame A frame + * @param aux A struct containing extra contexts required by certain + * payload types. Any pointer present is owned by the caller. + * May be NULL, in which case the relevant payloads will not + * be parsed. + * @return 0 on succes, or a negative AVERROR code on failure + */ +int ff_itut_t35_parse_payload_to_frame(AVCodecContext *avctx, FFITUTT35 *itut_t35, + FFITUTT35Aux *aux, AVFrame *frame); + #endif /* AVCODEC_ITUT35_H */ -- 2.52.0 >From 4cfa175db31c175e295451c195f90e8e96a25bf0 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Fri, 29 May 2026 12:13:15 -0300 Subject: [PATCH 2/4] avcodec/av1dec: use the ITU-T T35 parsing helpers Signed-off-by: James Almer <[email protected]> --- libavcodec/Makefile | 2 +- libavcodec/av1dec.c | 114 ++++---------------------------------------- 2 files changed, 11 insertions(+), 105 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ac3c4d1978..7bd0c0b6bd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -272,7 +272,7 @@ OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \ OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o -OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o +OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o itut35.o OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_AV1_D3D12VA_ENCODER) += d3d12va_encode_av1.o av1_levels.o OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 78edb3c8d4..30cc171973 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -968,113 +968,19 @@ fail: static int export_itut_t35(AVCodecContext *avctx, AVFrame *frame, const AV1RawMetadataITUTT35 *itut_t35) { - GetByteContext gb; AV1DecContext *s = avctx->priv_data; - int ret, provider_code, country_code; + FFITUTT35 itut35 = { .country_code = itut_t35->itu_t_t35_country_code }; + FFITUTT35Aux aux = { .dovi = &s->dovi }; + int ret; - bytestream2_init(&gb, itut_t35->payload, itut_t35->payload_size); + ret = ff_itut_t35_parse_buffer(&itut35, itut_t35->payload, itut_t35->payload_size, + FF_ITUT_T35_FLAG_COUNTRY_CODE); + if (ret <= 0) + return ret; - country_code = itut_t35->itu_t_t35_country_code ; - switch (country_code) { - case ITU_T_T35_COUNTRY_CODE_US: - provider_code = bytestream2_get_be16(&gb); - - switch (provider_code) { - case ITU_T_T35_PROVIDER_CODE_ATSC: { - uint32_t user_identifier = bytestream2_get_be32(&gb); - switch (user_identifier) { - case MKBETAG('G', 'A', '9', '4'): { // closed captions - AVBufferRef *buf = NULL; - - ret = ff_parse_a53_cc(&buf, gb.buffer, bytestream2_get_bytes_left(&gb)); - if (ret < 0) - return ret; - if (!ret) - break; - - ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_A53_CC, &buf); - if (ret < 0) - return ret; - -#if FF_API_CODEC_PROPS -FF_DISABLE_DEPRECATION_WARNINGS - avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - break; - } - default: // ignore unsupported identifiers - break; - } - break; - } - case ITU_T_T35_PROVIDER_CODE_SAMSUNG: { - AVDynamicHDRPlus *hdrplus; - int provider_oriented_code = bytestream2_get_be16(&gb); - int application_identifier = bytestream2_get_byte(&gb); - - if (provider_oriented_code != 1 || application_identifier != 4) - return 0; // ignore - - hdrplus = av_dynamic_hdr_plus_create_side_data(frame); - if (!hdrplus) - return AVERROR(ENOMEM); - - ret = av_dynamic_hdr_plus_from_t35(hdrplus, gb.buffer, - bytestream2_get_bytes_left(&gb)); - if (ret < 0) - return ret; - break; - } - case ITU_T_T35_PROVIDER_CODE_DOLBY: { - int provider_oriented_code = bytestream2_get_be32(&gb); - if (provider_oriented_code != 0x800) - return 0; // ignore - - ret = ff_dovi_rpu_parse(&s->dovi, gb.buffer, bytestream2_get_bytes_left(&gb), - avctx->err_recognition); - if (ret < 0) { - av_log(avctx, AV_LOG_WARNING, "Error parsing DOVI OBU.\n"); - return 0; // ignore - } - - ret = ff_dovi_attach_side_data(&s->dovi, frame); - if (ret < 0) - return ret; - break; - } - default: - break; - } - break; - case ITU_T_T35_COUNTRY_CODE_UK: - bytestream2_skip(&gb, 1); // t35_uk_country_code_second_octet - - provider_code = bytestream2_get_be16(&gb); - switch (provider_code) { - case ITU_T_T35_PROVIDER_CODE_VNOVA: { - AVFrameSideData *sd; - if (bytestream2_get_bytes_left(&gb) < 2) - return AVERROR_INVALIDDATA; - - ret = ff_frame_new_side_data(avctx, frame, AV_FRAME_DATA_LCEVC, - bytestream2_get_bytes_left(&gb), &sd); - if (ret < 0) - return ret; - if (!sd) - break; - - bytestream2_get_bufferu(&gb, sd->data, sd->size); - break; - } - default: - break; - } - break; - default: - // ignore unsupported provider codes - break; - } + ret = ff_itut_t35_parse_payload_to_frame(avctx, &itut35, &aux, frame); + if (ret < 0) + return ret; return 0; } -- 2.52.0 >From 60ba2d8517fa785646621b155b4b98f2cf6440fd Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Fri, 29 May 2026 12:13:25 -0300 Subject: [PATCH 3/4] avcodec/libdav1d: use the ITU-T T35 parsing helpers Signed-off-by: James Almer <[email protected]> --- libavcodec/Makefile | 2 +- libavcodec/libdav1d.c | 133 +++--------------------------------------- 2 files changed, 10 insertions(+), 125 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7bd0c0b6bd..3439e6a1e4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1176,7 +1176,7 @@ OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o -OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o av1_parse.o +OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o av1_parse.o itut35.o OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 2eaeefc71a..f377f3a3d0 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -364,134 +364,19 @@ static int libdav1d_receive_frame_internal(AVCodecContext *c, Dav1dPicture *p) static int parse_itut_t35_metadata(Libdav1dContext *dav1d, Dav1dPicture *p, const Dav1dITUTT35 *itut_t35, AVCodecContext *c, AVFrame *frame) { - GetByteContext gb; - int provider_code, country_code; + FFITUTT35 itut35 = { .country_code = itut_t35->country_code }; + FFITUTT35Aux aux = { .dovi = &dav1d->dovi }; int res; - bytestream2_init(&gb, itut_t35->payload, itut_t35->payload_size); + res = ff_itut_t35_parse_buffer(&itut35, itut_t35->payload, itut_t35->payload_size, + FF_ITUT_T35_FLAG_COUNTRY_CODE); + if (res <= 0) + return res; - country_code = itut_t35->country_code; - switch (country_code) { - case ITU_T_T35_COUNTRY_CODE_US: - if (bytestream2_get_bytes_left(&gb) < 2) - return AVERROR_INVALIDDATA; - provider_code = bytestream2_get_be16u(&gb); + res = ff_itut_t35_parse_payload_to_frame(c, &itut35, &aux, frame); + if (res < 0) + return res; - switch (provider_code) { - case ITU_T_T35_PROVIDER_CODE_ATSC: { - uint32_t user_identifier = bytestream2_get_be32(&gb); - switch (user_identifier) { - case MKBETAG('G', 'A', '9', '4'): { // closed captions - AVBufferRef *buf = NULL; - - res = ff_parse_a53_cc(&buf, gb.buffer, bytestream2_get_bytes_left(&gb)); - if (res < 0) - return res; - if (!res) - return 0; // no cc found, ignore - - res = ff_frame_new_side_data_from_buf(c, frame, AV_FRAME_DATA_A53_CC, &buf); - if (res < 0) - return res; - -#if FF_API_CODEC_PROPS -FF_DISABLE_DEPRECATION_WARNINGS - c->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - break; - } - default: // ignore unsupported identifiers - break; - } - break; - } - case ITU_T_T35_PROVIDER_CODE_SAMSUNG: { - AVDynamicHDRPlus *hdrplus; - int provider_oriented_code = bytestream2_get_be16(&gb); - int application_identifier = bytestream2_get_byte(&gb); - - if (provider_oriented_code != 1 || application_identifier != 4) - return 0; // ignore - - hdrplus = av_dynamic_hdr_plus_create_side_data(frame); - if (!hdrplus) - return AVERROR(ENOMEM); - - res = av_dynamic_hdr_plus_from_t35(hdrplus, gb.buffer, - bytestream2_get_bytes_left(&gb)); - if (res < 0) - return res; - break; - } - case ITU_T_T35_PROVIDER_CODE_DOLBY: { - int provider_oriented_code = bytestream2_get_be32(&gb); - if (provider_oriented_code != 0x800) - return 0; // ignore - - res = ff_dovi_rpu_parse(&dav1d->dovi, gb.buffer, bytestream2_get_bytes_left(&gb), - c->err_recognition); - if (res < 0) { - av_log(c, AV_LOG_WARNING, "Error parsing DOVI OBU.\n"); - return 0; // ignore - } - - res = ff_dovi_attach_side_data(&dav1d->dovi, frame); - if (res < 0) - return res; - break; - } - case ITU_T_T35_PROVIDER_CODE_SMPTE: { - AVDynamicHDRSmpte2094App5 *hdr_smpte2094_app5; - int provider_oriented_code = bytestream2_get_be16(&gb); - if (provider_oriented_code != 1) - return 0; // ignore - - hdr_smpte2094_app5 = av_dynamic_hdr_smpte2094_app5_create_side_data(frame); - if (!hdr_smpte2094_app5) - return AVERROR(ENOMEM); - - res = av_dynamic_hdr_smpte2094_app5_from_t35(hdr_smpte2094_app5, gb.buffer, - bytestream2_get_bytes_left(&gb)); - if (res < 0) - return res; - break; - } - default: - break; - } - break; - case ITU_T_T35_COUNTRY_CODE_UK: - bytestream2_skipu(&gb, 1); // t35_uk_country_code_second_octet - if (bytestream2_get_bytes_left(&gb) < 2) - return AVERROR_INVALIDDATA; - - provider_code = bytestream2_get_be16u(&gb); - switch (provider_code) { - case ITU_T_T35_PROVIDER_CODE_VNOVA: { - AVFrameSideData *sd; - if (bytestream2_get_bytes_left(&gb) < 2) - return AVERROR_INVALIDDATA; - - res = ff_frame_new_side_data(c, frame, AV_FRAME_DATA_LCEVC, - bytestream2_get_bytes_left(&gb), &sd); - if (res < 0) - return res; - if (!sd) - break; - - bytestream2_get_bufferu(&gb, sd->data, sd->size); - break; - } - default: - break; - } - break; - - default: - // ignore unsupported provider codes - break; - } return 0; } -- 2.52.0 >From fcca7432aae9b815446a2e5965a6f711386a8c95 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Fri, 29 May 2026 14:08:57 -0300 Subject: [PATCH 4/4] avcodec/libaomdec: use the ITU-T T35 parsing helpers Signed-off-by: James Almer <[email protected]> --- libavcodec/Makefile | 2 +- libavcodec/libaomdec.c | 40 ++++++++++++++-------------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3439e6a1e4..baf642f390 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1170,7 +1170,7 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o -OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o +OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o itut35.o OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 79b299bac8..50bfdb693b 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -143,40 +143,28 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) } } -static int decode_metadata_itu_t_t35(AVFrame *frame, +static int decode_metadata_itu_t_t35(AVCodecContext *avctx, AVFrame *frame, const uint8_t *buffer, size_t buffer_size) { + FFITUTT35 itut35 = { 0 }; + int ret; + if (buffer_size < 6) return AVERROR(EINVAL); - GetByteContext bc; - bytestream2_init(&bc, buffer, buffer_size); + ret = ff_itut_t35_parse_buffer(&itut35, buffer, buffer_size, 0); + if (ret <= 0) + return ret; - const int country_code = bytestream2_get_byteu(&bc); - const int provider_code = bytestream2_get_be16u(&bc); - const int provider_oriented_code = bytestream2_get_be16u(&bc); - const int application_identifier = bytestream2_get_byteu(&bc); - - // See "HDR10+ AV1 Metadata Handling Specification" v1.0.1, Section 2.1. - if (country_code == ITU_T_T35_COUNTRY_CODE_US - && provider_code == ITU_T_T35_PROVIDER_CODE_SAMSUNG - && provider_oriented_code == 0x0001 - && application_identifier == 0x04) { - // HDR10+ - AVDynamicHDRPlus *hdr_plus = av_dynamic_hdr_plus_create_side_data(frame); - if (!hdr_plus) - return AVERROR(ENOMEM); - - int res = av_dynamic_hdr_plus_from_t35(hdr_plus, bc.buffer, - bytestream2_get_bytes_left(&bc)); - if (res < 0) - return res; - } + ret = ff_itut_t35_parse_payload_to_frame(avctx, &itut35, NULL, frame); + if (ret < 0) + return ret; return 0; } -static int decode_metadata(AVFrame *frame, const struct aom_image *img) +static int decode_metadata(AVCodecContext *avctx, AVFrame *frame, + const struct aom_image *img) { const size_t num_metadata = aom_img_num_metadata(img); for (size_t i = 0; i < num_metadata; ++i) { @@ -186,7 +174,7 @@ static int decode_metadata(AVFrame *frame, const struct aom_image *img) switch (metadata->type) { case OBU_METADATA_TYPE_ITUT_T35: { - int res = decode_metadata_itu_t_t35(frame, metadata->payload, metadata->sz); + int res = decode_metadata_itu_t_t35(avctx, frame, metadata->payload, metadata->sz); if (res < 0) return res; break; @@ -276,7 +264,7 @@ static int aom_decode(AVCodecContext *avctx, AVFrame *picture, av_image_copy(picture->data, picture->linesize, planes, stride, avctx->pix_fmt, img->d_w, img->d_h); } - ret = decode_metadata(picture, img); + ret = decode_metadata(avctx, picture, img); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to decode metadata\n"); return ret; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
