Commit d1434518fb for ffmpeg
commit d1434518fbd03789e3e5dc0657a7a9f1123ce074
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Mon Sep 28 15:38:10 2026 +0200
avutil/encryption_info: add av_encryption_init_info_append_side_data()
Appends to already serialized init info side data, growing it with
av_fast_realloc(), so a demuxer can collect pssh records in linear time
without depending on the side data format.
diff --git a/doc/APIchanges b/doc/APIchanges
index 4e02c0996d..42d539990f 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2026-06-23.
API changes, most recent first:
+2026-10-xx - xxxxxxxxxx - lavu 61.15.100 - encryption_info.h
+ Add av_encryption_init_info_append_side_data().
+
2026-10-18 - xxxxxxxxxx - lavc 63.21.100 - codec_id.h
Add AV_CODEC_ID_IMM6.
diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 6fc3e33842..9643840157 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -19,6 +19,7 @@
#include <string.h>
#include "encryption_info.h"
+#include "error.h"
#include "mem.h"
#include "intreadwrite.h"
@@ -295,37 +296,36 @@ AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
return ret;
}
-uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info, size_t *side_data_size)
+int av_encryption_init_info_append_side_data(uint8_t **side_data, size_t *side_data_size,
+ unsigned int *allocated_size,
+ const AVEncryptionInitInfo *info)
{
const AVEncryptionInitInfo *cur_info;
uint8_t *buffer, *cur_buffer;
- uint32_t i, init_info_count;
- uint64_t temp_side_data_size;
+ uint32_t i;
+ uint64_t init_info_count = *side_data ? AV_RB32(*side_data) : 0;
+ size_t old_side_data_size = *side_data ? *side_data_size : 4;
+ uint64_t new_side_data_size = old_side_data_size;
- temp_side_data_size = 4;
- init_info_count = 0;
for (cur_info = info; cur_info; cur_info = cur_info->next) {
- temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + cur_info->system_id_size + cur_info->data_size;
- if (init_info_count == UINT32_MAX || temp_side_data_size > UINT32_MAX) {
- return NULL;
- }
+ new_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + cur_info->system_id_size + cur_info->data_size;
+ if (init_info_count == UINT32_MAX || new_side_data_size > UINT32_MAX)
+ return AVERROR(EINVAL);
init_info_count++;
if (cur_info->num_key_ids) {
- temp_side_data_size += (uint64_t)cur_info->num_key_ids * cur_info->key_id_size;
- if (temp_side_data_size > UINT32_MAX) {
- return NULL;
- }
+ new_side_data_size += (uint64_t)cur_info->num_key_ids * cur_info->key_id_size;
+ if (new_side_data_size > UINT32_MAX)
+ return AVERROR(EINVAL);
}
}
- *side_data_size = temp_side_data_size;
- cur_buffer = buffer = av_malloc(*side_data_size);
+ buffer = av_fast_realloc(*side_data, allocated_size, new_side_data_size);
if (!buffer)
- return NULL;
+ return AVERROR(ENOMEM);
- AV_WB32(cur_buffer, init_info_count);
- cur_buffer += 4;
+ AV_WB32(buffer, init_info_count);
+ cur_buffer = buffer + old_side_data_size;
for (cur_info = info; cur_info; cur_info = cur_info->next) {
AV_WB32(cur_buffer, cur_info->system_id_size);
AV_WB32(cur_buffer + 4, cur_info->num_key_ids);
@@ -345,5 +345,17 @@ uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info,
}
}
- return buffer;
+ *side_data = buffer;
+ *side_data_size = new_side_data_size;
+ return 0;
+}
+
+uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info, size_t *side_data_size)
+{
+ uint8_t *side_data = NULL;
+ unsigned int allocated_size = 0;
+
+ if (av_encryption_init_info_append_side_data(&side_data, side_data_size, &allocated_size, info) < 0)
+ return NULL;
+ return side_data;
}
diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
index 8fe7ebfe43..6fd39cf02c 100644
--- a/libavutil/encryption_info.h
+++ b/libavutil/encryption_info.h
@@ -202,4 +202,21 @@ AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
uint8_t *av_encryption_init_info_add_side_data(
const AVEncryptionInitInfo *info, size_t *side_data_size);
+/**
+ * Appends a copy of the given encryption init info list to encryption init
+ * info side data, growing the side data with av_fast_realloc().
+ *
+ * @param side_data Side data created by this function or
+ * av_encryption_init_info_add_side_data(), *side_data
+ * may be NULL to create new side data.
+ * @param side_data_size Size of *side_data.
+ * @param allocated_size Allocated size of *side_data, as for av_fast_realloc().
+ * @param info The list to append.
+ * @return 0 on success, a negative AVERROR code on failure, in which case
+ * *side_data and *side_data_size are unchanged.
+ */
+int av_encryption_init_info_append_side_data(
+ uint8_t **side_data, size_t *side_data_size, unsigned int *allocated_size,
+ const AVEncryptionInitInfo *info);
+
#endif /* AVUTIL_ENCRYPTION_INFO_H */
diff --git a/libavutil/tests/encryption_info.c b/libavutil/tests/encryption_info.c
index 55c668c6d5..d8f0187ef9 100644
--- a/libavutil/tests/encryption_info.c
+++ b/libavutil/tests/encryption_info.c
@@ -141,8 +141,9 @@ static AVEncryptionInitInfo *create_init_info(void)
static void run_encryption_init_info_test(void)
{
AVEncryptionInitInfo *info, *copy;
- uint8_t *side_data;
- size_t side_data_size;
+ uint8_t *side_data, *appended;
+ size_t side_data_size, appended_size;
+ unsigned int allocated_size = 0;
info = create_init_info();
@@ -157,6 +158,8 @@ static void run_encryption_init_info_test(void)
// Make the first init info different from the second to test the correct order.
memset(info->system_id, 0, info->system_id_size);
+ appended = av_encryption_init_info_add_side_data(info, &appended_size);
+ av_assert0(appended);
info->next = create_init_info();
side_data = av_encryption_init_info_add_side_data(info, &side_data_size);
av_assert0(side_data);
@@ -164,6 +167,11 @@ static void run_encryption_init_info_test(void)
av_assert0(copy);
av_assert0(compare_encryption_init_info(info, copy) == 0);
av_encryption_init_info_free(copy);
+
+ av_assert0(av_encryption_init_info_append_side_data(&appended, &appended_size, &allocated_size, info->next) == 0);
+ av_assert0(appended_size == side_data_size);
+ av_assert0(memcmp(appended, side_data, side_data_size) == 0);
+ av_free(appended);
av_free(side_data);
av_encryption_init_info_free(info);
diff --git a/libavutil/version.h b/libavutil/version.h
index ed6abeab78..9f1429987a 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 61
-#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MINOR 15
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \