FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/frame.c
Date: 2024-04-24 13:31:03
Exec Total Coverage
Lines: 422 648 65.1%
Functions: 39 41 95.1%
Branches: 207 404 51.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 "channel_layout.h"
20 #include "avassert.h"
21 #include "buffer.h"
22 #include "common.h"
23 #include "cpu.h"
24 #include "dict.h"
25 #include "frame.h"
26 #include "imgutils.h"
27 #include "mem.h"
28 #include "samplefmt.h"
29 #include "hwcontext.h"
30
31 static const AVSideDataDescriptor sd_props[] = {
32 [AV_FRAME_DATA_PANSCAN] = { "AVPanScan" },
33 [AV_FRAME_DATA_A53_CC] = { "ATSC A53 Part 4 Closed Captions" },
34 [AV_FRAME_DATA_MATRIXENCODING] = { "AVMatrixEncoding" },
35 [AV_FRAME_DATA_DOWNMIX_INFO] = { "Metadata relevant to a downmix procedure" },
36 [AV_FRAME_DATA_AFD] = { "Active format description" },
37 [AV_FRAME_DATA_MOTION_VECTORS] = { "Motion vectors" },
38 [AV_FRAME_DATA_SKIP_SAMPLES] = { "Skip samples" },
39 [AV_FRAME_DATA_GOP_TIMECODE] = { "GOP timecode" },
40 [AV_FRAME_DATA_S12M_TIMECODE] = { "SMPTE 12-1 timecode" },
41 [AV_FRAME_DATA_DYNAMIC_HDR_PLUS] = { "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)" },
42 [AV_FRAME_DATA_DYNAMIC_HDR_VIVID] = { "HDR Dynamic Metadata CUVA 005.1 2021 (Vivid)" },
43 [AV_FRAME_DATA_REGIONS_OF_INTEREST] = { "Regions Of Interest" },
44 [AV_FRAME_DATA_VIDEO_ENC_PARAMS] = { "Video encoding parameters" },
45 [AV_FRAME_DATA_FILM_GRAIN_PARAMS] = { "Film grain parameters" },
46 [AV_FRAME_DATA_DETECTION_BBOXES] = { "Bounding boxes for object detection and classification" },
47 [AV_FRAME_DATA_DOVI_RPU_BUFFER] = { "Dolby Vision RPU Data" },
48 [AV_FRAME_DATA_DOVI_METADATA] = { "Dolby Vision Metadata" },
49 [AV_FRAME_DATA_STEREO3D] = { "Stereo 3D", AV_SIDE_DATA_PROP_GLOBAL },
50 [AV_FRAME_DATA_REPLAYGAIN] = { "AVReplayGain", AV_SIDE_DATA_PROP_GLOBAL },
51 [AV_FRAME_DATA_DISPLAYMATRIX] = { "3x3 displaymatrix", AV_SIDE_DATA_PROP_GLOBAL },
52 [AV_FRAME_DATA_AUDIO_SERVICE_TYPE] = { "Audio service type", AV_SIDE_DATA_PROP_GLOBAL },
53 [AV_FRAME_DATA_MASTERING_DISPLAY_METADATA] = { "Mastering display metadata", AV_SIDE_DATA_PROP_GLOBAL },
54 [AV_FRAME_DATA_CONTENT_LIGHT_LEVEL] = { "Content light level metadata", AV_SIDE_DATA_PROP_GLOBAL },
55 [AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT] = { "Ambient viewing environment", AV_SIDE_DATA_PROP_GLOBAL },
56 [AV_FRAME_DATA_SPHERICAL] = { "Spherical Mapping", AV_SIDE_DATA_PROP_GLOBAL },
57 [AV_FRAME_DATA_ICC_PROFILE] = { "ICC profile", 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 };
60
61 12310918 static void get_frame_defaults(AVFrame *frame)
62 {
63 12310918 memset(frame, 0, sizeof(*frame));
64
65 12310918 frame->pts =
66 12310918 frame->pkt_dts = AV_NOPTS_VALUE;
67 12310918 frame->best_effort_timestamp = AV_NOPTS_VALUE;
68 12310918 frame->duration = 0;
69 #if FF_API_FRAME_PKT
70 FF_DISABLE_DEPRECATION_WARNINGS
71 12310918 frame->pkt_pos = -1;
72 12310918 frame->pkt_size = -1;
73 FF_ENABLE_DEPRECATION_WARNINGS
74 #endif
75 12310918 frame->time_base = (AVRational){ 0, 1 };
76 12310918 frame->sample_aspect_ratio = (AVRational){ 0, 1 };
77 12310918 frame->format = -1; /* unknown */
78 12310918 frame->extended_data = frame->data;
79 12310918 frame->color_primaries = AVCOL_PRI_UNSPECIFIED;
80 12310918 frame->color_trc = AVCOL_TRC_UNSPECIFIED;
81 12310918 frame->colorspace = AVCOL_SPC_UNSPECIFIED;
82 12310918 frame->color_range = AVCOL_RANGE_UNSPECIFIED;
83 12310918 frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
84 12310918 frame->flags = 0;
85 12310918 }
86
87 66356 static void free_side_data(AVFrameSideData **ptr_sd)
88 {
89 66356 AVFrameSideData *sd = *ptr_sd;
90
91 66356 av_buffer_unref(&sd->buf);
92 66356 av_dict_free(&sd->metadata);
93 66356 av_freep(ptr_sd);
94 66356 }
95
96 7900673 static void wipe_side_data(AVFrameSideData ***sd, int *nb_side_data)
97 {
98
2/2
✓ Branch 0 taken 66123 times.
✓ Branch 1 taken 7900673 times.
7966796 for (int i = 0; i < *nb_side_data; i++) {
99 66123 free_side_data(&((*sd)[i]));
100 }
101 7900673 *nb_side_data = 0;
102
103 7900673 av_freep(sd);
104 7900673 }
105
106 7843447 static void frame_side_data_wipe(AVFrame *frame)
107 {
108 7843447 wipe_side_data(&frame->side_data, &frame->nb_side_data);
109 7843447 }
110
111 57226 void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd)
112 {
113 57226 wipe_side_data(sd, nb_sd);
114 57226 }
115
116 398671 static void remove_side_data(AVFrameSideData ***sd, int *nb_side_data,
117 const enum AVFrameSideDataType type)
118 {
119
2/2
✓ Branch 0 taken 15196 times.
✓ Branch 1 taken 398671 times.
413867 for (int i = *nb_side_data - 1; i >= 0; i--) {
120 15196 AVFrameSideData *entry = ((*sd)[i]);
121
2/2
✓ Branch 0 taken 14963 times.
✓ Branch 1 taken 233 times.
15196 if (entry->type != type)
122 14963 continue;
123
124 233 free_side_data(&entry);
125
126 233 ((*sd)[i]) = ((*sd)[*nb_side_data - 1]);
127 233 (*nb_side_data)--;
128 }
129 398671 }
130
131 static void remove_side_data_by_entry(AVFrameSideData ***sd, int *nb_sd,
132 const AVFrameSideData *target)
133 {
134 for (int i = *nb_sd - 1; i >= 0; i--) {
135 AVFrameSideData *entry = ((*sd)[i]);
136 if (entry != target)
137 continue;
138
139 free_side_data(&entry);
140
141 ((*sd)[i]) = ((*sd)[*nb_sd - 1]);
142 (*nb_sd)--;
143
144 return;
145 }
146 }
147
148 1180848 AVFrame *av_frame_alloc(void)
149 {
150 1180848 AVFrame *frame = av_malloc(sizeof(*frame));
151
152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1180848 times.
1180848 if (!frame)
153 return NULL;
154
155 1180848 get_frame_defaults(frame);
156
157 1180848 return frame;
158 }
159
160 1291095 void av_frame_free(AVFrame **frame)
161 {
162
3/4
✓ Branch 0 taken 1291095 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110183 times.
✓ Branch 3 taken 1180912 times.
1291095 if (!frame || !*frame)
163 110183 return;
164
165 1180912 av_frame_unref(*frame);
166 1180912 av_freep(frame);
167 }
168
169 419 static int get_video_buffer(AVFrame *frame, int align)
170 {
171 419 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
172 int ret, padded_height, total_size;
173 419 int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align);
174 ptrdiff_t linesizes[4];
175 size_t sizes[4];
176
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 419 times.
419 if (!desc)
178 return AVERROR(EINVAL);
179
180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 419 times.
419 if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0)
181 return ret;
182
183
1/2
✓ Branch 0 taken 419 times.
✗ Branch 1 not taken.
419 if (!frame->linesize[0]) {
184
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 24 times.
419 if (align <= 0)
185 395 align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */
186
187
1/2
✓ Branch 0 taken 931 times.
✗ Branch 1 not taken.
931 for (int i = 1; i <= align; i += i) {
188 931 ret = av_image_fill_linesizes(frame->linesize, frame->format,
189 931 FFALIGN(frame->width, i));
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 931 times.
931 if (ret < 0)
191 return ret;
192
2/2
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 512 times.
931 if (!(frame->linesize[0] & (align-1)))
193 419 break;
194 }
195
196
3/4
✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 621 times.
✓ Branch 3 taken 419 times.
1040 for (int i = 0; i < 4 && frame->linesize[i]; i++)
197 621 frame->linesize[i] = FFALIGN(frame->linesize[i], align);
198 }
199
200
2/2
✓ Branch 0 taken 1676 times.
✓ Branch 1 taken 419 times.
2095 for (int i = 0; i < 4; i++)
201 1676 linesizes[i] = frame->linesize[i];
202
203 419 padded_height = FFALIGN(frame->height, 32);
204
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 419 times.
419 if ((ret = av_image_fill_plane_sizes(sizes, frame->format,
205 padded_height, linesizes)) < 0)
206 return ret;
207
208 419 total_size = 4*plane_padding;
209
2/2
✓ Branch 0 taken 1676 times.
✓ Branch 1 taken 419 times.
2095 for (int i = 0; i < 4; i++) {
210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1676 times.
1676 if (sizes[i] > INT_MAX - total_size)
211 return AVERROR(EINVAL);
212 1676 total_size += sizes[i];
213 }
214
215 419 frame->buf[0] = av_buffer_alloc(total_size);
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 419 times.
419 if (!frame->buf[0]) {
217 ret = AVERROR(ENOMEM);
218 goto fail;
219 }
220
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 419 times.
419 if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
222 419 frame->buf[0]->data, frame->linesize)) < 0)
223 goto fail;
224
225
2/2
✓ Branch 0 taken 1257 times.
✓ Branch 1 taken 419 times.
1676 for (int i = 1; i < 4; i++) {
226
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 1055 times.
1257 if (frame->data[i])
227 202 frame->data[i] += i * plane_padding;
228 }
229
230 419 frame->extended_data = frame->data;
231
232 419 return 0;
233 fail:
234 av_frame_unref(frame);
235 return ret;
236 }
237
238 14298 static int get_audio_buffer(AVFrame *frame, int align)
239 {
240 14298 int planar = av_sample_fmt_is_planar(frame->format);
241 int channels, planes;
242 int ret;
243
244 14298 channels = frame->ch_layout.nb_channels;
245
2/2
✓ Branch 0 taken 1169 times.
✓ Branch 1 taken 13129 times.
14298 planes = planar ? channels : 1;
246
1/2
✓ Branch 0 taken 14298 times.
✗ Branch 1 not taken.
14298 if (!frame->linesize[0]) {
247 14298 ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
248 14298 frame->nb_samples, frame->format,
249 align);
250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14298 times.
14298 if (ret < 0)
251 return ret;
252 }
253
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14298 times.
14298 if (planes > AV_NUM_DATA_POINTERS) {
255 frame->extended_data = av_calloc(planes,
256 sizeof(*frame->extended_data));
257 frame->extended_buf = av_calloc(planes - AV_NUM_DATA_POINTERS,
258 sizeof(*frame->extended_buf));
259 if (!frame->extended_data || !frame->extended_buf) {
260 av_freep(&frame->extended_data);
261 av_freep(&frame->extended_buf);
262 return AVERROR(ENOMEM);
263 }
264 frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
265 } else
266 14298 frame->extended_data = frame->data;
267
268
2/2
✓ Branch 0 taken 15093 times.
✓ Branch 1 taken 14298 times.
29391 for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
269 15093 frame->buf[i] = av_buffer_alloc(frame->linesize[0]);
270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15093 times.
15093 if (!frame->buf[i]) {
271 av_frame_unref(frame);
272 return AVERROR(ENOMEM);
273 }
274 15093 frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
275 }
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14298 times.
14298 for (int i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {
277 frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]);
278 if (!frame->extended_buf[i]) {
279 av_frame_unref(frame);
280 return AVERROR(ENOMEM);
281 }
282 frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
283 }
284 14298 return 0;
285
286 }
287
288 14717 int av_frame_get_buffer(AVFrame *frame, int align)
289 {
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14717 times.
14717 if (frame->format < 0)
291 return AVERROR(EINVAL);
292
293
3/4
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 14298 times.
✓ Branch 2 taken 419 times.
✗ Branch 3 not taken.
14717 if (frame->width > 0 && frame->height > 0)
294 419 return get_video_buffer(frame, align);
295
2/4
✓ Branch 0 taken 14298 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14298 times.
✗ Branch 3 not taken.
28596 else if (frame->nb_samples > 0 &&
296 14298 (av_channel_layout_check(&frame->ch_layout)))
297 14298 return get_audio_buffer(frame, align);
298
299 return AVERROR(EINVAL);
300 }
301
302 1165161 static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
303 {
304 int ret;
305
306 #if FF_API_FRAME_KEY
307 FF_DISABLE_DEPRECATION_WARNINGS
308 1165161 dst->key_frame = src->key_frame;
309 FF_ENABLE_DEPRECATION_WARNINGS
310 #endif
311 1165161 dst->pict_type = src->pict_type;
312 1165161 dst->sample_aspect_ratio = src->sample_aspect_ratio;
313 1165161 dst->crop_top = src->crop_top;
314 1165161 dst->crop_bottom = src->crop_bottom;
315 1165161 dst->crop_left = src->crop_left;
316 1165161 dst->crop_right = src->crop_right;
317 1165161 dst->pts = src->pts;
318 1165161 dst->duration = src->duration;
319 1165161 dst->repeat_pict = src->repeat_pict;
320 #if FF_API_INTERLACED_FRAME
321 FF_DISABLE_DEPRECATION_WARNINGS
322 1165161 dst->interlaced_frame = src->interlaced_frame;
323 1165161 dst->top_field_first = src->top_field_first;
324 FF_ENABLE_DEPRECATION_WARNINGS
325 #endif
326 #if FF_API_PALETTE_HAS_CHANGED
327 FF_DISABLE_DEPRECATION_WARNINGS
328 1165161 dst->palette_has_changed = src->palette_has_changed;
329 FF_ENABLE_DEPRECATION_WARNINGS
330 #endif
331 1165161 dst->sample_rate = src->sample_rate;
332 1165161 dst->opaque = src->opaque;
333 1165161 dst->pkt_dts = src->pkt_dts;
334 #if FF_API_FRAME_PKT
335 FF_DISABLE_DEPRECATION_WARNINGS
336 1165161 dst->pkt_pos = src->pkt_pos;
337 1165161 dst->pkt_size = src->pkt_size;
338 FF_ENABLE_DEPRECATION_WARNINGS
339 #endif
340 1165161 dst->time_base = src->time_base;
341 1165161 dst->quality = src->quality;
342 1165161 dst->best_effort_timestamp = src->best_effort_timestamp;
343 1165161 dst->flags = src->flags;
344 1165161 dst->decode_error_flags = src->decode_error_flags;
345 1165161 dst->color_primaries = src->color_primaries;
346 1165161 dst->color_trc = src->color_trc;
347 1165161 dst->colorspace = src->colorspace;
348 1165161 dst->color_range = src->color_range;
349 1165161 dst->chroma_location = src->chroma_location;
350
351 1165161 av_dict_copy(&dst->metadata, src->metadata, 0);
352
353
2/2
✓ Branch 0 taken 49791 times.
✓ Branch 1 taken 1165161 times.
1214952 for (int i = 0; i < src->nb_side_data; i++) {
354 49791 const AVFrameSideData *sd_src = src->side_data[i];
355 AVFrameSideData *sd_dst;
356
2/2
✓ Branch 0 taken 19768 times.
✓ Branch 1 taken 30023 times.
49791 if ( sd_src->type == AV_FRAME_DATA_PANSCAN
357
2/4
✓ Branch 0 taken 19768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19768 times.
19768 && (src->width != dst->width || src->height != dst->height))
358 continue;
359
2/2
✓ Branch 0 taken 8143 times.
✓ Branch 1 taken 41648 times.
49791 if (force_copy) {
360 8143 sd_dst = av_frame_new_side_data(dst, sd_src->type,
361 8143 sd_src->size);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8143 times.
8143 if (!sd_dst) {
363 frame_side_data_wipe(dst);
364 return AVERROR(ENOMEM);
365 }
366 8143 memcpy(sd_dst->data, sd_src->data, sd_src->size);
367 } else {
368 41648 AVBufferRef *ref = av_buffer_ref(sd_src->buf);
369 41648 sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref);
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41648 times.
41648 if (!sd_dst) {
371 av_buffer_unref(&ref);
372 frame_side_data_wipe(dst);
373 return AVERROR(ENOMEM);
374 }
375 }
376 49791 av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
377 }
378
379 1165161 ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
380 1165161 ret |= av_buffer_replace(&dst->private_ref, src->private_ref);
381 1165161 return ret;
382 }
383
384 861374 int av_frame_ref(AVFrame *dst, const AVFrame *src)
385 {
386 861374 int ret = 0;
387
388 av_assert1(dst->width == 0 && dst->height == 0);
389 av_assert1(dst->ch_layout.nb_channels == 0 &&
390 dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
391
392 861374 dst->format = src->format;
393 861374 dst->width = src->width;
394 861374 dst->height = src->height;
395 861374 dst->nb_samples = src->nb_samples;
396
397 861374 ret = frame_copy_props(dst, src, 0);
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 861374 times.
861374 if (ret < 0)
399 goto fail;
400
401 861374 ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 861374 times.
861374 if (ret < 0)
403 goto fail;
404
405 /* duplicate the frame data if it's not refcounted */
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 861374 times.
861374 if (!src->buf[0]) {
407 ret = av_frame_get_buffer(dst, 0);
408 if (ret < 0)
409 goto fail;
410
411 ret = av_frame_copy(dst, src);
412 if (ret < 0)
413 goto fail;
414
415 return 0;
416 }
417
418 /* ref the buffers */
419
2/2
✓ Branch 0 taken 6890992 times.
✓ Branch 1 taken 861374 times.
7752366 for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
420
2/2
✓ Branch 0 taken 5179340 times.
✓ Branch 1 taken 1711652 times.
6890992 if (!src->buf[i])
421 5179340 continue;
422 1711652 dst->buf[i] = av_buffer_ref(src->buf[i]);
423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1711652 times.
1711652 if (!dst->buf[i]) {
424 ret = AVERROR(ENOMEM);
425 goto fail;
426 }
427 }
428
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 861374 times.
861374 if (src->extended_buf) {
430 dst->extended_buf = av_calloc(src->nb_extended_buf,
431 sizeof(*dst->extended_buf));
432 if (!dst->extended_buf) {
433 ret = AVERROR(ENOMEM);
434 goto fail;
435 }
436 dst->nb_extended_buf = src->nb_extended_buf;
437
438 for (int i = 0; i < src->nb_extended_buf; i++) {
439 dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]);
440 if (!dst->extended_buf[i]) {
441 ret = AVERROR(ENOMEM);
442 goto fail;
443 }
444 }
445 }
446
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 861374 times.
861374 if (src->hw_frames_ctx) {
448 dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
449 if (!dst->hw_frames_ctx) {
450 ret = AVERROR(ENOMEM);
451 goto fail;
452 }
453 }
454
455 /* duplicate extended data */
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 861374 times.
861374 if (src->extended_data != src->data) {
457 int ch = dst->ch_layout.nb_channels;
458
459 if (!ch) {
460 ret = AVERROR(EINVAL);
461 goto fail;
462 }
463
464 dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch);
465 if (!dst->extended_data) {
466 ret = AVERROR(ENOMEM);
467 goto fail;
468 }
469 memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch);
470 } else
471 861374 dst->extended_data = dst->data;
472
473 861374 memcpy(dst->data, src->data, sizeof(src->data));
474 861374 memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
475
476 861374 return 0;
477
478 fail:
479 av_frame_unref(dst);
480 return ret;
481 }
482
483 4078 int av_frame_replace(AVFrame *dst, const AVFrame *src)
484 {
485 4078 int ret = 0;
486
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (dst == src)
488 return AVERROR(EINVAL);
489
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (!src->buf[0]) {
491 av_frame_unref(dst);
492
493 /* duplicate the frame data if it's not refcounted */
494 if ( src->data[0] || src->data[1]
495 || src->data[2] || src->data[3])
496 return av_frame_ref(dst, src);
497
498 ret = frame_copy_props(dst, src, 0);
499 if (ret < 0)
500 goto fail;
501 }
502
503 4078 dst->format = src->format;
504 4078 dst->width = src->width;
505 4078 dst->height = src->height;
506 4078 dst->nb_samples = src->nb_samples;
507
508 4078 ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (ret < 0)
510 goto fail;
511
512 4078 frame_side_data_wipe(dst);
513 4078 av_dict_free(&dst->metadata);
514 4078 ret = frame_copy_props(dst, src, 0);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (ret < 0)
516 goto fail;
517
518 /* replace the buffers */
519
2/2
✓ Branch 0 taken 32624 times.
✓ Branch 1 taken 4078 times.
36702 for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
520 32624 ret = av_buffer_replace(&dst->buf[i], src->buf[i]);
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32624 times.
32624 if (ret < 0)
522 goto fail;
523 }
524
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (src->extended_buf) {
526 if (dst->nb_extended_buf != src->nb_extended_buf) {
527 int nb_extended_buf = FFMIN(dst->nb_extended_buf, src->nb_extended_buf);
528 void *tmp;
529
530 for (int i = nb_extended_buf; i < dst->nb_extended_buf; i++)
531 av_buffer_unref(&dst->extended_buf[i]);
532
533 tmp = av_realloc_array(dst->extended_buf, sizeof(*dst->extended_buf),
534 src->nb_extended_buf);
535 if (!tmp) {
536 ret = AVERROR(ENOMEM);
537 goto fail;
538 }
539 dst->extended_buf = tmp;
540 dst->nb_extended_buf = src->nb_extended_buf;
541
542 memset(&dst->extended_buf[nb_extended_buf], 0,
543 (src->nb_extended_buf - nb_extended_buf) * sizeof(*dst->extended_buf));
544 }
545
546 for (int i = 0; i < src->nb_extended_buf; i++) {
547 ret = av_buffer_replace(&dst->extended_buf[i], src->extended_buf[i]);
548 if (ret < 0)
549 goto fail;
550 }
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 } else if (dst->extended_buf) {
552 for (int i = 0; i < dst->nb_extended_buf; i++)
553 av_buffer_unref(&dst->extended_buf[i]);
554 av_freep(&dst->extended_buf);
555 }
556
557 4078 ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx);
558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (ret < 0)
559 goto fail;
560
561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (dst->extended_data != dst->data)
562 av_freep(&dst->extended_data);
563
564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4078 times.
4078 if (src->extended_data != src->data) {
565 int ch = dst->ch_layout.nb_channels;
566
567 if (!ch) {
568 ret = AVERROR(EINVAL);
569 goto fail;
570 }
571
572 if (ch > SIZE_MAX / sizeof(*dst->extended_data))
573 goto fail;
574
575 dst->extended_data = av_memdup(src->extended_data, sizeof(*dst->extended_data) * ch);
576 if (!dst->extended_data) {
577 ret = AVERROR(ENOMEM);
578 goto fail;
579 }
580 } else
581 4078 dst->extended_data = dst->data;
582
583 4078 memcpy(dst->data, src->data, sizeof(src->data));
584 4078 memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
585
586 4078 return 0;
587
588 fail:
589 av_frame_unref(dst);
590 return ret;
591 }
592
593 18928 AVFrame *av_frame_clone(const AVFrame *src)
594 {
595 18928 AVFrame *ret = av_frame_alloc();
596
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18928 times.
18928 if (!ret)
598 return NULL;
599
600
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18928 times.
18928 if (av_frame_ref(ret, src) < 0)
601 av_frame_free(&ret);
602
603 18928 return ret;
604 }
605
606 7839373 void av_frame_unref(AVFrame *frame)
607 {
608
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7839369 times.
7839373 if (!frame)
609 4 return;
610
611 7839369 frame_side_data_wipe(frame);
612
613
2/2
✓ Branch 0 taken 62714952 times.
✓ Branch 1 taken 7839369 times.
70554321 for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
614 62714952 av_buffer_unref(&frame->buf[i]);
615
2/2
✓ Branch 0 taken 960 times.
✓ Branch 1 taken 7839369 times.
7840329 for (int i = 0; i < frame->nb_extended_buf; i++)
616 960 av_buffer_unref(&frame->extended_buf[i]);
617 7839369 av_freep(&frame->extended_buf);
618 7839369 av_dict_free(&frame->metadata);
619
620 7839369 av_buffer_unref(&frame->hw_frames_ctx);
621
622 7839369 av_buffer_unref(&frame->opaque_ref);
623 7839369 av_buffer_unref(&frame->private_ref);
624
625
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 7839057 times.
7839369 if (frame->extended_data != frame->data)
626 312 av_freep(&frame->extended_data);
627
628 7839369 av_channel_layout_uninit(&frame->ch_layout);
629
630 7839369 get_frame_defaults(frame);
631 }
632
633 3290701 void av_frame_move_ref(AVFrame *dst, AVFrame *src)
634 {
635 av_assert1(dst->width == 0 && dst->height == 0);
636 av_assert1(dst->ch_layout.nb_channels == 0 &&
637 dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
638
639 3290701 *dst = *src;
640
1/2
✓ Branch 0 taken 3290701 times.
✗ Branch 1 not taken.
3290701 if (src->extended_data == src->data)
641 3290701 dst->extended_data = dst->data;
642 3290701 get_frame_defaults(src);
643 3290701 }
644
645 18859 int av_frame_is_writable(AVFrame *frame)
646 {
647 18859 int ret = 1;
648
649 /* assume non-refcounted frames are not writable */
650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18859 times.
18859 if (!frame->buf[0])
651 return 0;
652
653
2/2
✓ Branch 0 taken 150872 times.
✓ Branch 1 taken 18859 times.
169731 for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
654
2/2
✓ Branch 0 taken 37403 times.
✓ Branch 1 taken 113469 times.
150872 if (frame->buf[i])
655 37403 ret &= !!av_buffer_is_writable(frame->buf[i]);
656
2/2
✓ Branch 0 taken 960 times.
✓ Branch 1 taken 18859 times.
19819 for (int i = 0; i < frame->nb_extended_buf; i++)
657 960 ret &= !!av_buffer_is_writable(frame->extended_buf[i]);
658
659 18859 return ret;
660 }
661
662 3200 int av_frame_make_writable(AVFrame *frame)
663 {
664 AVFrame tmp;
665 int ret;
666
667
1/2
✓ Branch 1 taken 3200 times.
✗ Branch 2 not taken.
3200 if (av_frame_is_writable(frame))
668 3200 return 0;
669
670 memset(&tmp, 0, sizeof(tmp));
671 tmp.format = frame->format;
672 tmp.width = frame->width;
673 tmp.height = frame->height;
674 tmp.nb_samples = frame->nb_samples;
675 ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout);
676 if (ret < 0) {
677 av_frame_unref(&tmp);
678 return ret;
679 }
680
681 if (frame->hw_frames_ctx)
682 ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0);
683 else
684 ret = av_frame_get_buffer(&tmp, 0);
685 if (ret < 0)
686 return ret;
687
688 ret = av_frame_copy(&tmp, frame);
689 if (ret < 0) {
690 av_frame_unref(&tmp);
691 return ret;
692 }
693
694 ret = av_frame_copy_props(&tmp, frame);
695 if (ret < 0) {
696 av_frame_unref(&tmp);
697 return ret;
698 }
699
700 av_frame_unref(frame);
701
702 *frame = tmp;
703 if (tmp.data == tmp.extended_data)
704 frame->extended_data = frame->data;
705
706 return 0;
707 }
708
709 299709 int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
710 {
711 299709 return frame_copy_props(dst, src, 1);
712 }
713
714 5405 AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane)
715 {
716 uint8_t *data;
717 int planes;
718
719
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 5080 times.
5405 if (frame->nb_samples) {
720 325 int channels = frame->ch_layout.nb_channels;
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (!channels)
722 return NULL;
723
1/2
✓ Branch 1 taken 325 times.
✗ Branch 2 not taken.
325 planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
724 } else
725 5080 planes = 4;
726
727
3/6
✓ Branch 0 taken 5405 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5405 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5405 times.
5405 if (plane < 0 || plane >= planes || !frame->extended_data[plane])
728 return NULL;
729 5405 data = frame->extended_data[plane];
730
731
2/4
✓ Branch 0 taken 12797 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12797 times.
✗ Branch 3 not taken.
12797 for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) {
732 12797 AVBufferRef *buf = frame->buf[i];
733
4/4
✓ Branch 0 taken 11809 times.
✓ Branch 1 taken 988 times.
✓ Branch 2 taken 5405 times.
✓ Branch 3 taken 6404 times.
12797 if (data >= buf->data && data < buf->data + buf->size)
734 5405 return buf;
735 }
736 for (int i = 0; i < frame->nb_extended_buf; i++) {
737 AVBufferRef *buf = frame->extended_buf[i];
738 if (data >= buf->data && data < buf->data + buf->size)
739 return buf;
740 }
741 return NULL;
742 }
743
744 66356 static AVFrameSideData *add_side_data_from_buf_ext(AVFrameSideData ***sd,
745 int *nb_sd,
746 enum AVFrameSideDataType type,
747 AVBufferRef *buf, uint8_t *data,
748 size_t size)
749 {
750 AVFrameSideData *ret, **tmp;
751
752 // *nb_sd + 1 needs to fit into an int and a size_t.
753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66356 times.
66356 if ((unsigned)*nb_sd >= FFMIN(INT_MAX, SIZE_MAX))
754 return NULL;
755
756 66356 tmp = av_realloc_array(*sd, sizeof(**sd), *nb_sd + 1);
757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66356 times.
66356 if (!tmp)
758 return NULL;
759 66356 *sd = tmp;
760
761 66356 ret = av_mallocz(sizeof(*ret));
762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66356 times.
66356 if (!ret)
763 return NULL;
764
765 66356 ret->buf = buf;
766 66356 ret->data = data;
767 66356 ret->size = size;
768 66356 ret->type = type;
769
770 66356 (*sd)[(*nb_sd)++] = ret;
771
772 66356 return ret;
773 }
774
775 66132 static AVFrameSideData *add_side_data_from_buf(AVFrameSideData ***sd,
776 int *nb_sd,
777 enum AVFrameSideDataType type,
778 AVBufferRef *buf)
779 {
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66132 times.
66132 if (!buf)
781 return NULL;
782
783 66132 return add_side_data_from_buf_ext(sd, nb_sd, type, buf, buf->data, buf->size);
784 }
785
786 65050 AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
787 enum AVFrameSideDataType type,
788 AVBufferRef *buf)
789 {
790 return
791 65050 add_side_data_from_buf(
792 &frame->side_data, &frame->nb_side_data, type, buf);
793 }
794
795 23335 AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
796 enum AVFrameSideDataType type,
797 size_t size)
798 {
799 AVFrameSideData *ret;
800 23335 AVBufferRef *buf = av_buffer_alloc(size);
801 23335 ret = av_frame_new_side_data_from_buf(frame, type, buf);
802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23335 times.
23335 if (!ret)
803 av_buffer_unref(&buf);
804 23335 return ret;
805 }
806
807 2 static AVFrameSideData *replace_side_data_from_buf(AVFrameSideData *dst,
808 AVBufferRef *buf, int flags)
809 {
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
811 return NULL;
812
813 2 av_dict_free(&dst->metadata);
814 2 av_buffer_unref(&dst->buf);
815 2 dst->buf = buf;
816 2 dst->data = buf->data;
817 2 dst->size = buf->size;
818 2 return dst;
819 }
820
821 11 AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd,
822 enum AVFrameSideDataType type,
823 size_t size, unsigned int flags)
824 {
825 11 const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
826 11 AVBufferRef *buf = av_buffer_alloc(size);
827 11 AVFrameSideData *ret = NULL;
828
829
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
830 1 remove_side_data(sd, nb_sd, type);
831
5/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
15 if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
832 4 (ret = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, type))) {
833 2 ret = replace_side_data_from_buf(ret, buf, flags);
834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ret)
835 av_buffer_unref(&buf);
836 2 return ret;
837 }
838
839 9 ret = add_side_data_from_buf(sd, nb_sd, type, buf);
840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!ret)
841 av_buffer_unref(&buf);
842
843 9 return ret;
844 }
845
846 1073 AVFrameSideData *av_frame_side_data_add(AVFrameSideData ***sd, int *nb_sd,
847 enum AVFrameSideDataType type,
848 AVBufferRef **pbuf, unsigned int flags)
849 {
850 1073 const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
851 1073 AVFrameSideData *sd_dst = NULL;
852 1073 AVBufferRef *buf = *pbuf;
853
854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1073 times.
1073 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
855 remove_side_data(sd, nb_sd, type);
856
4/6
✓ Branch 0 taken 1073 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 779 times.
✓ Branch 3 taken 294 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 779 times.
1852 if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
857 779 (sd_dst = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, type))) {
858 sd_dst = replace_side_data_from_buf(sd_dst, buf, flags);
859 if (sd_dst)
860 *pbuf = NULL;
861 return sd_dst;
862 }
863
864 1073 sd_dst = add_side_data_from_buf(sd, nb_sd, type, buf);
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1073 times.
1073 if (!sd_dst)
866 return NULL;
867
868 1073 *pbuf = NULL;
869 1073 return sd_dst;
870 }
871
872 224 int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd,
873 const AVFrameSideData *src, unsigned int flags)
874 {
875 const AVSideDataDescriptor *desc;
876 224 AVBufferRef *buf = NULL;
877 224 AVFrameSideData *sd_dst = NULL;
878 224 int ret = AVERROR_BUG;
879
880
6/10
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 224 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 223 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
224 if (!sd || !src || !nb_sd || (*nb_sd && !*sd))
881 return AVERROR(EINVAL);
882
883 224 desc = av_frame_side_data_desc(src->type);
884
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
885 224 remove_side_data(sd, nb_sd, src->type);
886
3/6
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 224 times.
448 if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
887 224 (sd_dst = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, src->type))) {
888 AVDictionary *dict = NULL;
889
890 if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
891 return AVERROR(EEXIST);
892
893 ret = av_dict_copy(&dict, src->metadata, 0);
894 if (ret < 0)
895 return ret;
896
897 ret = av_buffer_replace(&sd_dst->buf, src->buf);
898 if (ret < 0) {
899 av_dict_free(&dict);
900 return ret;
901 }
902
903 av_dict_free(&sd_dst->metadata);
904 sd_dst->metadata = dict;
905 sd_dst->data = src->data;
906 sd_dst->size = src->size;
907 return 0;
908 }
909
910 224 buf = av_buffer_ref(src->buf);
911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (!buf)
912 return AVERROR(ENOMEM);
913
914 224 sd_dst = add_side_data_from_buf_ext(sd, nb_sd, src->type, buf,
915 224 src->data, src->size);
916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (!sd_dst) {
917 av_buffer_unref(&buf);
918 return AVERROR(ENOMEM);
919 }
920
921 224 ret = av_dict_copy(&sd_dst->metadata, src->metadata, 0);
922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (ret < 0) {
923 remove_side_data_by_entry(sd, nb_sd, sd_dst);
924 return ret;
925 }
926
927 224 return 0;
928 }
929
930 1123289 const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd,
931 const int nb_sd,
932 enum AVFrameSideDataType type)
933 {
934
2/2
✓ Branch 0 taken 36894 times.
✓ Branch 1 taken 1121861 times.
1158755 for (int i = 0; i < nb_sd; i++) {
935
2/2
✓ Branch 0 taken 1428 times.
✓ Branch 1 taken 35466 times.
36894 if (sd[i]->type == type)
936 1428 return sd[i];
937 }
938 1121861 return NULL;
939 }
940
941 10 void av_frame_side_data_remove(AVFrameSideData ***sd, int *nb_sd,
942 enum AVFrameSideDataType type)
943 {
944 10 remove_side_data(sd, nb_sd, type);
945 10 }
946
947 943555 AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
948 enum AVFrameSideDataType type)
949 {
950 1887110 return (AVFrameSideData *)av_frame_side_data_get(
951 943555 frame->side_data, frame->nb_side_data,
952 type
953 );
954 }
955
956 9549 static int frame_copy_video(AVFrame *dst, const AVFrame *src)
957 {
958 int planes;
959
960
1/2
✓ Branch 0 taken 9549 times.
✗ Branch 1 not taken.
9549 if (dst->width < src->width ||
961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9549 times.
9549 dst->height < src->height)
962 return AVERROR(EINVAL);
963
964
2/4
✓ Branch 0 taken 9549 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9549 times.
9549 if (src->hw_frames_ctx || dst->hw_frames_ctx)
965 return av_hwframe_transfer_data(dst, src, 0);
966
967 9549 planes = av_pix_fmt_count_planes(dst->format);
968
2/2
✓ Branch 0 taken 15813 times.
✓ Branch 1 taken 9549 times.
25362 for (int i = 0; i < planes; i++)
969
2/4
✓ Branch 0 taken 15813 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15813 times.
15813 if (!dst->data[i] || !src->data[i])
970 return AVERROR(EINVAL);
971
972 9549 av_image_copy2(dst->data, dst->linesize,
973 9549 src->data, src->linesize,
974 9549 dst->format, src->width, src->height);
975
976 9549 return 0;
977 }
978
979 static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
980 {
981 int planar = av_sample_fmt_is_planar(dst->format);
982 int channels = dst->ch_layout.nb_channels;
983 int planes = planar ? channels : 1;
984
985 if (dst->nb_samples != src->nb_samples ||
986 av_channel_layout_compare(&dst->ch_layout, &src->ch_layout))
987 return AVERROR(EINVAL);
988
989 for (int i = 0; i < planes; i++)
990 if (!dst->extended_data[i] || !src->extended_data[i])
991 return AVERROR(EINVAL);
992
993 av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
994 dst->nb_samples, channels, dst->format);
995
996 return 0;
997 }
998
999 9549 int av_frame_copy(AVFrame *dst, const AVFrame *src)
1000 {
1001
2/4
✓ Branch 0 taken 9549 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9549 times.
9549 if (dst->format != src->format || dst->format < 0)
1002 return AVERROR(EINVAL);
1003
1004
2/4
✓ Branch 0 taken 9549 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9549 times.
✗ Branch 3 not taken.
9549 if (dst->width > 0 && dst->height > 0)
1005 9549 return frame_copy_video(dst, src);
1006 else if (dst->nb_samples > 0 &&
1007 (av_channel_layout_check(&dst->ch_layout)))
1008 return frame_copy_audio(dst, src);
1009
1010 return AVERROR(EINVAL);
1011 }
1012
1013 398436 void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
1014 {
1015 398436 remove_side_data(&frame->side_data, &frame->nb_side_data, type);
1016 398436 }
1017
1018 2271 const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type)
1019 {
1020 2271 unsigned t = type;
1021
2/4
✓ Branch 0 taken 2271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2271 times.
✗ Branch 3 not taken.
2271 if (t < FF_ARRAY_ELEMS(sd_props) && sd_props[t].name)
1022 2271 return &sd_props[t];
1023 return NULL;
1024 }
1025
1026 475 const char *av_frame_side_data_name(enum AVFrameSideDataType type)
1027 {
1028 475 const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
1029
1/2
✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
475 return desc ? desc->name : NULL;
1030 }
1031
1032 137010 static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
1033 const AVPixFmtDescriptor *desc)
1034 {
1035
2/2
✓ Branch 0 taken 386321 times.
✓ Branch 1 taken 132298 times.
518619 for (int i = 0; frame->data[i]; i++) {
1036 386321 const AVComponentDescriptor *comp = NULL;
1037
4/4
✓ Branch 0 taken 259755 times.
✓ Branch 1 taken 126566 times.
✓ Branch 2 taken 121854 times.
✓ Branch 3 taken 137901 times.
386321 int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
1038
4/4
✓ Branch 0 taken 259755 times.
✓ Branch 1 taken 126566 times.
✓ Branch 2 taken 121854 times.
✓ Branch 3 taken 137901 times.
386321 int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
1039
1040
4/4
✓ Branch 0 taken 9424 times.
✓ Branch 1 taken 376897 times.
✓ Branch 2 taken 4712 times.
✓ Branch 3 taken 4712 times.
386321 if (desc->flags & AV_PIX_FMT_FLAG_PAL && i == 1) {
1041 4712 offsets[i] = 0;
1042 4712 break;
1043 }
1044
1045 /* find any component descriptor for this plane */
1046
1/2
✓ Branch 0 taken 749844 times.
✗ Branch 1 not taken.
749844 for (int j = 0; j < desc->nb_components; j++) {
1047
2/2
✓ Branch 0 taken 381609 times.
✓ Branch 1 taken 368235 times.
749844 if (desc->comp[j].plane == i) {
1048 381609 comp = &desc->comp[j];
1049 381609 break;
1050 }
1051 }
1052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381609 times.
381609 if (!comp)
1053 return AVERROR_BUG;
1054
1055 381609 offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
1056 381609 (frame->crop_left >> shift_x) * comp->step;
1057 }
1058
1059 137010 return 0;
1060 }
1061
1062 137314 int av_frame_apply_cropping(AVFrame *frame, int flags)
1063 {
1064 const AVPixFmtDescriptor *desc;
1065 size_t offsets[4];
1066
1067
2/4
✓ Branch 0 taken 137314 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 137314 times.
137314 if (!(frame->width > 0 && frame->height > 0))
1068 return AVERROR(EINVAL);
1069
1070
1/2
✓ Branch 0 taken 137314 times.
✗ Branch 1 not taken.
137314 if (frame->crop_left >= INT_MAX - frame->crop_right ||
1071
1/2
✓ Branch 0 taken 137314 times.
✗ Branch 1 not taken.
137314 frame->crop_top >= INT_MAX - frame->crop_bottom ||
1072
1/2
✓ Branch 0 taken 137314 times.
✗ Branch 1 not taken.
137314 (frame->crop_left + frame->crop_right) >= frame->width ||
1073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137314 times.
137314 (frame->crop_top + frame->crop_bottom) >= frame->height)
1074 return AVERROR(ERANGE);
1075
1076 137314 desc = av_pix_fmt_desc_get(frame->format);
1077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137314 times.
137314 if (!desc)
1078 return AVERROR_BUG;
1079
1080 /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
1081 * formats cannot be easily handled here either (and corresponding decoders
1082 * should not export any cropping anyway), so do the same for those as well.
1083 * */
1084
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 136996 times.
137314 if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
1085 318 frame->width -= frame->crop_right;
1086 318 frame->height -= frame->crop_bottom;
1087 318 frame->crop_right = 0;
1088 318 frame->crop_bottom = 0;
1089 318 return 0;
1090 }
1091
1092 /* calculate the offsets for each plane */
1093 136996 calc_cropping_offsets(offsets, frame, desc);
1094
1095 /* adjust the offsets to avoid breaking alignment */
1096
2/2
✓ Branch 0 taken 7312 times.
✓ Branch 1 taken 129684 times.
136996 if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
1097
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7298 times.
7312 int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
1098 7312 int min_log2_align = INT_MAX;
1099
1100
2/2
✓ Branch 0 taken 21456 times.
✓ Branch 1 taken 7312 times.
28768 for (int i = 0; frame->data[i]; i++) {
1101
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 21414 times.
21456 int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
1102 21456 min_log2_align = FFMIN(log2_align, min_log2_align);
1103 }
1104
1105 /* we assume, and it should always be true, that the data alignment is
1106 * related to the cropping alignment by a constant power-of-2 factor */
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7312 times.
7312 if (log2_crop_align < min_log2_align)
1108 return AVERROR_BUG;
1109
1110
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7298 times.
7312 if (min_log2_align < 5) {
1111 14 frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
1112 14 calc_cropping_offsets(offsets, frame, desc);
1113 }
1114 }
1115
1116
2/2
✓ Branch 0 taken 386279 times.
✓ Branch 1 taken 136996 times.
523275 for (int i = 0; frame->data[i]; i++)
1117 386279 frame->data[i] += offsets[i];
1118
1119 136996 frame->width -= (frame->crop_left + frame->crop_right);
1120 136996 frame->height -= (frame->crop_top + frame->crop_bottom);
1121 136996 frame->crop_left = 0;
1122 136996 frame->crop_right = 0;
1123 136996 frame->crop_top = 0;
1124 136996 frame->crop_bottom = 0;
1125
1126 136996 return 0;
1127 }
1128