blob: 8811dcdcfec401bdc66a51eb176428fdf82baa91
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 "dict.h" |
24 | #include "frame.h" |
25 | #include "imgutils.h" |
26 | #include "mem.h" |
27 | #include "samplefmt.h" |
28 | |
29 | |
30 | static AVFrameSideData *frame_new_side_data(AVFrame *frame, |
31 | enum AVFrameSideDataType type, |
32 | AVBufferRef *buf); |
33 | |
34 | MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) |
35 | MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration) |
36 | MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_pos) |
37 | MAKE_ACCESSORS(AVFrame, frame, int64_t, channel_layout) |
38 | MAKE_ACCESSORS(AVFrame, frame, int, channels) |
39 | MAKE_ACCESSORS(AVFrame, frame, int, sample_rate) |
40 | MAKE_ACCESSORS(AVFrame, frame, AVDictionary *, metadata) |
41 | MAKE_ACCESSORS(AVFrame, frame, int, decode_error_flags) |
42 | MAKE_ACCESSORS(AVFrame, frame, int, pkt_size) |
43 | MAKE_ACCESSORS(AVFrame, frame, enum AVColorSpace, colorspace) |
44 | MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range) |
45 | |
46 | #define CHECK_CHANNELS_CONSISTENCY(frame) \ |
47 | av_assert2(!(frame)->channel_layout || \ |
48 | (frame)->channels == \ |
49 | av_get_channel_layout_nb_channels((frame)->channel_layout)) |
50 | |
51 | AVDictionary **avpriv_frame_get_metadatap(AVFrame *frame) {return &frame->metadata;}; |
52 | |
53 | #if FF_API_FRAME_QP |
54 | int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int qp_type) |
55 | { |
56 | av_buffer_unref(&f->qp_table_buf); |
57 | |
58 | f->qp_table_buf = buf; |
59 | |
60 | FF_DISABLE_DEPRECATION_WARNINGS |
61 | f->qscale_table = buf->data; |
62 | f->qstride = stride; |
63 | f->qscale_type = qp_type; |
64 | FF_ENABLE_DEPRECATION_WARNINGS |
65 | |
66 | return 0; |
67 | } |
68 | |
69 | int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type) |
70 | { |
71 | FF_DISABLE_DEPRECATION_WARNINGS |
72 | *stride = f->qstride; |
73 | *type = f->qscale_type; |
74 | FF_ENABLE_DEPRECATION_WARNINGS |
75 | |
76 | if (!f->qp_table_buf) |
77 | return NULL; |
78 | |
79 | return f->qp_table_buf->data; |
80 | } |
81 | #endif |
82 | |
83 | const char *av_get_colorspace_name(enum AVColorSpace val) |
84 | { |
85 | static const char * const name[] = { |
86 | [AVCOL_SPC_RGB] = "GBR", |
87 | [AVCOL_SPC_BT709] = "bt709", |
88 | [AVCOL_SPC_FCC] = "fcc", |
89 | [AVCOL_SPC_BT470BG] = "bt470bg", |
90 | [AVCOL_SPC_SMPTE170M] = "smpte170m", |
91 | [AVCOL_SPC_SMPTE240M] = "smpte240m", |
92 | [AVCOL_SPC_YCOCG] = "YCgCo", |
93 | }; |
94 | if ((unsigned)val >= FF_ARRAY_ELEMS(name)) |
95 | return NULL; |
96 | return name[val]; |
97 | } |
98 | |
99 | static void get_frame_defaults(AVFrame *frame) |
100 | { |
101 | if (frame->extended_data != frame->data) |
102 | av_freep(&frame->extended_data); |
103 | |
104 | memset(frame, 0, sizeof(*frame)); |
105 | |
106 | frame->pts = |
107 | frame->pkt_dts = AV_NOPTS_VALUE; |
108 | #if FF_API_PKT_PTS |
109 | FF_DISABLE_DEPRECATION_WARNINGS |
110 | frame->pkt_pts = AV_NOPTS_VALUE; |
111 | FF_ENABLE_DEPRECATION_WARNINGS |
112 | #endif |
113 | frame->best_effort_timestamp = AV_NOPTS_VALUE; |
114 | frame->pkt_duration = 0; |
115 | frame->pkt_pos = -1; |
116 | frame->pkt_size = -1; |
117 | frame->key_frame = 1; |
118 | frame->sample_aspect_ratio = (AVRational){ 0, 1 }; |
119 | frame->format = -1; /* unknown */ |
120 | frame->extended_data = frame->data; |
121 | frame->color_primaries = AVCOL_PRI_UNSPECIFIED; |
122 | frame->color_trc = AVCOL_TRC_UNSPECIFIED; |
123 | frame->colorspace = AVCOL_SPC_UNSPECIFIED; |
124 | frame->color_range = AVCOL_RANGE_UNSPECIFIED; |
125 | frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED; |
126 | frame->flags = 0; |
127 | } |
128 | |
129 | static void free_side_data(AVFrameSideData **ptr_sd) |
130 | { |
131 | AVFrameSideData *sd = *ptr_sd; |
132 | |
133 | av_buffer_unref(&sd->buf); |
134 | av_dict_free(&sd->metadata); |
135 | av_freep(ptr_sd); |
136 | } |
137 | |
138 | static void wipe_side_data(AVFrame *frame) |
139 | { |
140 | int i; |
141 | |
142 | for (i = 0; i < frame->nb_side_data; i++) { |
143 | free_side_data(&frame->side_data[i]); |
144 | } |
145 | frame->nb_side_data = 0; |
146 | |
147 | av_freep(&frame->side_data); |
148 | } |
149 | |
150 | AVFrame *av_frame_alloc(void) |
151 | { |
152 | AVFrame *frame = av_mallocz(sizeof(*frame)); |
153 | |
154 | if (!frame) |
155 | return NULL; |
156 | |
157 | frame->extended_data = NULL; |
158 | get_frame_defaults(frame); |
159 | |
160 | return frame; |
161 | } |
162 | |
163 | void av_frame_free(AVFrame **frame) |
164 | { |
165 | if (!frame || !*frame) |
166 | return; |
167 | |
168 | av_frame_unref(*frame); |
169 | av_freep(frame); |
170 | } |
171 | |
172 | static int get_video_buffer(AVFrame *frame, int align) |
173 | { |
174 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); |
175 | int ret, i; |
176 | |
177 | if (!desc) |
178 | return AVERROR(EINVAL); |
179 | |
180 | if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0) |
181 | return ret; |
182 | |
183 | if (!frame->linesize[0]) { |
184 | for(i=1; i<=align; i+=i) { |
185 | ret = av_image_fill_linesizes(frame->linesize, frame->format, |
186 | FFALIGN(frame->width, i)); |
187 | if (ret < 0) |
188 | return ret; |
189 | if (!(frame->linesize[0] & (align-1))) |
190 | break; |
191 | } |
192 | |
193 | for (i = 0; i < 4 && frame->linesize[i]; i++) |
194 | frame->linesize[i] = FFALIGN(frame->linesize[i], align); |
195 | } |
196 | |
197 | for (i = 0; i < 4 && frame->linesize[i]; i++) { |
198 | int h = FFALIGN(frame->height, 32); |
199 | if (i == 1 || i == 2) |
200 | h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); |
201 | |
202 | frame->buf[i] = av_buffer_alloc(frame->linesize[i] * h + 16 + 16/*STRIDE_ALIGN*/ - 1); |
203 | if (!frame->buf[i]) |
204 | goto fail; |
205 | |
206 | frame->data[i] = frame->buf[i]->data; |
207 | } |
208 | if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
209 | av_buffer_unref(&frame->buf[1]); |
210 | frame->buf[1] = av_buffer_alloc(AVPALETTE_SIZE); |
211 | if (!frame->buf[1]) |
212 | goto fail; |
213 | frame->data[1] = frame->buf[1]->data; |
214 | } |
215 | |
216 | frame->extended_data = frame->data; |
217 | |
218 | return 0; |
219 | fail: |
220 | av_frame_unref(frame); |
221 | return AVERROR(ENOMEM); |
222 | } |
223 | |
224 | static int get_audio_buffer(AVFrame *frame, int align) |
225 | { |
226 | int channels; |
227 | int planar = av_sample_fmt_is_planar(frame->format); |
228 | int planes; |
229 | int ret, i; |
230 | |
231 | if (!frame->channels) |
232 | frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout); |
233 | |
234 | channels = frame->channels; |
235 | planes = planar ? channels : 1; |
236 | |
237 | CHECK_CHANNELS_CONSISTENCY(frame); |
238 | if (!frame->linesize[0]) { |
239 | ret = av_samples_get_buffer_size(&frame->linesize[0], channels, |
240 | frame->nb_samples, frame->format, |
241 | align); |
242 | if (ret < 0) |
243 | return ret; |
244 | } |
245 | |
246 | if (planes > AV_NUM_DATA_POINTERS) { |
247 | frame->extended_data = av_mallocz_array(planes, |
248 | sizeof(*frame->extended_data)); |
249 | frame->extended_buf = av_mallocz_array((planes - AV_NUM_DATA_POINTERS), |
250 | sizeof(*frame->extended_buf)); |
251 | if (!frame->extended_data || !frame->extended_buf) { |
252 | av_freep(&frame->extended_data); |
253 | av_freep(&frame->extended_buf); |
254 | return AVERROR(ENOMEM); |
255 | } |
256 | frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; |
257 | } else |
258 | frame->extended_data = frame->data; |
259 | |
260 | for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { |
261 | frame->buf[i] = av_buffer_alloc(frame->linesize[0]); |
262 | if (!frame->buf[i]) { |
263 | av_frame_unref(frame); |
264 | return AVERROR(ENOMEM); |
265 | } |
266 | frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; |
267 | } |
268 | for (i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) { |
269 | frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]); |
270 | if (!frame->extended_buf[i]) { |
271 | av_frame_unref(frame); |
272 | return AVERROR(ENOMEM); |
273 | } |
274 | frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; |
275 | } |
276 | return 0; |
277 | |
278 | } |
279 | |
280 | int av_frame_get_buffer(AVFrame *frame, int align) |
281 | { |
282 | if (frame->format < 0) |
283 | return AVERROR(EINVAL); |
284 | |
285 | if (frame->width > 0 && frame->height > 0) |
286 | return get_video_buffer(frame, align); |
287 | else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0)) |
288 | return get_audio_buffer(frame, align); |
289 | |
290 | return AVERROR(EINVAL); |
291 | } |
292 | |
293 | static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) |
294 | { |
295 | int i; |
296 | |
297 | dst->key_frame = src->key_frame; |
298 | dst->pict_type = src->pict_type; |
299 | dst->sample_aspect_ratio = src->sample_aspect_ratio; |
300 | dst->pts = src->pts; |
301 | dst->repeat_pict = src->repeat_pict; |
302 | dst->interlaced_frame = src->interlaced_frame; |
303 | dst->top_field_first = src->top_field_first; |
304 | dst->palette_has_changed = src->palette_has_changed; |
305 | dst->sample_rate = src->sample_rate; |
306 | dst->opaque = src->opaque; |
307 | #if FF_API_PKT_PTS |
308 | FF_DISABLE_DEPRECATION_WARNINGS |
309 | dst->pkt_pts = src->pkt_pts; |
310 | FF_ENABLE_DEPRECATION_WARNINGS |
311 | #endif |
312 | dst->pkt_dts = src->pkt_dts; |
313 | dst->pkt_pos = src->pkt_pos; |
314 | dst->pkt_size = src->pkt_size; |
315 | dst->pkt_duration = src->pkt_duration; |
316 | dst->reordered_opaque = src->reordered_opaque; |
317 | dst->quality = src->quality; |
318 | dst->best_effort_timestamp = src->best_effort_timestamp; |
319 | dst->coded_picture_number = src->coded_picture_number; |
320 | dst->display_picture_number = src->display_picture_number; |
321 | dst->flags = src->flags; |
322 | dst->decode_error_flags = src->decode_error_flags; |
323 | dst->color_primaries = src->color_primaries; |
324 | dst->color_trc = src->color_trc; |
325 | dst->colorspace = src->colorspace; |
326 | dst->color_range = src->color_range; |
327 | dst->chroma_location = src->chroma_location; |
328 | |
329 | av_dict_copy(&dst->metadata, src->metadata, 0); |
330 | |
331 | #if FF_API_ERROR_FRAME |
332 | FF_DISABLE_DEPRECATION_WARNINGS |
333 | memcpy(dst->error, src->error, sizeof(dst->error)); |
334 | FF_ENABLE_DEPRECATION_WARNINGS |
335 | #endif |
336 | |
337 | for (i = 0; i < src->nb_side_data; i++) { |
338 | const AVFrameSideData *sd_src = src->side_data[i]; |
339 | AVFrameSideData *sd_dst; |
340 | if ( sd_src->type == AV_FRAME_DATA_PANSCAN |
341 | && (src->width != dst->width || src->height != dst->height)) |
342 | continue; |
343 | if (force_copy) { |
344 | sd_dst = av_frame_new_side_data(dst, sd_src->type, |
345 | sd_src->size); |
346 | if (!sd_dst) { |
347 | wipe_side_data(dst); |
348 | return AVERROR(ENOMEM); |
349 | } |
350 | memcpy(sd_dst->data, sd_src->data, sd_src->size); |
351 | } else { |
352 | sd_dst = frame_new_side_data(dst, sd_src->type, av_buffer_ref(sd_src->buf)); |
353 | if (!sd_dst) { |
354 | wipe_side_data(dst); |
355 | return AVERROR(ENOMEM); |
356 | } |
357 | } |
358 | av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0); |
359 | } |
360 | |
361 | #if FF_API_FRAME_QP |
362 | FF_DISABLE_DEPRECATION_WARNINGS |
363 | dst->qscale_table = NULL; |
364 | dst->qstride = 0; |
365 | dst->qscale_type = 0; |
366 | av_buffer_unref(&dst->qp_table_buf); |
367 | if (src->qp_table_buf) { |
368 | dst->qp_table_buf = av_buffer_ref(src->qp_table_buf); |
369 | if (dst->qp_table_buf) { |
370 | dst->qscale_table = dst->qp_table_buf->data; |
371 | dst->qstride = src->qstride; |
372 | dst->qscale_type = src->qscale_type; |
373 | } |
374 | } |
375 | FF_ENABLE_DEPRECATION_WARNINGS |
376 | #endif |
377 | |
378 | av_buffer_unref(&dst->opaque_ref); |
379 | if (src->opaque_ref) { |
380 | dst->opaque_ref = av_buffer_ref(src->opaque_ref); |
381 | if (!dst->opaque_ref) |
382 | return AVERROR(ENOMEM); |
383 | } |
384 | |
385 | return 0; |
386 | } |
387 | |
388 | int av_frame_ref(AVFrame *dst, const AVFrame *src) |
389 | { |
390 | int i, ret = 0; |
391 | |
392 | av_assert1(dst->width == 0 && dst->height == 0); |
393 | av_assert1(dst->channels == 0); |
394 | |
395 | dst->format = src->format; |
396 | dst->width = src->width; |
397 | dst->height = src->height; |
398 | dst->channels = src->channels; |
399 | dst->channel_layout = src->channel_layout; |
400 | dst->nb_samples = src->nb_samples; |
401 | |
402 | ret = frame_copy_props(dst, src, 0); |
403 | if (ret < 0) |
404 | return ret; |
405 | |
406 | /* duplicate the frame data if it's not refcounted */ |
407 | if (!src->buf[0]) { |
408 | ret = av_frame_get_buffer(dst, 32); |
409 | if (ret < 0) |
410 | return ret; |
411 | |
412 | ret = av_frame_copy(dst, src); |
413 | if (ret < 0) |
414 | av_frame_unref(dst); |
415 | |
416 | return ret; |
417 | } |
418 | |
419 | /* ref the buffers */ |
420 | for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { |
421 | if (!src->buf[i]) |
422 | continue; |
423 | dst->buf[i] = av_buffer_ref(src->buf[i]); |
424 | if (!dst->buf[i]) { |
425 | ret = AVERROR(ENOMEM); |
426 | goto fail; |
427 | } |
428 | } |
429 | |
430 | if (src->extended_buf) { |
431 | dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf), |
432 | src->nb_extended_buf); |
433 | if (!dst->extended_buf) { |
434 | ret = AVERROR(ENOMEM); |
435 | goto fail; |
436 | } |
437 | dst->nb_extended_buf = src->nb_extended_buf; |
438 | |
439 | for (i = 0; i < src->nb_extended_buf; i++) { |
440 | dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]); |
441 | if (!dst->extended_buf[i]) { |
442 | ret = AVERROR(ENOMEM); |
443 | goto fail; |
444 | } |
445 | } |
446 | } |
447 | |
448 | if (src->hw_frames_ctx) { |
449 | dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx); |
450 | if (!dst->hw_frames_ctx) { |
451 | ret = AVERROR(ENOMEM); |
452 | goto fail; |
453 | } |
454 | } |
455 | |
456 | /* duplicate extended data */ |
457 | if (src->extended_data != src->data) { |
458 | int ch = src->channels; |
459 | |
460 | if (!ch) { |
461 | ret = AVERROR(EINVAL); |
462 | goto fail; |
463 | } |
464 | CHECK_CHANNELS_CONSISTENCY(src); |
465 | |
466 | dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch); |
467 | if (!dst->extended_data) { |
468 | ret = AVERROR(ENOMEM); |
469 | goto fail; |
470 | } |
471 | memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch); |
472 | } else |
473 | dst->extended_data = dst->data; |
474 | |
475 | memcpy(dst->data, src->data, sizeof(src->data)); |
476 | memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); |
477 | |
478 | return 0; |
479 | |
480 | fail: |
481 | av_frame_unref(dst); |
482 | return ret; |
483 | } |
484 | |
485 | AVFrame *av_frame_clone(const AVFrame *src) |
486 | { |
487 | AVFrame *ret = av_frame_alloc(); |
488 | |
489 | if (!ret) |
490 | return NULL; |
491 | |
492 | if (av_frame_ref(ret, src) < 0) |
493 | av_frame_free(&ret); |
494 | |
495 | return ret; |
496 | } |
497 | |
498 | void av_frame_unref(AVFrame *frame) |
499 | { |
500 | int i; |
501 | |
502 | if (!frame) |
503 | return; |
504 | |
505 | wipe_side_data(frame); |
506 | |
507 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) |
508 | av_buffer_unref(&frame->buf[i]); |
509 | for (i = 0; i < frame->nb_extended_buf; i++) |
510 | av_buffer_unref(&frame->extended_buf[i]); |
511 | av_freep(&frame->extended_buf); |
512 | av_dict_free(&frame->metadata); |
513 | #if FF_API_FRAME_QP |
514 | av_buffer_unref(&frame->qp_table_buf); |
515 | #endif |
516 | |
517 | av_buffer_unref(&frame->hw_frames_ctx); |
518 | |
519 | av_buffer_unref(&frame->opaque_ref); |
520 | |
521 | get_frame_defaults(frame); |
522 | } |
523 | |
524 | void av_frame_move_ref(AVFrame *dst, AVFrame *src) |
525 | { |
526 | av_assert1(dst->width == 0 && dst->height == 0); |
527 | av_assert1(dst->channels == 0); |
528 | |
529 | *dst = *src; |
530 | if (src->extended_data == src->data) |
531 | dst->extended_data = dst->data; |
532 | memset(src, 0, sizeof(*src)); |
533 | get_frame_defaults(src); |
534 | } |
535 | |
536 | int av_frame_is_writable(AVFrame *frame) |
537 | { |
538 | int i, ret = 1; |
539 | |
540 | /* assume non-refcounted frames are not writable */ |
541 | if (!frame->buf[0]) |
542 | return 0; |
543 | |
544 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) |
545 | if (frame->buf[i]) |
546 | ret &= !!av_buffer_is_writable(frame->buf[i]); |
547 | for (i = 0; i < frame->nb_extended_buf; i++) |
548 | ret &= !!av_buffer_is_writable(frame->extended_buf[i]); |
549 | |
550 | return ret; |
551 | } |
552 | |
553 | int av_frame_make_writable(AVFrame *frame) |
554 | { |
555 | AVFrame tmp; |
556 | int ret; |
557 | |
558 | if (!frame->buf[0]) |
559 | return AVERROR(EINVAL); |
560 | |
561 | if (av_frame_is_writable(frame)) |
562 | return 0; |
563 | |
564 | memset(&tmp, 0, sizeof(tmp)); |
565 | tmp.format = frame->format; |
566 | tmp.width = frame->width; |
567 | tmp.height = frame->height; |
568 | tmp.channels = frame->channels; |
569 | tmp.channel_layout = frame->channel_layout; |
570 | tmp.nb_samples = frame->nb_samples; |
571 | ret = av_frame_get_buffer(&tmp, 32); |
572 | if (ret < 0) |
573 | return ret; |
574 | |
575 | ret = av_frame_copy(&tmp, frame); |
576 | if (ret < 0) { |
577 | av_frame_unref(&tmp); |
578 | return ret; |
579 | } |
580 | |
581 | ret = av_frame_copy_props(&tmp, frame); |
582 | if (ret < 0) { |
583 | av_frame_unref(&tmp); |
584 | return ret; |
585 | } |
586 | |
587 | av_frame_unref(frame); |
588 | |
589 | *frame = tmp; |
590 | if (tmp.data == tmp.extended_data) |
591 | frame->extended_data = frame->data; |
592 | |
593 | return 0; |
594 | } |
595 | |
596 | int av_frame_copy_props(AVFrame *dst, const AVFrame *src) |
597 | { |
598 | return frame_copy_props(dst, src, 1); |
599 | } |
600 | |
601 | AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) |
602 | { |
603 | uint8_t *data; |
604 | int planes, i; |
605 | |
606 | if (frame->nb_samples) { |
607 | int channels = frame->channels; |
608 | if (!channels) |
609 | return NULL; |
610 | CHECK_CHANNELS_CONSISTENCY(frame); |
611 | planes = av_sample_fmt_is_planar(frame->format) ? channels : 1; |
612 | } else |
613 | planes = 4; |
614 | |
615 | if (plane < 0 || plane >= planes || !frame->extended_data[plane]) |
616 | return NULL; |
617 | data = frame->extended_data[plane]; |
618 | |
619 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) { |
620 | AVBufferRef *buf = frame->buf[i]; |
621 | if (data >= buf->data && data < buf->data + buf->size) |
622 | return buf; |
623 | } |
624 | for (i = 0; i < frame->nb_extended_buf; i++) { |
625 | AVBufferRef *buf = frame->extended_buf[i]; |
626 | if (data >= buf->data && data < buf->data + buf->size) |
627 | return buf; |
628 | } |
629 | return NULL; |
630 | } |
631 | |
632 | static AVFrameSideData *frame_new_side_data(AVFrame *frame, |
633 | enum AVFrameSideDataType type, |
634 | AVBufferRef *buf) |
635 | { |
636 | AVFrameSideData *ret, **tmp; |
637 | |
638 | if (!buf) |
639 | return NULL; |
640 | |
641 | if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1) |
642 | goto fail; |
643 | |
644 | tmp = av_realloc(frame->side_data, |
645 | (frame->nb_side_data + 1) * sizeof(*frame->side_data)); |
646 | if (!tmp) |
647 | goto fail; |
648 | frame->side_data = tmp; |
649 | |
650 | ret = av_mallocz(sizeof(*ret)); |
651 | if (!ret) |
652 | goto fail; |
653 | |
654 | ret->buf = buf; |
655 | ret->data = ret->buf->data; |
656 | ret->size = buf->size; |
657 | ret->type = type; |
658 | |
659 | frame->side_data[frame->nb_side_data++] = ret; |
660 | |
661 | return ret; |
662 | fail: |
663 | av_buffer_unref(&buf); |
664 | return NULL; |
665 | } |
666 | |
667 | AVFrameSideData *av_frame_new_side_data(AVFrame *frame, |
668 | enum AVFrameSideDataType type, |
669 | int size) |
670 | { |
671 | |
672 | return frame_new_side_data(frame, type, av_buffer_alloc(size)); |
673 | } |
674 | |
675 | AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, |
676 | enum AVFrameSideDataType type) |
677 | { |
678 | int i; |
679 | |
680 | for (i = 0; i < frame->nb_side_data; i++) { |
681 | if (frame->side_data[i]->type == type) |
682 | return frame->side_data[i]; |
683 | } |
684 | return NULL; |
685 | } |
686 | |
687 | static int frame_copy_video(AVFrame *dst, const AVFrame *src) |
688 | { |
689 | const uint8_t *src_data[4]; |
690 | int i, planes; |
691 | |
692 | if (dst->width < src->width || |
693 | dst->height < src->height) |
694 | return AVERROR(EINVAL); |
695 | |
696 | planes = av_pix_fmt_count_planes(dst->format); |
697 | for (i = 0; i < planes; i++) |
698 | if (!dst->data[i] || !src->data[i]) |
699 | return AVERROR(EINVAL); |
700 | |
701 | memcpy(src_data, src->data, sizeof(src_data)); |
702 | av_image_copy(dst->data, dst->linesize, |
703 | src_data, src->linesize, |
704 | dst->format, src->width, src->height); |
705 | |
706 | return 0; |
707 | } |
708 | |
709 | static int frame_copy_audio(AVFrame *dst, const AVFrame *src) |
710 | { |
711 | int planar = av_sample_fmt_is_planar(dst->format); |
712 | int channels = dst->channels; |
713 | int planes = planar ? channels : 1; |
714 | int i; |
715 | |
716 | if (dst->nb_samples != src->nb_samples || |
717 | dst->channels != src->channels || |
718 | dst->channel_layout != src->channel_layout) |
719 | return AVERROR(EINVAL); |
720 | |
721 | CHECK_CHANNELS_CONSISTENCY(src); |
722 | |
723 | for (i = 0; i < planes; i++) |
724 | if (!dst->extended_data[i] || !src->extended_data[i]) |
725 | return AVERROR(EINVAL); |
726 | |
727 | av_samples_copy(dst->extended_data, src->extended_data, 0, 0, |
728 | dst->nb_samples, channels, dst->format); |
729 | |
730 | return 0; |
731 | } |
732 | |
733 | int av_frame_copy(AVFrame *dst, const AVFrame *src) |
734 | { |
735 | if (dst->format != src->format || dst->format < 0) |
736 | return AVERROR(EINVAL); |
737 | |
738 | if (dst->width > 0 && dst->height > 0) |
739 | return frame_copy_video(dst, src); |
740 | else if (dst->nb_samples > 0 && dst->channels > 0) |
741 | return frame_copy_audio(dst, src); |
742 | |
743 | return AVERROR(EINVAL); |
744 | } |
745 | |
746 | void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) |
747 | { |
748 | int i; |
749 | |
750 | for (i = 0; i < frame->nb_side_data; i++) { |
751 | AVFrameSideData *sd = frame->side_data[i]; |
752 | if (sd->type == type) { |
753 | free_side_data(&frame->side_data[i]); |
754 | frame->side_data[i] = frame->side_data[frame->nb_side_data - 1]; |
755 | frame->nb_side_data--; |
756 | } |
757 | } |
758 | } |
759 | |
760 | const char *av_frame_side_data_name(enum AVFrameSideDataType type) |
761 | { |
762 | switch(type) { |
763 | case AV_FRAME_DATA_PANSCAN: return "AVPanScan"; |
764 | case AV_FRAME_DATA_A53_CC: return "ATSC A53 Part 4 Closed Captions"; |
765 | case AV_FRAME_DATA_STEREO3D: return "Stereoscopic 3d metadata"; |
766 | case AV_FRAME_DATA_MATRIXENCODING: return "AVMatrixEncoding"; |
767 | case AV_FRAME_DATA_DOWNMIX_INFO: return "Metadata relevant to a downmix procedure"; |
768 | case AV_FRAME_DATA_REPLAYGAIN: return "AVReplayGain"; |
769 | case AV_FRAME_DATA_DISPLAYMATRIX: return "3x3 displaymatrix"; |
770 | case AV_FRAME_DATA_AFD: return "Active format description"; |
771 | case AV_FRAME_DATA_MOTION_VECTORS: return "Motion vectors"; |
772 | case AV_FRAME_DATA_SKIP_SAMPLES: return "Skip samples"; |
773 | case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: return "Audio service type"; |
774 | case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata"; |
775 | case AV_FRAME_DATA_GOP_TIMECODE: return "GOP timecode"; |
776 | } |
777 | return NULL; |
778 | } |
779 |