/src/vlc/contrib/contrib-build/bpg/libavutil/frame.c
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * This file is part of FFmpeg. |
4 | | * |
5 | | * FFmpeg is free software; you can redistribute it and/or |
6 | | * modify it under the terms of the GNU Lesser General Public |
7 | | * License as published by the Free Software Foundation; either |
8 | | * version 2.1 of the License, or (at your option) any later version. |
9 | | * |
10 | | * FFmpeg is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | | * Lesser General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU Lesser General Public |
16 | | * License along with FFmpeg; if not, write to the Free Software |
17 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | | */ |
19 | | |
20 | | #include "channel_layout.h" |
21 | | #include "avassert.h" |
22 | | #include "buffer.h" |
23 | | #include "common.h" |
24 | | #include "dict.h" |
25 | | #include "frame.h" |
26 | | #include "imgutils.h" |
27 | | #include "mem.h" |
28 | | #include "samplefmt.h" |
29 | | |
30 | | MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) |
31 | | MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration) |
32 | | MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_pos) |
33 | | MAKE_ACCESSORS(AVFrame, frame, int64_t, channel_layout) |
34 | | MAKE_ACCESSORS(AVFrame, frame, int, channels) |
35 | | MAKE_ACCESSORS(AVFrame, frame, int, sample_rate) |
36 | | MAKE_ACCESSORS(AVFrame, frame, int, decode_error_flags) |
37 | | MAKE_ACCESSORS(AVFrame, frame, int, pkt_size) |
38 | | MAKE_ACCESSORS(AVFrame, frame, enum AVColorSpace, colorspace) |
39 | | MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range) |
40 | | |
41 | | #define CHECK_CHANNELS_CONSISTENCY(frame) \ |
42 | | av_assert2(!(frame)->channel_layout || \ |
43 | | (frame)->channels == \ |
44 | | av_get_channel_layout_nb_channels((frame)->channel_layout)) |
45 | | |
46 | | static void get_frame_defaults(AVFrame *frame) |
47 | 0 | { |
48 | 0 | memset(frame, 0, sizeof(*frame)); |
49 | |
|
50 | 0 | frame->pts = |
51 | 0 | frame->pkt_dts = |
52 | 0 | frame->pkt_pts = AV_NOPTS_VALUE; |
53 | 0 | av_frame_set_best_effort_timestamp(frame, AV_NOPTS_VALUE); |
54 | 0 | av_frame_set_pkt_duration (frame, 0); |
55 | 0 | av_frame_set_pkt_pos (frame, -1); |
56 | 0 | av_frame_set_pkt_size (frame, -1); |
57 | 0 | frame->key_frame = 1; |
58 | 0 | frame->sample_aspect_ratio = (AVRational){ 0, 1 }; |
59 | 0 | frame->format = -1; /* unknown */ |
60 | 0 | frame->color_primaries = AVCOL_PRI_UNSPECIFIED; |
61 | 0 | frame->color_trc = AVCOL_TRC_UNSPECIFIED; |
62 | 0 | frame->colorspace = AVCOL_SPC_UNSPECIFIED; |
63 | 0 | frame->color_range = AVCOL_RANGE_UNSPECIFIED; |
64 | 0 | frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED; |
65 | 0 | } |
66 | | |
67 | | static void free_side_data(AVFrameSideData **ptr_sd) |
68 | 0 | { |
69 | 0 | AVFrameSideData *sd = *ptr_sd; |
70 | 0 |
|
71 | 0 | av_freep(&sd->data); |
72 | 0 | av_freep(ptr_sd); |
73 | 0 | } |
74 | | |
75 | | AVFrame *av_frame_alloc(void) |
76 | 0 | { |
77 | 0 | AVFrame *frame = av_mallocz(sizeof(*frame)); |
78 | |
|
79 | 0 | if (!frame) |
80 | 0 | return NULL; |
81 | | |
82 | 0 | get_frame_defaults(frame); |
83 | |
|
84 | 0 | return frame; |
85 | 0 | } |
86 | | |
87 | | void av_frame_free(AVFrame **frame) |
88 | 8 | { |
89 | 8 | if (!frame || !*frame) |
90 | 8 | return; |
91 | | |
92 | 0 | av_frame_unref(*frame); |
93 | 0 | av_freep(frame); |
94 | 0 | } |
95 | | |
96 | | void av_frame_unref(AVFrame *frame) |
97 | 0 | { |
98 | 0 | int i; |
99 | |
|
100 | 0 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) |
101 | 0 | av_buffer_unref(&frame->buf[i]); |
102 | |
|
103 | 0 | get_frame_defaults(frame); |
104 | 0 | } |
105 | | |
106 | | void av_frame_move_ref(AVFrame *dst, AVFrame *src) |
107 | 0 | { |
108 | 0 | *dst = *src; |
109 | 0 | memset(src, 0, sizeof(*src)); |
110 | 0 | get_frame_defaults(src); |
111 | 0 | } |
112 | | |
113 | | int av_frame_ref(AVFrame *dst, const AVFrame *src) |
114 | 0 | { |
115 | 0 | int i, ret = 0; |
116 | |
|
117 | 0 | dst->format = src->format; |
118 | 0 | dst->width = src->width; |
119 | 0 | dst->height = src->height; |
120 | 0 | dst->channels = src->channels; |
121 | 0 | dst->channel_layout = src->channel_layout; |
122 | 0 | dst->nb_samples = src->nb_samples; |
123 | | |
124 | | /* duplicate the frame data if it's not refcounted */ |
125 | 0 | if (!src->buf[0]) { |
126 | 0 | abort(); |
127 | | #if 0 |
128 | | ret = av_frame_get_buffer(dst, 32); |
129 | | if (ret < 0) |
130 | | return ret; |
131 | | |
132 | | ret = av_frame_copy(dst, src); |
133 | | if (ret < 0) |
134 | | av_frame_unref(dst); |
135 | | |
136 | | return ret; |
137 | | #endif |
138 | 0 | } |
139 | | |
140 | | /* ref the buffers */ |
141 | 0 | for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { |
142 | 0 | if (!src->buf[i]) |
143 | 0 | continue; |
144 | 0 | dst->buf[i] = av_buffer_ref(src->buf[i]); |
145 | 0 | if (!dst->buf[i]) { |
146 | 0 | ret = AVERROR(ENOMEM); |
147 | 0 | goto fail; |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | 0 | memcpy(dst->data, src->data, sizeof(src->data)); |
152 | 0 | memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); |
153 | |
|
154 | 0 | return 0; |
155 | | |
156 | 0 | fail: |
157 | 0 | av_frame_unref(dst); |
158 | 0 | return ret; |
159 | 0 | } |
160 | | |
161 | | #if 0 |
162 | | static int get_video_buffer(AVFrame *frame, int align) |
163 | | { |
164 | | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); |
165 | | int ret, i; |
166 | | |
167 | | if (!desc) |
168 | | return AVERROR(EINVAL); |
169 | | |
170 | | if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0) |
171 | | return ret; |
172 | | |
173 | | if (!frame->linesize[0]) { |
174 | | for(i=1; i<=align; i+=i) { |
175 | | ret = av_image_fill_linesizes(frame->linesize, frame->format, |
176 | | FFALIGN(frame->width, i)); |
177 | | if (ret < 0) |
178 | | return ret; |
179 | | if (!(frame->linesize[0] & (align-1))) |
180 | | break; |
181 | | } |
182 | | |
183 | | for (i = 0; i < 4 && frame->linesize[i]; i++) |
184 | | frame->linesize[i] = FFALIGN(frame->linesize[i], align); |
185 | | } |
186 | | |
187 | | for (i = 0; i < 4 && frame->linesize[i]; i++) { |
188 | | int h = FFALIGN(frame->height, 32); |
189 | | if (i == 1 || i == 2) |
190 | | h = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); |
191 | | |
192 | | frame->buf[i] = av_buffer_alloc(frame->linesize[i] * h + 16 + 16/*STRIDE_ALIGN*/ - 1); |
193 | | if (!frame->buf[i]) |
194 | | goto fail; |
195 | | |
196 | | frame->data[i] = frame->buf[i]->data; |
197 | | } |
198 | | if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
199 | | av_buffer_unref(&frame->buf[1]); |
200 | | frame->buf[1] = av_buffer_alloc(1024); |
201 | | if (!frame->buf[1]) |
202 | | goto fail; |
203 | | frame->data[1] = frame->buf[1]->data; |
204 | | } |
205 | | |
206 | | frame->extended_data = frame->data; |
207 | | |
208 | | return 0; |
209 | | fail: |
210 | | av_frame_unref(frame); |
211 | | return AVERROR(ENOMEM); |
212 | | } |
213 | | |
214 | | static int get_audio_buffer(AVFrame *frame, int align) |
215 | | { |
216 | | int channels; |
217 | | int planar = av_sample_fmt_is_planar(frame->format); |
218 | | int planes; |
219 | | int ret, i; |
220 | | |
221 | | if (!frame->channels) |
222 | | frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout); |
223 | | |
224 | | channels = frame->channels; |
225 | | planes = planar ? channels : 1; |
226 | | |
227 | | CHECK_CHANNELS_CONSISTENCY(frame); |
228 | | if (!frame->linesize[0]) { |
229 | | ret = av_samples_get_buffer_size(&frame->linesize[0], channels, |
230 | | frame->nb_samples, frame->format, |
231 | | align); |
232 | | if (ret < 0) |
233 | | return ret; |
234 | | } |
235 | | |
236 | | if (planes > AV_NUM_DATA_POINTERS) { |
237 | | frame->extended_data = av_mallocz_array(planes, |
238 | | sizeof(*frame->extended_data)); |
239 | | frame->extended_buf = av_mallocz_array((planes - AV_NUM_DATA_POINTERS), |
240 | | sizeof(*frame->extended_buf)); |
241 | | if (!frame->extended_data || !frame->extended_buf) { |
242 | | av_freep(&frame->extended_data); |
243 | | av_freep(&frame->extended_buf); |
244 | | return AVERROR(ENOMEM); |
245 | | } |
246 | | frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; |
247 | | } else |
248 | | frame->extended_data = frame->data; |
249 | | |
250 | | for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { |
251 | | frame->buf[i] = av_buffer_alloc(frame->linesize[0]); |
252 | | if (!frame->buf[i]) { |
253 | | av_frame_unref(frame); |
254 | | return AVERROR(ENOMEM); |
255 | | } |
256 | | frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; |
257 | | } |
258 | | for (i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) { |
259 | | frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]); |
260 | | if (!frame->extended_buf[i]) { |
261 | | av_frame_unref(frame); |
262 | | return AVERROR(ENOMEM); |
263 | | } |
264 | | frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; |
265 | | } |
266 | | return 0; |
267 | | |
268 | | } |
269 | | |
270 | | int av_frame_get_buffer(AVFrame *frame, int align) |
271 | | { |
272 | | if (frame->format < 0) |
273 | | return AVERROR(EINVAL); |
274 | | |
275 | | if (frame->width > 0 && frame->height > 0) |
276 | | return get_video_buffer(frame, align); |
277 | | else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0)) |
278 | | return get_audio_buffer(frame, align); |
279 | | |
280 | | return AVERROR(EINVAL); |
281 | | } |
282 | | |
283 | | |
284 | | int av_frame_ref(AVFrame *dst, const AVFrame *src) |
285 | | { |
286 | | int i, ret = 0; |
287 | | |
288 | | dst->format = src->format; |
289 | | dst->width = src->width; |
290 | | dst->height = src->height; |
291 | | dst->channels = src->channels; |
292 | | dst->channel_layout = src->channel_layout; |
293 | | dst->nb_samples = src->nb_samples; |
294 | | |
295 | | ret = av_frame_copy_props(dst, src); |
296 | | if (ret < 0) |
297 | | return ret; |
298 | | |
299 | | /* duplicate the frame data if it's not refcounted */ |
300 | | if (!src->buf[0]) { |
301 | | ret = av_frame_get_buffer(dst, 32); |
302 | | if (ret < 0) |
303 | | return ret; |
304 | | |
305 | | ret = av_frame_copy(dst, src); |
306 | | if (ret < 0) |
307 | | av_frame_unref(dst); |
308 | | |
309 | | return ret; |
310 | | } |
311 | | |
312 | | /* ref the buffers */ |
313 | | for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { |
314 | | if (!src->buf[i]) |
315 | | continue; |
316 | | dst->buf[i] = av_buffer_ref(src->buf[i]); |
317 | | if (!dst->buf[i]) { |
318 | | ret = AVERROR(ENOMEM); |
319 | | goto fail; |
320 | | } |
321 | | } |
322 | | |
323 | | if (src->extended_buf) { |
324 | | dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf), |
325 | | src->nb_extended_buf); |
326 | | if (!dst->extended_buf) { |
327 | | ret = AVERROR(ENOMEM); |
328 | | goto fail; |
329 | | } |
330 | | dst->nb_extended_buf = src->nb_extended_buf; |
331 | | |
332 | | for (i = 0; i < src->nb_extended_buf; i++) { |
333 | | dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]); |
334 | | if (!dst->extended_buf[i]) { |
335 | | ret = AVERROR(ENOMEM); |
336 | | goto fail; |
337 | | } |
338 | | } |
339 | | } |
340 | | |
341 | | /* duplicate extended data */ |
342 | | if (src->extended_data != src->data) { |
343 | | int ch = src->channels; |
344 | | |
345 | | if (!ch) { |
346 | | ret = AVERROR(EINVAL); |
347 | | goto fail; |
348 | | } |
349 | | CHECK_CHANNELS_CONSISTENCY(src); |
350 | | |
351 | | dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch); |
352 | | if (!dst->extended_data) { |
353 | | ret = AVERROR(ENOMEM); |
354 | | goto fail; |
355 | | } |
356 | | memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch); |
357 | | } else |
358 | | dst->extended_data = dst->data; |
359 | | |
360 | | memcpy(dst->data, src->data, sizeof(src->data)); |
361 | | memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); |
362 | | |
363 | | return 0; |
364 | | |
365 | | fail: |
366 | | av_frame_unref(dst); |
367 | | return ret; |
368 | | } |
369 | | |
370 | | AVFrame *av_frame_clone(const AVFrame *src) |
371 | | { |
372 | | AVFrame *ret = av_frame_alloc(); |
373 | | |
374 | | if (!ret) |
375 | | return NULL; |
376 | | |
377 | | if (av_frame_ref(ret, src) < 0) |
378 | | av_frame_free(&ret); |
379 | | |
380 | | return ret; |
381 | | } |
382 | | |
383 | | int av_frame_is_writable(AVFrame *frame) |
384 | | { |
385 | | int i, ret = 1; |
386 | | |
387 | | /* assume non-refcounted frames are not writable */ |
388 | | if (!frame->buf[0]) |
389 | | return 0; |
390 | | |
391 | | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) |
392 | | if (frame->buf[i]) |
393 | | ret &= !!av_buffer_is_writable(frame->buf[i]); |
394 | | for (i = 0; i < frame->nb_extended_buf; i++) |
395 | | ret &= !!av_buffer_is_writable(frame->extended_buf[i]); |
396 | | |
397 | | return ret; |
398 | | } |
399 | | |
400 | | int av_frame_make_writable(AVFrame *frame) |
401 | | { |
402 | | AVFrame tmp; |
403 | | int ret; |
404 | | |
405 | | if (!frame->buf[0]) |
406 | | return AVERROR(EINVAL); |
407 | | |
408 | | if (av_frame_is_writable(frame)) |
409 | | return 0; |
410 | | |
411 | | memset(&tmp, 0, sizeof(tmp)); |
412 | | tmp.format = frame->format; |
413 | | tmp.width = frame->width; |
414 | | tmp.height = frame->height; |
415 | | tmp.channels = frame->channels; |
416 | | tmp.channel_layout = frame->channel_layout; |
417 | | tmp.nb_samples = frame->nb_samples; |
418 | | ret = av_frame_get_buffer(&tmp, 32); |
419 | | if (ret < 0) |
420 | | return ret; |
421 | | |
422 | | ret = av_frame_copy(&tmp, frame); |
423 | | if (ret < 0) { |
424 | | av_frame_unref(&tmp); |
425 | | return ret; |
426 | | } |
427 | | |
428 | | ret = av_frame_copy_props(&tmp, frame); |
429 | | if (ret < 0) { |
430 | | av_frame_unref(&tmp); |
431 | | return ret; |
432 | | } |
433 | | |
434 | | av_frame_unref(frame); |
435 | | |
436 | | *frame = tmp; |
437 | | if (tmp.data == tmp.extended_data) |
438 | | frame->extended_data = frame->data; |
439 | | |
440 | | return 0; |
441 | | } |
442 | | |
443 | | int av_frame_copy_props(AVFrame *dst, const AVFrame *src) |
444 | | { |
445 | | int i; |
446 | | |
447 | | dst->key_frame = src->key_frame; |
448 | | dst->pict_type = src->pict_type; |
449 | | dst->sample_aspect_ratio = src->sample_aspect_ratio; |
450 | | dst->pts = src->pts; |
451 | | dst->repeat_pict = src->repeat_pict; |
452 | | dst->interlaced_frame = src->interlaced_frame; |
453 | | dst->top_field_first = src->top_field_first; |
454 | | dst->palette_has_changed = src->palette_has_changed; |
455 | | dst->sample_rate = src->sample_rate; |
456 | | dst->opaque = src->opaque; |
457 | | dst->pkt_pts = src->pkt_pts; |
458 | | dst->pkt_dts = src->pkt_dts; |
459 | | dst->pkt_pos = src->pkt_pos; |
460 | | dst->pkt_size = src->pkt_size; |
461 | | dst->pkt_duration = src->pkt_duration; |
462 | | dst->reordered_opaque = src->reordered_opaque; |
463 | | dst->quality = src->quality; |
464 | | dst->best_effort_timestamp = src->best_effort_timestamp; |
465 | | dst->coded_picture_number = src->coded_picture_number; |
466 | | dst->display_picture_number = src->display_picture_number; |
467 | | dst->flags = src->flags; |
468 | | dst->decode_error_flags = src->decode_error_flags; |
469 | | dst->color_primaries = src->color_primaries; |
470 | | dst->color_trc = src->color_trc; |
471 | | dst->colorspace = src->colorspace; |
472 | | dst->color_range = src->color_range; |
473 | | dst->chroma_location = src->chroma_location; |
474 | | |
475 | | memcpy(dst->error, src->error, sizeof(dst->error)); |
476 | | |
477 | | for (i = 0; i < src->nb_side_data; i++) { |
478 | | const AVFrameSideData *sd_src = src->side_data[i]; |
479 | | AVFrameSideData *sd_dst; |
480 | | if ( sd_src->type == AV_FRAME_DATA_PANSCAN |
481 | | && (src->width != dst->width || src->height != dst->height)) |
482 | | continue; |
483 | | sd_dst = av_frame_new_side_data(dst, sd_src->type, |
484 | | sd_src->size); |
485 | | if (!sd_dst) { |
486 | | for (i = 0; i < dst->nb_side_data; i++) { |
487 | | free_side_data(&dst->side_data[i]); |
488 | | } |
489 | | av_freep(&dst->side_data); |
490 | | return AVERROR(ENOMEM); |
491 | | } |
492 | | memcpy(sd_dst->data, sd_src->data, sd_src->size); |
493 | | } |
494 | | |
495 | | return 0; |
496 | | } |
497 | | |
498 | | AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) |
499 | | { |
500 | | uint8_t *data; |
501 | | int planes, i; |
502 | | |
503 | | if (frame->nb_samples) { |
504 | | int channels = frame->channels; |
505 | | if (!channels) |
506 | | return NULL; |
507 | | CHECK_CHANNELS_CONSISTENCY(frame); |
508 | | planes = av_sample_fmt_is_planar(frame->format) ? channels : 1; |
509 | | } else |
510 | | planes = 4; |
511 | | |
512 | | if (plane < 0 || plane >= planes || !frame->extended_data[plane]) |
513 | | return NULL; |
514 | | data = frame->extended_data[plane]; |
515 | | |
516 | | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) { |
517 | | AVBufferRef *buf = frame->buf[i]; |
518 | | if (data >= buf->data && data < buf->data + buf->size) |
519 | | return buf; |
520 | | } |
521 | | for (i = 0; i < frame->nb_extended_buf; i++) { |
522 | | AVBufferRef *buf = frame->extended_buf[i]; |
523 | | if (data >= buf->data && data < buf->data + buf->size) |
524 | | return buf; |
525 | | } |
526 | | return NULL; |
527 | | } |
528 | | |
529 | | AVFrameSideData *av_frame_new_side_data(AVFrame *frame, |
530 | | enum AVFrameSideDataType type, |
531 | | int size) |
532 | | { |
533 | | AVFrameSideData *ret, **tmp; |
534 | | |
535 | | if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1) |
536 | | return NULL; |
537 | | |
538 | | tmp = av_realloc(frame->side_data, |
539 | | (frame->nb_side_data + 1) * sizeof(*frame->side_data)); |
540 | | if (!tmp) |
541 | | return NULL; |
542 | | frame->side_data = tmp; |
543 | | |
544 | | ret = av_mallocz(sizeof(*ret)); |
545 | | if (!ret) |
546 | | return NULL; |
547 | | |
548 | | ret->data = av_malloc(size); |
549 | | if (!ret->data) { |
550 | | av_freep(&ret); |
551 | | return NULL; |
552 | | } |
553 | | |
554 | | ret->size = size; |
555 | | ret->type = type; |
556 | | |
557 | | frame->side_data[frame->nb_side_data++] = ret; |
558 | | |
559 | | return ret; |
560 | | } |
561 | | |
562 | | AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, |
563 | | enum AVFrameSideDataType type) |
564 | | { |
565 | | int i; |
566 | | |
567 | | for (i = 0; i < frame->nb_side_data; i++) { |
568 | | if (frame->side_data[i]->type == type) |
569 | | return frame->side_data[i]; |
570 | | } |
571 | | return NULL; |
572 | | } |
573 | | |
574 | | static int frame_copy_video(AVFrame *dst, const AVFrame *src) |
575 | | { |
576 | | const uint8_t *src_data[4]; |
577 | | int i, planes; |
578 | | |
579 | | if (dst->width < src->width || |
580 | | dst->height < src->height) |
581 | | return AVERROR(EINVAL); |
582 | | |
583 | | planes = av_pix_fmt_count_planes(dst->format); |
584 | | for (i = 0; i < planes; i++) |
585 | | if (!dst->data[i] || !src->data[i]) |
586 | | return AVERROR(EINVAL); |
587 | | |
588 | | memcpy(src_data, src->data, sizeof(src_data)); |
589 | | av_image_copy(dst->data, dst->linesize, |
590 | | src_data, src->linesize, |
591 | | dst->format, src->width, src->height); |
592 | | |
593 | | return 0; |
594 | | } |
595 | | |
596 | | static int frame_copy_audio(AVFrame *dst, const AVFrame *src) |
597 | | { |
598 | | int planar = av_sample_fmt_is_planar(dst->format); |
599 | | int channels = dst->channels; |
600 | | int planes = planar ? channels : 1; |
601 | | int i; |
602 | | |
603 | | if (dst->nb_samples != src->nb_samples || |
604 | | dst->channels != src->channels || |
605 | | dst->channel_layout != src->channel_layout) |
606 | | return AVERROR(EINVAL); |
607 | | |
608 | | CHECK_CHANNELS_CONSISTENCY(src); |
609 | | |
610 | | for (i = 0; i < planes; i++) |
611 | | if (!dst->extended_data[i] || !src->extended_data[i]) |
612 | | return AVERROR(EINVAL); |
613 | | |
614 | | av_samples_copy(dst->extended_data, src->extended_data, 0, 0, |
615 | | dst->nb_samples, channels, dst->format); |
616 | | |
617 | | return 0; |
618 | | } |
619 | | |
620 | | int av_frame_copy(AVFrame *dst, const AVFrame *src) |
621 | | { |
622 | | if (dst->format != src->format || dst->format < 0) |
623 | | return AVERROR(EINVAL); |
624 | | |
625 | | if (dst->width > 0 && dst->height > 0) |
626 | | return frame_copy_video(dst, src); |
627 | | else if (dst->nb_samples > 0 && dst->channel_layout) |
628 | | return frame_copy_audio(dst, src); |
629 | | |
630 | | return AVERROR(EINVAL); |
631 | | } |
632 | | |
633 | | void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) |
634 | | { |
635 | | int i; |
636 | | |
637 | | for (i = 0; i < frame->nb_side_data; i++) { |
638 | | AVFrameSideData *sd = frame->side_data[i]; |
639 | | if (sd->type == type) { |
640 | | free_side_data(&frame->side_data[i]); |
641 | | frame->side_data[i] = frame->side_data[frame->nb_side_data - 1]; |
642 | | frame->nb_side_data--; |
643 | | } |
644 | | } |
645 | | } |
646 | | |
647 | | const char *av_frame_side_data_name(enum AVFrameSideDataType type) |
648 | | { |
649 | | switch(type) { |
650 | | case AV_FRAME_DATA_PANSCAN: return "AVPanScan"; |
651 | | case AV_FRAME_DATA_A53_CC: return "ATSC A53 Part 4 Closed Captions"; |
652 | | case AV_FRAME_DATA_STEREO3D: return "Stereoscopic 3d metadata"; |
653 | | case AV_FRAME_DATA_MATRIXENCODING: return "AVMatrixEncoding"; |
654 | | case AV_FRAME_DATA_DOWNMIX_INFO: return "Metadata relevant to a downmix procedure"; |
655 | | case AV_FRAME_DATA_REPLAYGAIN: return "AVReplayGain"; |
656 | | case AV_FRAME_DATA_DISPLAYMATRIX: return "3x3 displaymatrix"; |
657 | | case AV_FRAME_DATA_MOTION_VECTORS: return "Motion vectors"; |
658 | | } |
659 | | return NULL; |
660 | | } |
661 | | #endif |