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