FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/side_data.c
Date: 2026-07-18 19:31:15
Exec Total Coverage
Lines: 113 154 73.4%
Functions: 13 14 92.9%
Branches: 60 98 61.2%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "avassert.h"
20 #include "buffer.h"
21 #include "common.h"
22 #include "dict.h"
23 #include "frame.h"
24 #include "mem.h"
25 #include "side_data.h"
26
27 static const AVSideDataDescriptor sd_props[] = {
28 [AV_FRAME_DATA_PANSCAN] = { "AVPanScan", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
29 [AV_FRAME_DATA_A53_CC] = { "ATSC A53 Part 4 Closed Captions" },
30 [AV_FRAME_DATA_MATRIXENCODING] = { "AVMatrixEncoding", AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT },
31 [AV_FRAME_DATA_DOWNMIX_INFO] = { "Metadata relevant to a downmix procedure", AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT },
32 [AV_FRAME_DATA_AFD] = { "Active format description" },
33 [AV_FRAME_DATA_MOTION_VECTORS] = { "Motion vectors", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
34 [AV_FRAME_DATA_SKIP_SAMPLES] = { "Skip samples" },
35 [AV_FRAME_DATA_GOP_TIMECODE] = { "GOP timecode" },
36 [AV_FRAME_DATA_S12M_TIMECODE] = { "SMPTE 12-1 timecode" },
37 [AV_FRAME_DATA_DYNAMIC_HDR_PLUS] = { "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)", AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
38 [AV_FRAME_DATA_DYNAMIC_HDR_VIVID] = { "HDR Dynamic Metadata CUVA 005.1 2021 (Vivid)", AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
39 [AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5] = { "HDR Dynamic Metadata SMPTE2094-50", AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
40 [AV_FRAME_DATA_REGIONS_OF_INTEREST] = { "Regions Of Interest", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
41 [AV_FRAME_DATA_VIDEO_ENC_PARAMS] = { "Video encoding parameters" },
42 [AV_FRAME_DATA_FILM_GRAIN_PARAMS] = { "Film grain parameters" },
43 [AV_FRAME_DATA_DETECTION_BBOXES] = { "Bounding boxes for object detection and classification", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
44 [AV_FRAME_DATA_DOVI_RPU_BUFFER] = { "Dolby Vision RPU Data", AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
45 [AV_FRAME_DATA_DOVI_METADATA] = { "Dolby Vision Metadata", AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
46 [AV_FRAME_DATA_LCEVC] = { "LCEVC NAL data", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
47 [AV_FRAME_DATA_VIEW_ID] = { "View ID" },
48 [AV_FRAME_DATA_STEREO3D] = { "Stereo 3D", AV_SIDE_DATA_PROP_GLOBAL },
49 [AV_FRAME_DATA_REPLAYGAIN] = { "AVReplayGain", AV_SIDE_DATA_PROP_GLOBAL },
50 [AV_FRAME_DATA_DISPLAYMATRIX] = { "3x3 displaymatrix", AV_SIDE_DATA_PROP_GLOBAL },
51 [AV_FRAME_DATA_AUDIO_SERVICE_TYPE] = { "Audio service type", AV_SIDE_DATA_PROP_GLOBAL },
52 [AV_FRAME_DATA_MASTERING_DISPLAY_METADATA] = { "Mastering display metadata", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
53 [AV_FRAME_DATA_CONTENT_LIGHT_LEVEL] = { "Content light level metadata", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
54 [AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT] = { "Ambient viewing environment", AV_SIDE_DATA_PROP_GLOBAL },
55 [AV_FRAME_DATA_SPHERICAL] = { "Spherical Mapping", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
56 [AV_FRAME_DATA_ICC_PROFILE] = { "ICC profile", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
57 [AV_FRAME_DATA_EXIF] = { "EXIF metadata", AV_SIDE_DATA_PROP_GLOBAL },
58 [AV_FRAME_DATA_SEI_UNREGISTERED] = { "H.26[45] User Data Unregistered SEI message", AV_SIDE_DATA_PROP_MULTI },
59 [AV_FRAME_DATA_VIDEO_HINT] = { "Encoding video hint", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
60 [AV_FRAME_DATA_3D_REFERENCE_DISPLAYS] = { "3D Reference Displays Information", AV_SIDE_DATA_PROP_GLOBAL },
61 [AV_FRAME_DATA_IAMF_MIX_GAIN_PARAM] = { "IAMF Mix Gain Parameter Data" },
62 [AV_FRAME_DATA_IAMF_DEMIXING_INFO_PARAM] = { "IAMF Demixing Info Parameter Data", AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT },
63 [AV_FRAME_DATA_IAMF_RECON_GAIN_INFO_PARAM] = { "IAMF Recon Gain Info Parameter Data" },
64 [AV_FRAME_DATA_RAW_COLOR_PARAMS] = { "RAW camera color parameters", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
65 [AV_FRAME_DATA_DOWNMIX_MATRIX] = { "Downmix Matrix", AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT },
66 };
67
68 6110 const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type)
69 {
70 6110 unsigned t = type;
71
2/4
✓ Branch 0 taken 6110 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6110 times.
✗ Branch 3 not taken.
6110 if (t < FF_ARRAY_ELEMS(sd_props) && sd_props[t].name)
72 6110 return &sd_props[t];
73 return NULL;
74 }
75
76 592 const char *av_frame_side_data_name(enum AVFrameSideDataType type)
77 {
78 592 const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
79
1/2
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
592 return desc ? desc->name : NULL;
80 }
81
82 63313 static void free_side_data_entry(AVFrameSideData **ptr_sd)
83 {
84 63313 AVFrameSideData *sd = *ptr_sd;
85
86 63313 av_buffer_unref(&sd->buf);
87 63313 av_dict_free(&sd->metadata);
88 63313 av_freep(ptr_sd);
89 63313 }
90
91 static void remove_side_data_by_entry(AVFrameSideData ***sd, int *nb_sd,
92 const AVFrameSideData *target)
93 {
94 for (int i = *nb_sd - 1; i >= 0; i--) {
95 AVFrameSideData *entry = ((*sd)[i]);
96 if (entry != target)
97 continue;
98
99 free_side_data_entry(&entry);
100
101 ((*sd)[i]) = ((*sd)[*nb_sd - 1]);
102 (*nb_sd)--;
103
104 return;
105 }
106 }
107
108 465700 void av_frame_side_data_remove(AVFrameSideData ***sd, int *nb_sd,
109 enum AVFrameSideDataType type)
110 {
111
2/2
✓ Branch 0 taken 15952 times.
✓ Branch 1 taken 465700 times.
481652 for (int i = *nb_sd - 1; i >= 0; i--) {
112 15952 AVFrameSideData *entry = ((*sd)[i]);
113
2/2
✓ Branch 0 taken 15286 times.
✓ Branch 1 taken 666 times.
15952 if (entry->type != type)
114 15286 continue;
115
116 666 free_side_data_entry(&entry);
117
118 666 ((*sd)[i]) = ((*sd)[*nb_sd - 1]);
119 666 (*nb_sd)--;
120 }
121 465700 }
122
123 7339 void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd,
124 int props)
125 {
126
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 7339 times.
7474 for (int i = *nb_sd - 1; i >= 0; i--) {
127 135 AVFrameSideData *entry = ((*sd)[i]);
128 135 const AVSideDataDescriptor *desc = av_frame_side_data_desc(entry->type);
129
3/4
✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 113 times.
✓ Branch 3 taken 22 times.
135 if (!desc || !(desc->props & props))
130 113 continue;
131
132 22 free_side_data_entry(&entry);
133
134 22 ((*sd)[i]) = ((*sd)[*nb_sd - 1]);
135 22 (*nb_sd)--;
136 }
137 7339 }
138
139 10886687 void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd)
140 {
141
2/2
✓ Branch 0 taken 62625 times.
✓ Branch 1 taken 10886687 times.
10949312 for (int i = 0; i < *nb_sd; i++)
142 62625 free_side_data_entry(&((*sd)[i]));
143 10886687 *nb_sd = 0;
144
145 10886687 av_freep(sd);
146 10886687 }
147
148 63313 static AVFrameSideData *add_side_data_from_buf_ext(AVFrameSideData ***sd,
149 int *nb_sd,
150 enum AVFrameSideDataType type,
151 AVBufferRef *buf, uint8_t *data,
152 size_t size)
153 {
154 AVFrameSideData *ret, **tmp;
155
156 // *nb_sd + 1 needs to fit into an int and a size_t.
157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63313 times.
63313 if ((unsigned)*nb_sd >= FFMIN(INT_MAX, SIZE_MAX))
158 return NULL;
159
160 63313 tmp = av_realloc_array(*sd, *nb_sd + 1, sizeof(**sd));
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63313 times.
63313 if (!tmp)
162 return NULL;
163 63313 *sd = tmp;
164
165 63313 ret = av_mallocz(sizeof(*ret));
166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63313 times.
63313 if (!ret)
167 return NULL;
168
169 63313 ret->buf = buf;
170 63313 ret->data = data;
171 63313 ret->size = size;
172 63313 ret->type = type;
173
174 63313 (*sd)[(*nb_sd)++] = ret;
175
176 63313 return ret;
177 }
178
179 60899 AVFrameSideData *ff_frame_side_data_add_from_buf(AVFrameSideData ***sd,
180 int *nb_sd,
181 enum AVFrameSideDataType type,
182 AVBufferRef *buf)
183 {
184
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 60895 times.
60899 if (!buf)
185 4 return NULL;
186
187 60895 return add_side_data_from_buf_ext(sd, nb_sd, type, buf, buf->data, buf->size);
188 }
189
190 2 static AVFrameSideData *replace_side_data_from_buf(AVFrameSideData *dst,
191 AVBufferRef *buf, int flags)
192 {
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
194 return NULL;
195
196 2 av_dict_free(&dst->metadata);
197 2 av_buffer_unref(&dst->buf);
198 2 dst->buf = buf;
199 2 dst->data = buf->data;
200 2 dst->size = buf->size;
201 2 return dst;
202 }
203
204 697 AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd,
205 enum AVFrameSideDataType type,
206 size_t size, unsigned int flags)
207 {
208 697 const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
209 697 AVBufferRef *buf = av_buffer_alloc(size);
210 697 AVFrameSideData *ret = NULL;
211
212
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 696 times.
697 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
213 1 av_frame_side_data_remove(sd, nb_sd, type);
214
5/6
✓ Branch 0 taken 697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 690 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 688 times.
1387 if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
215 690 (ret = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, type))) {
216 2 ret = replace_side_data_from_buf(ret, buf, flags);
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ret)
218 av_buffer_unref(&buf);
219 2 return ret;
220 }
221
222 695 ret = ff_frame_side_data_add_from_buf(sd, nb_sd, type, buf);
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 695 times.
695 if (!ret)
224 av_buffer_unref(&buf);
225
226 695 return ret;
227 }
228
229 1641 AVFrameSideData *av_frame_side_data_add(AVFrameSideData ***sd, int *nb_sd,
230 enum AVFrameSideDataType type,
231 AVBufferRef **pbuf, unsigned int flags)
232 {
233 1641 const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
234 1641 AVFrameSideData *sd_dst = NULL;
235 1641 AVBufferRef *buf = *pbuf;
236
237
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1639 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
1641 if ((flags & AV_FRAME_SIDE_DATA_FLAG_NEW_REF) && !(buf = av_buffer_ref(*pbuf)))
238 return NULL;
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1641 times.
1641 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
240 av_frame_side_data_remove(sd, nb_sd, type);
241
4/6
✓ Branch 0 taken 1641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1301 times.
✓ Branch 3 taken 340 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1301 times.
2942 if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
242 1301 (sd_dst = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, type))) {
243 sd_dst = replace_side_data_from_buf(sd_dst, buf, flags);
244 } else
245 1641 sd_dst = ff_frame_side_data_add_from_buf(sd, nb_sd, type, buf);
246
247
3/4
✓ Branch 0 taken 1641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1639 times.
✓ Branch 3 taken 2 times.
1641 if (sd_dst && !(flags & AV_FRAME_SIDE_DATA_FLAG_NEW_REF))
248 1639 *pbuf = NULL;
249
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 else if (!sd_dst && (flags & AV_FRAME_SIDE_DATA_FLAG_NEW_REF))
250 av_buffer_unref(&buf);
251 1641 return sd_dst;
252 }
253
254 2418 int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd,
255 const AVFrameSideData *src, unsigned int flags)
256 {
257 const AVSideDataDescriptor *desc;
258 2418 AVBufferRef *buf = NULL;
259 2418 AVFrameSideData *sd_dst = NULL;
260 2418 int ret = AVERROR_BUG;
261
262
6/10
✓ Branch 0 taken 2418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2418 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2418 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 244 times.
✓ Branch 7 taken 2174 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 244 times.
2418 if (!sd || !src || !nb_sd || (*nb_sd && !*sd))
263 return AVERROR(EINVAL);
264
265 2418 desc = av_frame_side_data_desc(src->type);
266
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 2138 times.
2418 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
267 280 av_frame_side_data_remove(sd, nb_sd, src->type);
268
4/6
✓ Branch 0 taken 2418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2366 times.
✓ Branch 3 taken 52 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2366 times.
4784 if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
269 2366 (sd_dst = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, src->type))) {
270 AVDictionary *dict = NULL;
271
272 if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
273 return AVERROR(EEXIST);
274
275 ret = av_dict_copy(&dict, src->metadata, 0);
276 if (ret < 0)
277 return ret;
278
279 ret = av_buffer_replace(&sd_dst->buf, src->buf);
280 if (ret < 0) {
281 av_dict_free(&dict);
282 return ret;
283 }
284
285 av_dict_free(&sd_dst->metadata);
286 sd_dst->metadata = dict;
287 sd_dst->data = src->data;
288 sd_dst->size = src->size;
289 return 0;
290 }
291
292 2418 buf = av_buffer_ref(src->buf);
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2418 times.
2418 if (!buf)
294 return AVERROR(ENOMEM);
295
296 2418 sd_dst = add_side_data_from_buf_ext(sd, nb_sd, src->type, buf,
297 2418 src->data, src->size);
298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2418 times.
2418 if (!sd_dst) {
299 av_buffer_unref(&buf);
300 return AVERROR(ENOMEM);
301 }
302
303 2418 ret = av_dict_copy(&sd_dst->metadata, src->metadata, 0);
304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2418 times.
2418 if (ret < 0) {
305 remove_side_data_by_entry(sd, nb_sd, sd_dst);
306 return ret;
307 }
308
309 2418 return 0;
310 }
311
312 4008976 const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd,
313 const int nb_sd,
314 enum AVFrameSideDataType type)
315 {
316
2/2
✓ Branch 0 taken 73085 times.
✓ Branch 1 taken 4004391 times.
4077476 for (int i = 0; i < nb_sd; i++) {
317
2/2
✓ Branch 0 taken 4585 times.
✓ Branch 1 taken 68500 times.
73085 if (sd[i]->type == type)
318 4585 return sd[i];
319 }
320 4004391 return NULL;
321 }
322