FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/frame.c
Date: 2025-04-25 22:50:00
Exec Total Coverage
Lines: 324 500 64.8%
Functions: 24 25 96.0%
Branches: 175 330 53.0%

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 "dict.h"
23 #include "frame.h"
24 #include "imgutils.h"
25 #include "mem.h"
26 #include "refstruct.h"
27 #include "samplefmt.h"
28 #include "side_data.h"
29 #include "hwcontext.h"
30
31 12241945 static void get_frame_defaults(AVFrame *frame)
32 {
33 12241945 memset(frame, 0, sizeof(*frame));
34
35 12241945 frame->pts =
36 12241945 frame->pkt_dts = AV_NOPTS_VALUE;
37 12241945 frame->best_effort_timestamp = AV_NOPTS_VALUE;
38 12241945 frame->duration = 0;
39 12241945 frame->time_base = (AVRational){ 0, 1 };
40 12241945 frame->sample_aspect_ratio = (AVRational){ 0, 1 };
41 12241945 frame->format = -1; /* unknown */
42 12241945 frame->extended_data = frame->data;
43 12241945 frame->color_primaries = AVCOL_PRI_UNSPECIFIED;
44 12241945 frame->color_trc = AVCOL_TRC_UNSPECIFIED;
45 12241945 frame->colorspace = AVCOL_SPC_UNSPECIFIED;
46 12241945 frame->color_range = AVCOL_RANGE_UNSPECIFIED;
47 12241945 frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
48 12241945 frame->flags = 0;
49 12241945 }
50
51 1320739 AVFrame *av_frame_alloc(void)
52 {
53 1320739 AVFrame *frame = av_malloc(sizeof(*frame));
54
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1320739 times.
1320739 if (!frame)
56 return NULL;
57
58 1320739 get_frame_defaults(frame);
59
60 1320739 return frame;
61 }
62
63 1608723 void av_frame_free(AVFrame **frame)
64 {
65
3/4
✓ Branch 0 taken 1608723 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287910 times.
✓ Branch 3 taken 1320813 times.
1608723 if (!frame || !*frame)
66 287910 return;
67
68 1320813 av_frame_unref(*frame);
69 1320813 av_freep(frame);
70 }
71
72 #define ALIGN (HAVE_SIMD_ALIGN_64 ? 64 : 32)
73
74 402 static int get_video_buffer(AVFrame *frame, int align)
75 {
76 402 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
77 int ret, padded_height;
78 int plane_padding;
79 ptrdiff_t linesizes[4];
80 size_t total_size, sizes[4];
81
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 if (!desc)
83 return AVERROR(EINVAL);
84
85
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 402 times.
402 if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0)
86 return ret;
87
88
2/2
✓ Branch 0 taken 378 times.
✓ Branch 1 taken 24 times.
402 if (align <= 0)
89 378 align = ALIGN;
90 402 plane_padding = FFMAX(ALIGN, align);
91
92
1/2
✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
402 if (!frame->linesize[0]) {
93
1/2
✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
1083 for (int i = 1; i <= align; i += i) {
94 1083 ret = av_image_fill_linesizes(frame->linesize, frame->format,
95 1083 FFALIGN(frame->width, i));
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
1083 if (ret < 0)
97 return ret;
98
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 681 times.
1083 if (!(frame->linesize[0] & (align-1)))
99 402 break;
100 }
101
102
3/4
✓ Branch 0 taken 1006 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 604 times.
✓ Branch 3 taken 402 times.
1006 for (int i = 0; i < 4 && frame->linesize[i]; i++)
103 604 frame->linesize[i] = FFALIGN(frame->linesize[i], align);
104 }
105
106
2/2
✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 402 times.
2010 for (int i = 0; i < 4; i++)
107 1608 linesizes[i] = frame->linesize[i];
108
109 402 padded_height = FFALIGN(frame->height, 32);
110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 402 times.
402 if ((ret = av_image_fill_plane_sizes(sizes, frame->format,
111 padded_height, linesizes)) < 0)
112 return ret;
113
114 402 total_size = 4 * plane_padding + 4 * align;
115
2/2
✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 402 times.
2010 for (int i = 0; i < 4; i++) {
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1608 times.
1608 if (sizes[i] > SIZE_MAX - total_size)
117 return AVERROR(EINVAL);
118 1608 total_size += sizes[i];
119 }
120
121 402 frame->buf[0] = av_buffer_alloc(total_size);
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 if (!frame->buf[0]) {
123 ret = AVERROR(ENOMEM);
124 goto fail;
125 }
126
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
128 402 frame->buf[0]->data, frame->linesize)) < 0)
129 goto fail;
130
131
2/2
✓ Branch 0 taken 1206 times.
✓ Branch 1 taken 402 times.
1608 for (int i = 1; i < 4; i++) {
132
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 1004 times.
1206 if (frame->data[i])
133 202 frame->data[i] += i * plane_padding;
134 1206 frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->data[i], align);
135 }
136
137 402 frame->extended_data = frame->data;
138
139 402 return 0;
140 fail:
141 av_frame_unref(frame);
142 return ret;
143 }
144
145 14441 static int get_audio_buffer(AVFrame *frame, int align)
146 {
147 14441 int planar = av_sample_fmt_is_planar(frame->format);
148 int channels, planes;
149 size_t size;
150 int ret;
151
152 14441 channels = frame->ch_layout.nb_channels;
153
2/2
✓ Branch 0 taken 1159 times.
✓ Branch 1 taken 13282 times.
14441 planes = planar ? channels : 1;
154
1/2
✓ Branch 0 taken 14441 times.
✗ Branch 1 not taken.
14441 if (!frame->linesize[0]) {
155 14441 ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
156 14441 frame->nb_samples, frame->format,
157 align);
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14441 times.
14441 if (ret < 0)
159 return ret;
160 }
161
162
2/2
✓ Branch 0 taken 14412 times.
✓ Branch 1 taken 29 times.
14441 if (align <= 0)
163 14412 align = ALIGN;
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14441 times.
14441 if (planes > AV_NUM_DATA_POINTERS) {
166 frame->extended_data = av_calloc(planes,
167 sizeof(*frame->extended_data));
168 frame->extended_buf = av_calloc(planes - AV_NUM_DATA_POINTERS,
169 sizeof(*frame->extended_buf));
170 if (!frame->extended_data || !frame->extended_buf) {
171 av_freep(&frame->extended_data);
172 av_freep(&frame->extended_buf);
173 return AVERROR(ENOMEM);
174 }
175 frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
176 } else
177 14441 frame->extended_data = frame->data;
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14441 times.
14441 if (frame->linesize[0] > SIZE_MAX - align)
180 return AVERROR(EINVAL);
181 14441 size = frame->linesize[0] + (size_t)align;
182
183
2/2
✓ Branch 0 taken 15236 times.
✓ Branch 1 taken 14441 times.
29677 for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
184 15236 frame->buf[i] = av_buffer_alloc(size);
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15236 times.
15236 if (!frame->buf[i]) {
186 av_frame_unref(frame);
187 return AVERROR(ENOMEM);
188 }
189 15236 frame->extended_data[i] = frame->data[i] =
190 15236 (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, align);
191 }
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14441 times.
14441 for (int i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {
193 frame->extended_buf[i] = av_buffer_alloc(size);
194 if (!frame->extended_buf[i]) {
195 av_frame_unref(frame);
196 return AVERROR(ENOMEM);
197 }
198 frame->extended_data[i + AV_NUM_DATA_POINTERS] =
199 (uint8_t *)FFALIGN((uintptr_t)frame->extended_buf[i]->data, align);
200 }
201 14441 return 0;
202
203 }
204
205 14843 int av_frame_get_buffer(AVFrame *frame, int align)
206 {
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14843 times.
14843 if (frame->format < 0)
208 return AVERROR(EINVAL);
209
210
3/4
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 14441 times.
✓ Branch 2 taken 402 times.
✗ Branch 3 not taken.
14843 if (frame->width > 0 && frame->height > 0)
211 402 return get_video_buffer(frame, align);
212
2/4
✓ Branch 0 taken 14441 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14441 times.
✗ Branch 3 not taken.
28882 else if (frame->nb_samples > 0 &&
213 14441 (av_channel_layout_check(&frame->ch_layout)))
214 14441 return get_audio_buffer(frame, align);
215
216 return AVERROR(EINVAL);
217 }
218
219 1174841 static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
220 {
221 1174841 dst->pict_type = src->pict_type;
222 1174841 dst->sample_aspect_ratio = src->sample_aspect_ratio;
223 1174841 dst->crop_top = src->crop_top;
224 1174841 dst->crop_bottom = src->crop_bottom;
225 1174841 dst->crop_left = src->crop_left;
226 1174841 dst->crop_right = src->crop_right;
227 1174841 dst->pts = src->pts;
228 1174841 dst->duration = src->duration;
229 1174841 dst->repeat_pict = src->repeat_pict;
230 1174841 dst->sample_rate = src->sample_rate;
231 1174841 dst->opaque = src->opaque;
232 1174841 dst->pkt_dts = src->pkt_dts;
233 1174841 dst->time_base = src->time_base;
234 1174841 dst->quality = src->quality;
235 1174841 dst->best_effort_timestamp = src->best_effort_timestamp;
236 1174841 dst->flags = src->flags;
237 1174841 dst->decode_error_flags = src->decode_error_flags;
238 1174841 dst->color_primaries = src->color_primaries;
239 1174841 dst->color_trc = src->color_trc;
240 1174841 dst->colorspace = src->colorspace;
241 1174841 dst->color_range = src->color_range;
242 1174841 dst->chroma_location = src->chroma_location;
243
244 1174841 av_dict_copy(&dst->metadata, src->metadata, 0);
245
246
2/2
✓ Branch 0 taken 36181 times.
✓ Branch 1 taken 1174841 times.
1211022 for (int i = 0; i < src->nb_side_data; i++) {
247 36181 const AVFrameSideData *sd_src = src->side_data[i];
248 AVFrameSideData *sd_dst;
249
2/2
✓ Branch 0 taken 13385 times.
✓ Branch 1 taken 22796 times.
36181 if ( sd_src->type == AV_FRAME_DATA_PANSCAN
250
2/4
✓ Branch 0 taken 13385 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13385 times.
13385 && (src->width != dst->width || src->height != dst->height))
251 continue;
252
2/2
✓ Branch 0 taken 4765 times.
✓ Branch 1 taken 31416 times.
36181 if (force_copy) {
253 4765 sd_dst = av_frame_new_side_data(dst, sd_src->type,
254 4765 sd_src->size);
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4765 times.
4765 if (!sd_dst) {
256 av_frame_side_data_free(&dst->side_data, &dst->nb_side_data);
257 return AVERROR(ENOMEM);
258 }
259 4765 memcpy(sd_dst->data, sd_src->data, sd_src->size);
260 } else {
261 31416 AVBufferRef *ref = av_buffer_ref(sd_src->buf);
262 31416 sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref);
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31416 times.
31416 if (!sd_dst) {
264 av_buffer_unref(&ref);
265 av_frame_side_data_free(&dst->side_data, &dst->nb_side_data);
266 return AVERROR(ENOMEM);
267 }
268 }
269 36181 av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
270 }
271
272 1174841 av_refstruct_replace(&dst->private_ref, src->private_ref);
273 1174841 return av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
274 }
275
276 805022 int av_frame_ref(AVFrame *dst, const AVFrame *src)
277 {
278 805022 int ret = 0;
279
280 av_assert1(dst->width == 0 && dst->height == 0);
281 av_assert1(dst->ch_layout.nb_channels == 0 &&
282 dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
283
284 805022 dst->format = src->format;
285 805022 dst->width = src->width;
286 805022 dst->height = src->height;
287 805022 dst->nb_samples = src->nb_samples;
288
289 805022 ret = frame_copy_props(dst, src, 0);
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 805022 times.
805022 if (ret < 0)
291 goto fail;
292
293 805022 ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 805022 times.
805022 if (ret < 0)
295 goto fail;
296
297 /* duplicate the frame data if it's not refcounted */
298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 805022 times.
805022 if (!src->buf[0]) {
299 ret = av_frame_get_buffer(dst, 0);
300 if (ret < 0)
301 goto fail;
302
303 ret = av_frame_copy(dst, src);
304 if (ret < 0)
305 goto fail;
306
307 return 0;
308 }
309
310 /* ref the buffers */
311
2/2
✓ Branch 0 taken 6440176 times.
✓ Branch 1 taken 805022 times.
7245198 for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
312
2/2
✓ Branch 0 taken 4887413 times.
✓ Branch 1 taken 1552763 times.
6440176 if (!src->buf[i])
313 4887413 continue;
314 1552763 dst->buf[i] = av_buffer_ref(src->buf[i]);
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1552763 times.
1552763 if (!dst->buf[i]) {
316 ret = AVERROR(ENOMEM);
317 goto fail;
318 }
319 }
320
321
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 804956 times.
805022 if (src->extended_buf) {
322 66 dst->extended_buf = av_calloc(src->nb_extended_buf,
323 sizeof(*dst->extended_buf));
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!dst->extended_buf) {
325 ret = AVERROR(ENOMEM);
326 goto fail;
327 }
328 66 dst->nb_extended_buf = src->nb_extended_buf;
329
330
2/2
✓ Branch 0 taken 3828 times.
✓ Branch 1 taken 66 times.
3894 for (int i = 0; i < src->nb_extended_buf; i++) {
331 3828 dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]);
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3828 times.
3828 if (!dst->extended_buf[i]) {
333 ret = AVERROR(ENOMEM);
334 goto fail;
335 }
336 }
337 }
338
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 805022 times.
805022 if (src->hw_frames_ctx) {
340 dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
341 if (!dst->hw_frames_ctx) {
342 ret = AVERROR(ENOMEM);
343 goto fail;
344 }
345 }
346
347 /* duplicate extended data */
348
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 804956 times.
805022 if (src->extended_data != src->data) {
349 66 int ch = dst->ch_layout.nb_channels;
350
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!ch) {
352 ret = AVERROR(EINVAL);
353 goto fail;
354 }
355
356 66 dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch);
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (!dst->extended_data) {
358 ret = AVERROR(ENOMEM);
359 goto fail;
360 }
361 66 memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch);
362 } else
363 804956 dst->extended_data = dst->data;
364
365 805022 memcpy(dst->data, src->data, sizeof(src->data));
366 805022 memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
367
368 805022 return 0;
369
370 fail:
371 av_frame_unref(dst);
372 return ret;
373 }
374
375 4353 int av_frame_replace(AVFrame *dst, const AVFrame *src)
376 {
377 4353 int ret = 0;
378
379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (dst == src)
380 return AVERROR(EINVAL);
381
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (!src->buf[0]) {
383 av_frame_unref(dst);
384
385 /* duplicate the frame data if it's not refcounted */
386 if ( src->data[0] || src->data[1]
387 || src->data[2] || src->data[3])
388 return av_frame_ref(dst, src);
389
390 ret = frame_copy_props(dst, src, 0);
391 if (ret < 0)
392 goto fail;
393 }
394
395 4353 dst->format = src->format;
396 4353 dst->width = src->width;
397 4353 dst->height = src->height;
398 4353 dst->nb_samples = src->nb_samples;
399
400 4353 ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (ret < 0)
402 goto fail;
403
404 4353 av_frame_side_data_free(&dst->side_data, &dst->nb_side_data);
405 4353 av_dict_free(&dst->metadata);
406 4353 ret = frame_copy_props(dst, src, 0);
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (ret < 0)
408 goto fail;
409
410 /* replace the buffers */
411
2/2
✓ Branch 0 taken 34824 times.
✓ Branch 1 taken 4353 times.
39177 for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
412 34824 ret = av_buffer_replace(&dst->buf[i], src->buf[i]);
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34824 times.
34824 if (ret < 0)
414 goto fail;
415 }
416
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (src->extended_buf) {
418 if (dst->nb_extended_buf != src->nb_extended_buf) {
419 int nb_extended_buf = FFMIN(dst->nb_extended_buf, src->nb_extended_buf);
420 void *tmp;
421
422 for (int i = nb_extended_buf; i < dst->nb_extended_buf; i++)
423 av_buffer_unref(&dst->extended_buf[i]);
424
425 tmp = av_realloc_array(dst->extended_buf, sizeof(*dst->extended_buf),
426 src->nb_extended_buf);
427 if (!tmp) {
428 ret = AVERROR(ENOMEM);
429 goto fail;
430 }
431 dst->extended_buf = tmp;
432 dst->nb_extended_buf = src->nb_extended_buf;
433
434 memset(&dst->extended_buf[nb_extended_buf], 0,
435 (src->nb_extended_buf - nb_extended_buf) * sizeof(*dst->extended_buf));
436 }
437
438 for (int i = 0; i < src->nb_extended_buf; i++) {
439 ret = av_buffer_replace(&dst->extended_buf[i], src->extended_buf[i]);
440 if (ret < 0)
441 goto fail;
442 }
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 } else if (dst->extended_buf) {
444 for (int i = 0; i < dst->nb_extended_buf; i++)
445 av_buffer_unref(&dst->extended_buf[i]);
446 av_freep(&dst->extended_buf);
447 }
448
449 4353 ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx);
450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (ret < 0)
451 goto fail;
452
453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 if (dst->extended_data != dst->data)
454 av_freep(&dst->extended_data);
455
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4353 times.
4353 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 if (ch > SIZE_MAX / sizeof(*dst->extended_data))
465 goto fail;
466
467 dst->extended_data = av_memdup(src->extended_data, sizeof(*dst->extended_data) * ch);
468 if (!dst->extended_data) {
469 ret = AVERROR(ENOMEM);
470 goto fail;
471 }
472 } else
473 4353 dst->extended_data = dst->data;
474
475 4353 memcpy(dst->data, src->data, sizeof(src->data));
476 4353 memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
477
478 4353 return 0;
479
480 fail:
481 av_frame_unref(dst);
482 return ret;
483 }
484
485 46209 AVFrame *av_frame_clone(const AVFrame *src)
486 {
487 46209 AVFrame *ret = av_frame_alloc();
488
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46209 times.
46209 if (!ret)
490 return NULL;
491
492
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46209 times.
46209 if (av_frame_ref(ret, src) < 0)
493 av_frame_free(&ret);
494
495 46209 return ret;
496 }
497
498 7419268 void av_frame_unref(AVFrame *frame)
499 {
500
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7419264 times.
7419268 if (!frame)
501 4 return;
502
503 7419264 av_frame_side_data_free(&frame->side_data, &frame->nb_side_data);
504
505
2/2
✓ Branch 0 taken 59354112 times.
✓ Branch 1 taken 7419264 times.
66773376 for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
506 59354112 av_buffer_unref(&frame->buf[i]);
507
2/2
✓ Branch 0 taken 5720 times.
✓ Branch 1 taken 7419264 times.
7424984 for (int i = 0; i < frame->nb_extended_buf; i++)
508 5720 av_buffer_unref(&frame->extended_buf[i]);
509 7419264 av_freep(&frame->extended_buf);
510 7419264 av_dict_free(&frame->metadata);
511
512 7419264 av_buffer_unref(&frame->hw_frames_ctx);
513
514 7419264 av_buffer_unref(&frame->opaque_ref);
515 7419264 av_refstruct_unref(&frame->private_ref);
516
517
2/2
✓ Branch 0 taken 584 times.
✓ Branch 1 taken 7418680 times.
7419264 if (frame->extended_data != frame->data)
518 584 av_freep(&frame->extended_data);
519
520 7419264 av_channel_layout_uninit(&frame->ch_layout);
521
522 7419264 get_frame_defaults(frame);
523 }
524
525 3501942 void av_frame_move_ref(AVFrame *dst, AVFrame *src)
526 {
527 av_assert1(dst->width == 0 && dst->height == 0);
528 av_assert1(dst->ch_layout.nb_channels == 0 &&
529 dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
530
531 3501942 *dst = *src;
532
1/2
✓ Branch 0 taken 3501942 times.
✗ Branch 1 not taken.
3501942 if (src->extended_data == src->data)
533 3501942 dst->extended_data = dst->data;
534 3501942 get_frame_defaults(src);
535 3501942 }
536
537 18205 int av_frame_is_writable(AVFrame *frame)
538 {
539 18205 int ret = 1;
540
541 /* assume non-refcounted frames are not writable */
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18205 times.
18205 if (!frame->buf[0])
543 return 0;
544
545
2/2
✓ Branch 0 taken 145640 times.
✓ Branch 1 taken 18205 times.
163845 for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
546
2/2
✓ Branch 0 taken 36939 times.
✓ Branch 1 taken 108701 times.
145640 if (frame->buf[i])
547 36939 ret &= !!av_buffer_is_writable(frame->buf[i]);
548
2/2
✓ Branch 0 taken 1834 times.
✓ Branch 1 taken 18205 times.
20039 for (int i = 0; i < frame->nb_extended_buf; i++)
549 1834 ret &= !!av_buffer_is_writable(frame->extended_buf[i]);
550
551 18205 return ret;
552 }
553
554 3200 int av_frame_make_writable(AVFrame *frame)
555 {
556 AVFrame tmp;
557 int ret;
558
559
1/2
✓ Branch 1 taken 3200 times.
✗ Branch 2 not taken.
3200 if (av_frame_is_writable(frame))
560 3200 return 0;
561
562 memset(&tmp, 0, sizeof(tmp));
563 tmp.format = frame->format;
564 tmp.width = frame->width;
565 tmp.height = frame->height;
566 tmp.nb_samples = frame->nb_samples;
567 ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout);
568 if (ret < 0) {
569 av_frame_unref(&tmp);
570 return ret;
571 }
572
573 if (frame->hw_frames_ctx)
574 ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0);
575 else
576 ret = av_frame_get_buffer(&tmp, 0);
577 if (ret < 0)
578 return ret;
579
580 ret = av_frame_copy(&tmp, frame);
581 if (ret < 0) {
582 av_frame_unref(&tmp);
583 return ret;
584 }
585
586 ret = av_frame_copy_props(&tmp, frame);
587 if (ret < 0) {
588 av_frame_unref(&tmp);
589 return ret;
590 }
591
592 av_frame_unref(frame);
593
594 *frame = tmp;
595 if (tmp.data == tmp.extended_data)
596 frame->extended_data = frame->data;
597
598 return 0;
599 }
600
601 365466 int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
602 {
603 365466 return frame_copy_props(dst, src, 1);
604 }
605
606 5594 AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane)
607 {
608 uintptr_t data;
609 int planes;
610
611
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 5137 times.
5594 if (frame->nb_samples) {
612 457 int channels = frame->ch_layout.nb_channels;
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (!channels)
614 return NULL;
615
1/2
✓ Branch 1 taken 457 times.
✗ Branch 2 not taken.
457 planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
616 } else
617 5137 planes = 4;
618
619
3/6
✓ Branch 0 taken 5594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5594 times.
5594 if (plane < 0 || plane >= planes || !frame->extended_data[plane])
620 return NULL;
621 5594 data = (uintptr_t)frame->extended_data[plane];
622
623
2/4
✓ Branch 0 taken 13138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13138 times.
✗ Branch 3 not taken.
13138 for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) {
624 13138 AVBufferRef *buf = frame->buf[i];
625 13138 uintptr_t buf_begin = (uintptr_t)buf->data;
626
627
4/4
✓ Branch 0 taken 11998 times.
✓ Branch 1 taken 1140 times.
✓ Branch 2 taken 5594 times.
✓ Branch 3 taken 6404 times.
13138 if (data >= buf_begin && data < buf_begin + buf->size)
628 5594 return buf;
629 }
630 for (int i = 0; i < frame->nb_extended_buf; i++) {
631 AVBufferRef *buf = frame->extended_buf[i];
632 uintptr_t buf_begin = (uintptr_t)buf->data;
633
634 if (data >= buf_begin && data < buf_begin + buf->size)
635 return buf;
636 }
637 return NULL;
638 }
639
640 47796 AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
641 enum AVFrameSideDataType type,
642 AVBufferRef *buf)
643 {
644 return
645 47796 ff_frame_side_data_add_from_buf(
646 &frame->side_data, &frame->nb_side_data, type, buf);
647 }
648
649 16311 AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
650 enum AVFrameSideDataType type,
651 size_t size)
652 {
653 AVFrameSideData *ret;
654 16311 AVBufferRef *buf = av_buffer_alloc(size);
655 16311 ret = av_frame_new_side_data_from_buf(frame, type, buf);
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16311 times.
16311 if (!ret)
657 av_buffer_unref(&buf);
658 16311 return ret;
659 }
660
661 2138184 AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
662 enum AVFrameSideDataType type)
663 {
664 4276368 return (AVFrameSideData *)av_frame_side_data_get(
665 2138184 frame->side_data, frame->nb_side_data,
666 type
667 );
668 }
669
670 9927 static int frame_copy_video(AVFrame *dst, const AVFrame *src)
671 {
672 int planes;
673
674
1/2
✓ Branch 0 taken 9927 times.
✗ Branch 1 not taken.
9927 if (dst->width < src->width ||
675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9927 times.
9927 dst->height < src->height)
676 return AVERROR(EINVAL);
677
678
2/4
✓ Branch 0 taken 9927 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9927 times.
9927 if (src->hw_frames_ctx || dst->hw_frames_ctx)
679 return av_hwframe_transfer_data(dst, src, 0);
680
681 9927 planes = av_pix_fmt_count_planes(dst->format);
682
2/2
✓ Branch 0 taken 16194 times.
✓ Branch 1 taken 9927 times.
26121 for (int i = 0; i < planes; i++)
683
2/4
✓ Branch 0 taken 16194 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16194 times.
16194 if (!dst->data[i] || !src->data[i])
684 return AVERROR(EINVAL);
685
686 9927 av_image_copy2(dst->data, dst->linesize,
687 9927 src->data, src->linesize,
688 9927 dst->format, src->width, src->height);
689
690 9927 return 0;
691 }
692
693 static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
694 {
695 int planar = av_sample_fmt_is_planar(dst->format);
696 int channels = dst->ch_layout.nb_channels;
697 int planes = planar ? channels : 1;
698
699 if (dst->nb_samples != src->nb_samples ||
700 av_channel_layout_compare(&dst->ch_layout, &src->ch_layout))
701 return AVERROR(EINVAL);
702
703 for (int i = 0; i < planes; i++)
704 if (!dst->extended_data[i] || !src->extended_data[i])
705 return AVERROR(EINVAL);
706
707 av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
708 dst->nb_samples, channels, dst->format);
709
710 return 0;
711 }
712
713 9927 int av_frame_copy(AVFrame *dst, const AVFrame *src)
714 {
715
2/4
✓ Branch 0 taken 9927 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9927 times.
9927 if (dst->format != src->format || dst->format < 0)
716 return AVERROR(EINVAL);
717
718
2/4
✓ Branch 0 taken 9927 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9927 times.
✗ Branch 3 not taken.
9927 if (dst->width > 0 && dst->height > 0)
719 9927 return frame_copy_video(dst, src);
720 else if (dst->nb_samples > 0 &&
721 (av_channel_layout_check(&dst->ch_layout)))
722 return frame_copy_audio(dst, src);
723
724 return AVERROR(EINVAL);
725 }
726
727 407086 void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
728 {
729 407086 av_frame_side_data_remove(&frame->side_data, &frame->nb_side_data, type);
730 407086 }
731
732 145508 static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
733 const AVPixFmtDescriptor *desc)
734 {
735
2/2
✓ Branch 0 taken 410309 times.
✓ Branch 1 taken 140768 times.
551077 for (int i = 0; frame->data[i]; i++) {
736 410309 const AVComponentDescriptor *comp = NULL;
737
4/4
✓ Branch 0 taken 275907 times.
✓ Branch 1 taken 134402 times.
✓ Branch 2 taken 129659 times.
✓ Branch 3 taken 146248 times.
410309 int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
738
4/4
✓ Branch 0 taken 275907 times.
✓ Branch 1 taken 134402 times.
✓ Branch 2 taken 129659 times.
✓ Branch 3 taken 146248 times.
410309 int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
739
740
4/4
✓ Branch 0 taken 9480 times.
✓ Branch 1 taken 400829 times.
✓ Branch 2 taken 4740 times.
✓ Branch 3 taken 4740 times.
410309 if (desc->flags & AV_PIX_FMT_FLAG_PAL && i == 1) {
741 4740 offsets[i] = 0;
742 4740 break;
743 }
744
745 /* find any component descriptor for this plane */
746
1/2
✓ Branch 0 taken 796769 times.
✗ Branch 1 not taken.
796769 for (int j = 0; j < desc->nb_components; j++) {
747
2/2
✓ Branch 0 taken 405569 times.
✓ Branch 1 taken 391200 times.
796769 if (desc->comp[j].plane == i) {
748 405569 comp = &desc->comp[j];
749 405569 break;
750 }
751 }
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 405569 times.
405569 if (!comp)
753 return AVERROR_BUG;
754
755 405569 offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
756 405569 (frame->crop_left >> shift_x) * comp->step;
757 }
758
759 145508 return 0;
760 }
761
762 145812 int av_frame_apply_cropping(AVFrame *frame, int flags)
763 {
764 const AVPixFmtDescriptor *desc;
765 size_t offsets[4];
766 int ret;
767
768
2/4
✓ Branch 0 taken 145812 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 145812 times.
145812 if (!(frame->width > 0 && frame->height > 0))
769 return AVERROR(EINVAL);
770
771
1/2
✓ Branch 0 taken 145812 times.
✗ Branch 1 not taken.
145812 if (frame->crop_left >= INT_MAX - frame->crop_right ||
772
1/2
✓ Branch 0 taken 145812 times.
✗ Branch 1 not taken.
145812 frame->crop_top >= INT_MAX - frame->crop_bottom ||
773
1/2
✓ Branch 0 taken 145812 times.
✗ Branch 1 not taken.
145812 (frame->crop_left + frame->crop_right) >= frame->width ||
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145812 times.
145812 (frame->crop_top + frame->crop_bottom) >= frame->height)
775 return AVERROR(ERANGE);
776
777 145812 desc = av_pix_fmt_desc_get(frame->format);
778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145812 times.
145812 if (!desc)
779 return AVERROR_BUG;
780
781 /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
782 * formats cannot be easily handled here either (and corresponding decoders
783 * should not export any cropping anyway), so do the same for those as well.
784 * */
785
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 145494 times.
145812 if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
786 318 frame->width -= frame->crop_right;
787 318 frame->height -= frame->crop_bottom;
788 318 frame->crop_right = 0;
789 318 frame->crop_bottom = 0;
790 318 return 0;
791 }
792
793 /* calculate the offsets for each plane */
794 145494 ret = calc_cropping_offsets(offsets, frame, desc);
795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145494 times.
145494 if (ret < 0)
796 return ret;
797
798 /* adjust the offsets to avoid breaking alignment */
799
2/2
✓ Branch 0 taken 7299 times.
✓ Branch 1 taken 138195 times.
145494 if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
800
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7285 times.
7299 int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
801 7299 int min_log2_align = INT_MAX;
802
803
2/2
✓ Branch 0 taken 21421 times.
✓ Branch 1 taken 7299 times.
28720 for (int i = 0; frame->data[i]; i++) {
804
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 21379 times.
21421 int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
805 21421 min_log2_align = FFMIN(log2_align, min_log2_align);
806 }
807
808 /* we assume, and it should always be true, that the data alignment is
809 * related to the cropping alignment by a constant power-of-2 factor */
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7299 times.
7299 if (log2_crop_align < min_log2_align)
811 return AVERROR_BUG;
812
813
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7285 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
7299 if (min_log2_align < 5 && log2_crop_align != INT_MAX) {
814 14 frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
815 14 ret = calc_cropping_offsets(offsets, frame, desc);
816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (ret < 0)
817 return ret;
818 }
819 }
820
821
2/2
✓ Branch 0 taken 410267 times.
✓ Branch 1 taken 145494 times.
555761 for (int i = 0; frame->data[i]; i++)
822 410267 frame->data[i] += offsets[i];
823
824 145494 frame->width -= (frame->crop_left + frame->crop_right);
825 145494 frame->height -= (frame->crop_top + frame->crop_bottom);
826 145494 frame->crop_left = 0;
827 145494 frame->crop_right = 0;
828 145494 frame->crop_top = 0;
829 145494 frame->crop_bottom = 0;
830
831 145494 return 0;
832 }
833