PR #23522 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23522 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23522.patch
>From 114ec661084966e36c51209108582c22fb98ca19 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 17 Jun 2026 22:11:53 +0200 Subject: [PATCH 1/2] avformat/matroskaenc: Extend EBML writer to write lists of buffers This is intended for LCEVC where an EBML buffer is assembled by prepending a short header to an already existing buffer. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/matroskaenc.c | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 97d66558f8..0d0cd0832b 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -116,8 +116,15 @@ typedef enum EbmlType { EBML_BIN, EBML_BLOCK, ///< pseudo-type for writing (Simple)Blocks EBML_MASTER, + EBML_BUFARRAY, ///< pseudo-type for writing an array of BufEntry, + ///< terminated by a BufEntry with data == NULL. } EbmlType; +typedef struct BufEntry { + const void *data; + size_t size; +} BufEntry; + typedef struct BlockContext { struct mkv_track *track; const AVPacket *pkt; @@ -144,6 +151,7 @@ typedef struct EbmlElement { const uint8_t *bin; struct MatroskaMuxContext *mkv; ///< used by EBML_BLOCK EbmlMaster master; + const BufEntry *bufs; } priv; } EbmlElement; @@ -585,6 +593,14 @@ static void ebml_writer_add_block(EbmlWriter *writer, MatroskaMuxContext *mkv) elem->priv.mkv = mkv; } +static void ebml_writer_add_bufarray(EbmlWriter *writer, uint32_t id, + const BufEntry *bufs) +{ + EbmlElement *elem = ebml_writer_add(writer, id, EBML_BUFARRAY); + av_assert2(bufs && bufs->data); + elem->priv.bufs = bufs; +} + static int ebml_writer_str_len(EbmlElement *elem) { size_t len = strlen(elem->priv.str); @@ -676,6 +692,22 @@ static int ebml_writer_block_len(EbmlElement *elem) return 0; } +static int ebml_writer_buf_array_len(EbmlElement *elem) +{ + const BufEntry *bufs = elem->priv.bufs; + uint64_t total_size = 0; + + do { + if (bufs->size > UINT64_MAX - total_size) + return AVERROR(ERANGE); + total_size += bufs->size; + } while ((++bufs)->data); + + elem->size = total_size; + + return 0; +} + static void ebml_writer_write_block(const EbmlElement *elem, AVIOContext *pb) { MatroskaMuxContext *const mkv = elem->priv.mkv; @@ -722,6 +754,9 @@ static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem, case EBML_MASTER: ret = ebml_writer_master_len(writer, elem, remaining_elems); break; + case EBML_BUFARRAY: + ret = ebml_writer_buf_array_len(elem); + break; } if (ret < 0) return ret; @@ -770,6 +805,13 @@ static int ebml_writer_elem_write(const EbmlElement *elem, AVIOContext *pb) return nb_elems; } + case EBML_BUFARRAY: { + const BufEntry *bufs = elem->priv.bufs; + do { + avio_write(pb, bufs->data, bufs->size); + } while ((++bufs)->data); + break; + } } return 0; } -- 2.52.0 >From 1c090a57ea7a3a03c391258c74393239af0596c2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 17 Jun 2026 22:51:41 +0200 Subject: [PATCH 2/2] avformat/matroskaenc: Avoid tmp buffer when writing LCEVC side data Also avoid an av_free() call in the ordinary case when there is no LCEVC side data. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/matroskaenc.c | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 0d0cd0832b..e091761ba9 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2903,6 +2903,16 @@ static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf, ebml_writer_close_master(writer); } +static void mkv_add_blockadditional_bufarray(EbmlWriter *writer, + const BufEntry *bufs, + uint64_t additional_id) +{ + ebml_writer_open_master(writer, MATROSKA_ID_BLOCKMORE); + ebml_writer_add_uint(writer, MATROSKA_ID_BLOCKADDID, additional_id); + ebml_writer_add_bufarray(writer, MATROSKA_ID_BLOCKADDITIONAL, bufs); + ebml_writer_close_master(writer); +} + static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, AVIOContext *pb, const AVStream *st, mkv_track *track, const AVPacket *pkt, @@ -2913,7 +2923,8 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, uint8_t t35_buf[6 + AV_HDR_PLUS_MAX_PAYLOAD_SIZE]; #define SMPTE_2094_APP5_MAX_SIZE 855 uint8_t smpte_2094_app5_buf[5 + SMPTE_2094_APP5_MAX_SIZE]; - uint8_t *lcevc = NULL; + BufEntry lcevc_buffers[3]; + uint8_t lcevc_header[4]; uint8_t *side_data; size_t side_data_size; uint64_t additional_id; @@ -3033,19 +3044,16 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_LCEVC, &side_data_size); if (side_data) { - size_t payload_size = side_data_size + 4; + AV_WB8 (lcevc_header + 0, ITU_T_T35_COUNTRY_CODE_UK); + AV_WB8 (lcevc_header + 1, 0); // t35_uk_country_code_second_octet + AV_WB16(lcevc_header + 2, ITU_T_T35_PROVIDER_CODE_VNOVA); + lcevc_buffers[0] = (BufEntry){ .data = lcevc_header, .size = 4 }; + lcevc_buffers[1] = (BufEntry){ .data = side_data, + .size = side_data_size }; + lcevc_buffers[2].data = NULL; - lcevc = av_malloc(payload_size); - if (!lcevc) - return AVERROR(ENOMEM); - - AV_WB8 (lcevc + 0, ITU_T_T35_COUNTRY_CODE_UK); - AV_WB8 (lcevc + 1, 0); // t35_uk_country_code_second_octet - AV_WB16(lcevc + 2, ITU_T_T35_PROVIDER_CODE_VNOVA); - memcpy (lcevc + 4, side_data, side_data_size); - - mkv_write_blockadditional(&writer, lcevc, payload_size, - MATROSKA_BLOCK_ADD_ID_ITU_T_T35); + mkv_add_blockadditional_bufarray(&writer, lcevc_buffers, + MATROSKA_BLOCK_ADD_ID_ITU_T_T35); track->max_blockaddid = FFMAX(track->max_blockaddid, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); } @@ -3065,11 +3073,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE, track->last_timestamp - ts); - ret = ebml_writer_write(&writer, pb); - - av_free(lcevc); - - return ret; + return ebml_writer_write(&writer, pb); } static int mkv_end_cluster(AVFormatContext *s) -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
