This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 3dba9eb80663abf77b083878a2f6e0f77abf81a7 Author: James Almer <[email protected]> AuthorDate: Mon Feb 16 11:58:46 2026 -0300 Commit: James Almer <[email protected]> CommitDate: Sat Feb 28 16:12:33 2026 -0300 avcodec/bsf/extract_extradata: add support for LCEVC Signed-off-by: James Almer <[email protected]> --- libavcodec/bsf/extract_extradata.c | 180 +++++++++++++++++++++++++++++++++++++ libavcodec/lcevc.h | 84 +++++++++++++++++ 2 files changed, 264 insertions(+) diff --git a/libavcodec/bsf/extract_extradata.c b/libavcodec/bsf/extract_extradata.c index 43f4d62855..f7b62189fe 100644 --- a/libavcodec/bsf/extract_extradata.c +++ b/libavcodec/bsf/extract_extradata.c @@ -29,6 +29,7 @@ #include "bytestream.h" #include "h2645_parse.h" #include "h264.h" +#include "lcevc.h" #include "startcode.h" #include "vc1_common.h" #include "vvc.h" @@ -167,6 +168,9 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, static const int extradata_nal_types_vvc[] = { VVC_VPS_NUT, VVC_SPS_NUT, VVC_PPS_NUT, }; + static const int extradata_nal_types_lcevc[] = { + LCEVC_IDR_NUT, LCEVC_NON_IDR_NUT, + }; static const int extradata_nal_types_hevc[] = { HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS, }; @@ -184,6 +188,9 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { extradata_nal_types = extradata_nal_types_vvc; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_vvc); + } else if (ctx->par_in->codec_id == AV_CODEC_ID_LCEVC) { + extradata_nal_types = extradata_nal_types_lcevc; + nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_lcevc); } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { extradata_nal_types = extradata_nal_types_hevc; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc); @@ -207,6 +214,8 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { if (nal->type == HEVC_NAL_SPS) has_sps = 1; if (nal->type == HEVC_NAL_VPS) has_vps = 1; + } else if (ctx->par_in->codec_id == AV_CODEC_ID_LCEVC) { + has_sps = 1; } else { if (nal->type == H264_NAL_SPS) has_sps = 1; } @@ -217,6 +226,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, if (extradata_size && ((ctx->par_in->codec_id == AV_CODEC_ID_VVC && has_sps) || + (ctx->par_in->codec_id == AV_CODEC_ID_LCEVC && has_sps) || (ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { AVBufferRef *filtered_buf = NULL; @@ -267,6 +277,174 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, return 0; } +static inline uint64_t get_mb(GetBitContext *s) { + int more, i = 0; + uint64_t mb = 0; + + do { + int byte = get_bits(s, 8); + unsigned bits = byte & 0x7f; + more = byte & 0x80; + mb = (mb << 7) | bits; + if (++i == 10) + break; + } while (more); + + return mb; +} + +/** + * Rewrite the NALu stripping the unneeded blocks. + * Given that length fields coded inside the NALu are not aware of any emulation_3bytes + * present in the bitstream, we need to keep track of the raw buffer as we navigate + * the stripped buffer. + */ +static int write_lcevc_nalu(AVBSFContext *ctx, PutByteContext *pbc, const H2645NAL *nal) +{ + GetByteContext gbc, raw_gbc; + int sc = 0, gc = 0; + int skipped_byte_pos = 0; + + bytestream2_init(&gbc, nal->data, nal->size); + bytestream2_init(&raw_gbc, nal->raw_data, nal->raw_size); + bytestream2_put_be16(pbc, bytestream2_get_be16(&gbc)); + bytestream2_skip(&raw_gbc, 2); + + while (bytestream2_get_bytes_left(&gbc) > 1) { + GetBitContext gb; + int payload_size_type, payload_type, payload_size; + int block_size, raw_block_size, block_end; + + init_get_bits8(&gb, gbc.buffer, bytestream2_get_bytes_left(&gbc)); + + payload_size_type = get_bits(&gb, 3); + payload_type = get_bits(&gb, 5); + payload_size = payload_size_type; + if (payload_size_type == 6) + return AVERROR_PATCHWELCOME; + if (payload_size_type == 7) + payload_size = get_mb(&gb); + + block_size = raw_block_size = payload_size + (get_bits_count(&gb) >> 3); + if (block_size >= bytestream2_get_bytes_left(&gbc)) + return AVERROR_INVALIDDATA; + + block_end = bytestream2_tell(&gbc) + block_size; + // Take into account removed emulation 3bytes, as payload_size in + // the bitstream is not aware of them. + for (; skipped_byte_pos < nal->skipped_bytes; skipped_byte_pos++) { + if (nal->skipped_bytes_pos[skipped_byte_pos] >= block_end) + break; + raw_block_size++; + } + + switch (payload_type) { + case 0: + bytestream2_put_buffer(pbc, raw_gbc.buffer, raw_block_size); + sc = 1; + break; + case 1: + bytestream2_put_buffer(pbc, raw_gbc.buffer, raw_block_size); + gc = 1; + break; + case 5: + bytestream2_put_buffer(pbc, raw_gbc.buffer, raw_block_size); + break; + default: + break; + } + + bytestream2_skip(&gbc, block_size); + bytestream2_skip(&raw_gbc, raw_block_size); + } + + if (!sc && !gc) + return AVERROR_INVALIDDATA; + + bytestream2_put_byte(pbc, 0x80); // rbsp_alignment bits + + return bytestream2_tell_p(pbc); +} + +static int extract_extradata_lcevc(AVBSFContext *ctx, AVPacket *pkt, + uint8_t **data, int *size) +{ + static const int extradata_nal_types[] = { + LCEVC_IDR_NUT, LCEVC_NON_IDR_NUT, + }; + + ExtractExtradataContext *s = ctx->priv_data; + PutByteContext pb_extradata; + int extradata_size = 0, filtered_size = 0; + size_t nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types); + int i, ret = 0; + + ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, + ctx, 0, ctx->par_in->codec_id, H2645_FLAG_SMALL_PADDING); + if (ret < 0) + return ret; + + for (i = 0; i < s->h2645_pkt.nb_nals; i++) { + H2645NAL *nal = &s->h2645_pkt.nals[i]; + if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { + bytestream2_init_writer(&pb_extradata, NULL, 0); + // dummy pass to find sc, gc or ai + if (!write_lcevc_nalu(ctx, &pb_extradata, nal)) + extradata_size += nal->raw_size + 3; + } else if (s->remove) { + filtered_size += nal->raw_size + 3; + } + } + + if (extradata_size) { + AVBufferRef *filtered_buf = NULL; + PutByteContext pb_filtered_data; + uint8_t *extradata; + + if (s->remove) { + filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!filtered_buf) { + return AVERROR(ENOMEM); + } + memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } + + extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!extradata) { + av_buffer_unref(&filtered_buf); + return AVERROR(ENOMEM); + } + + *data = extradata; + *size = extradata_size; + + bytestream2_init_writer(&pb_extradata, extradata, extradata_size); + if (s->remove) + bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); + + for (i = 0; i < s->h2645_pkt.nb_nals; i++) { + H2645NAL *nal = &s->h2645_pkt.nals[i]; + if (val_in_array(extradata_nal_types, nb_extradata_nal_types, + nal->type)) { + bytestream2_put_be24(&pb_extradata, 1); //startcode + *size = write_lcevc_nalu(ctx, &pb_extradata, nal); + } else if (s->remove) { + bytestream2_put_be24(&pb_filtered_data, 1); //startcode + *size = write_lcevc_nalu(ctx, &pb_filtered_data, nal); + } + } + + if (s->remove) { + av_buffer_unref(&pkt->buf); + pkt->buf = filtered_buf; + pkt->data = filtered_buf->data; + pkt->size = filtered_size; + } + } + + return 0; +} + static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size) { @@ -371,6 +549,7 @@ static const struct { { AV_CODEC_ID_CAVS, extract_extradata_mpeg4 }, { AV_CODEC_ID_H264, extract_extradata_h2645 }, { AV_CODEC_ID_HEVC, extract_extradata_h2645 }, + { AV_CODEC_ID_LCEVC, extract_extradata_lcevc }, { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12 }, { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12 }, { AV_CODEC_ID_MPEG4, extract_extradata_mpeg4 }, @@ -441,6 +620,7 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_CAVS, AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, + AV_CODEC_ID_LCEVC, AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_MPEG4, diff --git a/libavcodec/lcevc.h b/libavcodec/lcevc.h new file mode 100644 index 0000000000..cfe4c1e6e1 --- /dev/null +++ b/libavcodec/lcevc.h @@ -0,0 +1,84 @@ +/* + * 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 + */ + +/** + * @file + * LCEVC common definitions + */ + +#ifndef AVCODEC_LCEVC_H +#define AVCODEC_LCEVC_H + +/* + * Table 17 — NAL unit type codes and NAL unit type classes in + * ISO/IEC 23094-2:2021 + */ +enum { + LCEVC_UNSPEC0_NUT = 0, + LCEVC_UNSPEC1_NUT = 1, + LCEVC_UNSPEC2_NUT = 2, + LCEVC_UNSPEC3_NUT = 3, + LCEVC_UNSPEC4_NUT = 4, + LCEVC_UNSPEC5_NUT = 5, + LCEVC_UNSPEC6_NUT = 6, + LCEVC_UNSPEC7_NUT = 7, + LCEVC_UNSPEC8_NUT = 8, + LCEVC_UNSPEC9_NUT = 9, + LCEVC_UNSPEC10_NUT = 10, + LCEVC_UNSPEC11_NUT = 11, + LCEVC_UNSPEC12_NUT = 12, + LCEVC_UNSPEC13_NUT = 13, + LCEVC_UNSPEC14_NUT = 14, + LCEVC_UNSPEC15_NUT = 15, + LCEVC_UNSPEC16_NUT = 16, + LCEVC_UNSPEC17_NUT = 17, + LCEVC_UNSPEC18_NUT = 18, + LCEVC_UNSPEC19_NUT = 19, + LCEVC_UNSPEC20_NUT = 20, + LCEVC_UNSPEC21_NUT = 21, + LCEVC_UNSPEC22_NUT = 22, + LCEVC_UNSPEC23_NUT = 23, + LCEVC_UNSPEC24_NUT = 24, + LCEVC_UNSPEC25_NUT = 25, + LCEVC_UNSPEC26_NUT = 26, + LCEVC_UNSPEC27_NUT = 27, + LCEVC_NON_IDR_NUT = 28, + LCEVC_IDR_NUT = 29, + LCEVC_RSV_NUT = 30, + LCEVC_UNSPEC31_NUT = 31, +}; + +/* + * Table 19 — Content of payload + */ +enum { + LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG = 0, + LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG = 1, + LCEVC_PAYLOAD_TYPE_PICTURE_CONFIG = 2, + LCEVC_PAYLOAD_TYPE_ENCODED_DATA = 3, + LCEVC_PAYLOAD_TYPE_ENCODED_DATA_TILED = 4, + LCEVC_PAYLOAD_TYPE_ADDITIONAL_INFO = 5, + LCEVC_PAYLOAD_TYPE_FILLER = 6, +}; + +enum { + LCEVC_ADDITIONAL_INFO_TYPE_SEI = 0, + LCEVC_ADDITIONAL_INFO_TYPE_VUI = 1, +}; + +#endif /* AVCODEC_LCEVC_H */ _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
