[FFmpeg-devel] [PATCH 2/3] lavc/decode: make sure side data mapping does not produce duplicates

Anton Khirnov anton at khirnov.net
Sun Sep 22 21:00:04 EEST 2024


Also, deduplicate the code performing the mapping.
---
 libavcodec/decode.c | 98 +++++++++++++++++++++++++--------------------
 1 file changed, 54 insertions(+), 44 deletions(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 57cca44d05..9303254ef3 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1400,14 +1400,50 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
     return ret;
 }
 
+static const AVPacketSideData*
+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;
+}
+
 const AVPacketSideData *ff_get_coded_side_data(const AVCodecContext *avctx,
                                                enum AVPacketSideDataType type)
 {
-    for (int i = 0; i < avctx->nb_coded_side_data; i++)
-        if (avctx->coded_side_data[i].type == type)
-            return &avctx->coded_side_data[i];
+    return packet_side_data_get(avctx->coded_side_data, avctx->nb_coded_side_data, type);
+}
 
-    return NULL;
+static int side_data_map(AVFrame *dst,
+                         const AVPacketSideData *sd_src, int nb_sd_src,
+                         const SideDataMap *map)
+
+{
+    for (int i = 0; map[i].packet < AV_PKT_DATA_NB; i++) {
+        const enum AVFrameSideDataType type_pkt   = map[i].packet;
+        const enum AVFrameSideDataType type_frame = map[i].frame;
+        const AVPacketSideData *sd_pkt;
+        AVFrameSideData *sd_frame;
+
+        sd_pkt = packet_side_data_get(sd_src, nb_sd_src, type_pkt);
+        if (!sd_pkt)
+            continue;
+
+        sd_frame = av_frame_get_side_data(dst, type_frame);
+        if (sd_frame)
+            continue;
+
+        sd_frame = av_frame_new_side_data(dst, type_frame, sd_pkt->size);
+        if (!sd_frame)
+            return AVERROR(ENOMEM);
+
+        memcpy(sd_frame->data, sd_pkt->data, sd_pkt->size);
+    }
+
+    return 0;
 }
 
 static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame)
@@ -1425,17 +1461,17 @@ static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame)
 int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx,
                                    AVFrame *frame, const AVPacket *pkt)
 {
-    static const struct {
-        enum AVPacketSideDataType packet;
-        enum AVFrameSideDataType frame;
-    } sd[] = {
+    static const SideDataMap sd[] = {
         { AV_PKT_DATA_A53_CC,                     AV_FRAME_DATA_A53_CC },
         { AV_PKT_DATA_AFD,                        AV_FRAME_DATA_AFD },
         { AV_PKT_DATA_DYNAMIC_HDR10_PLUS,         AV_FRAME_DATA_DYNAMIC_HDR_PLUS },
         { AV_PKT_DATA_S12M_TIMECODE,              AV_FRAME_DATA_S12M_TIMECODE },
         { AV_PKT_DATA_SKIP_SAMPLES,               AV_FRAME_DATA_SKIP_SAMPLES },
+        { AV_PKT_DATA_NB }
     };
 
+    int ret = 0;
+
     frame->pts          = pkt->pts;
     frame->duration     = pkt->duration;
 #if FF_API_FRAME_PKT
@@ -1445,31 +1481,14 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-    for (int i = 0; ff_sd_global_map[i].packet < AV_PKT_DATA_NB; i++) {
-        size_t size;
-        const uint8_t *packet_sd = av_packet_get_side_data(pkt, ff_sd_global_map[i].packet, &size);
-        if (packet_sd) {
-            AVFrameSideData *frame_sd;
+    ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, ff_sd_global_map);
+    if (ret < 0)
+        return ret;
 
-            frame_sd = av_frame_new_side_data(frame, ff_sd_global_map[i].frame, size);
-            if (!frame_sd)
-                return AVERROR(ENOMEM);
-            memcpy(frame_sd->data, packet_sd, size);
-        }
-    }
-    for (int i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
-        size_t size;
-        uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
-        if (packet_sd) {
-            AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
-                                                               sd[i].frame,
-                                                               size);
-            if (!frame_sd)
-                return AVERROR(ENOMEM);
+    ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, sd);
+    if (ret < 0)
+        return ret;
 
-            memcpy(frame_sd->data, packet_sd, size);
-        }
-    }
     add_metadata_from_side_data(pkt, frame);
 
     if (pkt->flags & AV_PKT_FLAG_DISCARD) {
@@ -1490,19 +1509,10 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
 {
     int ret;
 
-    for (int i = 0; ff_sd_global_map[i].packet < AV_PKT_DATA_NB; i++) {
-        const AVPacketSideData *packet_sd = ff_get_coded_side_data(avctx,
-                                                                   ff_sd_global_map[i].packet);
-        if (packet_sd) {
-            AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
-                                                               ff_sd_global_map[i].frame,
-                                                               packet_sd->size);
-            if (!frame_sd)
-                return AVERROR(ENOMEM);
-
-            memcpy(frame_sd->data, packet_sd->data, packet_sd->size);
-        }
-    }
+    ret = side_data_map(frame, avctx->coded_side_data, avctx->nb_coded_side_data,
+                        ff_sd_global_map);
+    if (ret < 0)
+        return ret;
 
     if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) {
         const AVPacket *pkt = avctx->internal->last_pkt_props;
-- 
2.43.0



More information about the ffmpeg-devel mailing list