diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 9ec1feb068..750a17de48 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -646,3 +646,102 @@ int ff_side_data_set_prft(AVPacket *pkt, int64_t timestamp)
 
     return 0;
 }
+
+const AVPacketSideData *av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd,
+                                                enum AVPacketSideDataType type)
+{
+    for (int i = 0; i < nb_sd; i++)
+        if (sd[i].type == type)
+            return &sd[i];
+
+    return NULL;
+}
+
+static AVPacketSideData *packet_side_data_add(AVPacketSideData **psd, int *pnb_sd,
+                                              enum AVPacketSideDataType type,
+                                              void *data, size_t size)
+{
+    AVPacketSideData *sd = *psd, *tmp;
+    int nb_sd = *pnb_sd;
+
+    for (int i = 0; i < nb_sd; i++) {
+        if (sd[i].type != type)
+            continue;
+
+        av_free(sd[i].data);
+        sd[i].data = data;
+        sd[i].size = size;
+        return &sd[i];
+    }
+
+    if (nb_sd + 1U > INT_MAX)
+        return NULL;
+
+    tmp = av_realloc_array(sd, nb_sd + 1, sizeof(*tmp));
+    if (!tmp)
+        return NULL;
+
+    *psd = sd = tmp;
+    sd[nb_sd].type = type;
+    sd[nb_sd].data = data;
+    sd[nb_sd].size = size;
+    *pnb_sd = nb_sd + 1;
+
+    return &sd[nb_sd];
+}
+
+AVPacketSideData *av_packet_side_data_add(AVPacketSideData **psd, int *pnb_sd,
+                                          enum AVPacketSideDataType type,
+                                          void *data, size_t size, int flags)
+{
+    return packet_side_data_add(psd, pnb_sd, type, data, size);
+}
+
+AVPacketSideData *av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd,
+                                          enum AVPacketSideDataType type,
+                                          size_t size, int flags)
+{
+    AVPacketSideData *sd = NULL;
+    void *data;
+
+    if (size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
+        return NULL;
+
+    data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!data)
+        return NULL;
+
+    sd = packet_side_data_add(psd, pnb_sd, type, data, size);
+    if (!sd)
+        av_freep(&data);
+
+    return sd;
+}
+
+void av_packet_side_data_remove(AVPacketSideData *sd, int *pnb_sd,
+                                enum AVPacketSideDataType type)
+{
+    int nb_sd = *pnb_sd;
+
+    for (int i = nb_sd - 1; i >= 0; i--) {
+        if (sd[i].type != type)
+            continue;
+        av_free(sd[i].data);
+        sd[i] = sd[--nb_sd];
+        break;
+    }
+
+    *pnb_sd = nb_sd;
+}
+
+void av_packet_side_data_free(AVPacketSideData **psd, int *pnb_sd)
+{
+    AVPacketSideData *sd = *psd;
+    int nb_sd = *pnb_sd;
+
+    for (int i = 0; i < nb_sd; i++)
+        av_free(sd[i].data);
+
+    av_freep(psd);
+    *pnb_sd = 0;
+}
diff --git a/libavcodec/packet.h b/libavcodec/packet.h
index f28e7e7011..96fc0084d6 100644
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -33,9 +33,9 @@
 #include "libavcodec/version_major.h"
 
 /**
- * @defgroup lavc_packet AVPacket
+ * @defgroup lavc_packet_side_data AVPacketSideData
  *
- * Types and functions for working with AVPacket.
+ * Types and functions for working with AVPacketSideData.
  * @{
  */
 enum AVPacketSideDataType {
@@ -318,6 +318,96 @@ typedef struct AVPacketSideData {
     enum AVPacketSideDataType type;
 } AVPacketSideData;
 
+/**
+ * Allocate a new packet side data.
+ *
+ * @param sd    pointer to an array of side data to which the side data should
+ *              be added. *sd may be NULL, in which case the array will be
+ *              initialized.
+ * @param nb_sd pointer to an integer containing the number of entries in
+ *              the array. The integer value will be increased by 1 on success.
+ * @param type  side data type
+ * @param size  desired side data size
+ * @param flags currently unused. Must be zero
+ *
+ * @return pointer to freshly allocated side data on success, or NULL otherwise.
+ */
+AVPacketSideData *av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd,
+                                          enum AVPacketSideDataType type,
+                                          size_t size, int flags);
+
+/**
+ * Wrap existing data as packet side data.
+ *
+ * @param sd    pointer to an array of side data to which the side data should
+ *              be added. *sd may be NULL, in which case the array will be
+ *              initialized
+ * @param nb_sd pointer to an integer containing the number of entries in
+ *              the array. The integer value will be increased by 1 on success.
+ * @param type  side data type
+ * @param data  a data array. It must be allocated with the av_malloc() family
+ *              of functions. The ownership of the data is transferred to the
+ *              side data array on success
+ * @param size  size of the data array
+ * @param flags currently unused. Must be zero
+ *
+ * @return pointer to freshly allocated side data on success, or NULL otherwise
+ *         On failure, the side data array is unchanged and the data remains
+ *         owned by the caller.
+ */
+AVPacketSideData *av_packet_side_data_add(AVPacketSideData **sd, int *nb_sd,
+                                          enum AVPacketSideDataType type,
+                                          void *data, size_t size, int flags);
+
+/**
+ * Get side information from a side data array.
+ *
+ * @param sd    the array from which the side data should be fetched
+ * @param nb_sd value containing the number of entries in the array.
+ * @param type  desired side information type
+ *
+ * @return pointer to side data if present or NULL otherwise
+ */
+const AVPacketSideData *av_packet_side_data_get(const AVPacketSideData *sd,
+                                                int nb_sd,
+                                                enum AVPacketSideDataType type);
+
+/**
+ * Remove side data of the given type from a side data array.
+ *
+ * @param sd    the array from which the side data should be removed
+ * @param nb_sd pointer to an integer containing the number of entries in
+ *              the array. Will be reduced by the amount of entries removed
+ *              upon return
+ * @param type  side information type
+ */
+void av_packet_side_data_remove(AVPacketSideData *sd, int *nb_sd,
+                                enum AVPacketSideDataType type);
+
+/**
+ * Convenience function to free all the side data stored in an array, and
+ * the array itself.
+ *
+ * @param sd    pointer to array of side data to free. Will be set to NULL
+ *              upon return.
+ * @param nb_sd pointer to an integer containing the number of entries in
+ *              the array. Will be set to 0 upon return.
+ */
+void av_packet_side_data_free(AVPacketSideData **sd, int *nb_sd);
+
+const char *av_packet_side_data_name(enum AVPacketSideDataType type);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup lavc_packet AVPacket
+ *
+ * Types and functions for working with AVPacket.
+ * @{
+ */
+
 /**
  * This structure stores compressed data. It is typically exported by demuxers
  * and then passed as input to decoders, or received as output from encoders and
@@ -603,8 +693,6 @@ int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
 uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type,
                                  size_t *size);
 
-const char *av_packet_side_data_name(enum AVPacketSideDataType type);
-
 /**
  * Pack a dictionary for use in side_data.
  *
