Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 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 *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->colorspace = AVCOL_SPC_UNSPECIFIED; |
||
107 | frame->extended_data = frame->data; |
||
108 | } |
||
109 | |||
110 | AVFrame *av_frame_alloc(void) |
||
111 | { |
||
112 | AVFrame *frame = av_mallocz(sizeof(*frame)); |
||
113 | |||
114 | if (!frame) |
||
115 | return NULL; |
||
116 | |||
117 | frame->extended_data = NULL; |
||
118 | get_frame_defaults(frame); |
||
119 | |||
120 | return frame; |
||
121 | } |
||
122 | |||
123 | void av_frame_free(AVFrame **frame) |
||
124 | { |
||
125 | if (!frame || !*frame) |
||
126 | return; |
||
127 | |||
128 | av_frame_unref(*frame); |
||
129 | av_freep(frame); |
||
130 | } |
||
131 | |||
132 | static int get_video_buffer(AVFrame *frame, int align) |
||
133 | { |
||
134 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); |
||
135 | int ret, i; |
||
136 | |||
137 | if (!desc) |
||
138 | return AVERROR(EINVAL); |
||
139 | |||
140 | if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0) |
||
141 | return ret; |
||
142 | |||
143 | if (!frame->linesize[0]) { |
||
144 | for(i=1; i<=align; i+=i) { |
||
145 | ret = av_image_fill_linesizes(frame->linesize, frame->format, |
||
146 | FFALIGN(frame->width, i)); |
||
147 | if (ret < 0) |
||
148 | return ret; |
||
149 | if (!(frame->linesize[0] & (align-1))) |
||
150 | break; |
||
151 | } |
||
152 | |||
153 | for (i = 0; i < 4 && frame->linesize[i]; i++) |
||
154 | frame->linesize[i] = FFALIGN(frame->linesize[i], align); |
||
155 | } |
||
156 | |||
157 | for (i = 0; i < 4 && frame->linesize[i]; i++) { |
||
158 | int h = FFALIGN(frame->height, 32); |
||
159 | if (i == 1 || i == 2) |
||
160 | h = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); |
||
161 | |||
162 | frame->buf[i] = av_buffer_alloc(frame->linesize[i] * h + 16); |
||
163 | if (!frame->buf[i]) |
||
164 | goto fail; |
||
165 | |||
166 | frame->data[i] = frame->buf[i]->data; |
||
167 | } |
||
168 | if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
||
169 | av_buffer_unref(&frame->buf[1]); |
||
170 | frame->buf[1] = av_buffer_alloc(1024); |
||
171 | if (!frame->buf[1]) |
||
172 | goto fail; |
||
173 | frame->data[1] = frame->buf[1]->data; |
||
174 | } |
||
175 | |||
176 | frame->extended_data = frame->data; |
||
177 | |||
178 | return 0; |
||
179 | fail: |
||
180 | av_frame_unref(frame); |
||
181 | return AVERROR(ENOMEM); |
||
182 | } |
||
183 | |||
184 | static int get_audio_buffer(AVFrame *frame, int align) |
||
185 | { |
||
186 | int channels = frame->channels; |
||
187 | int planar = av_sample_fmt_is_planar(frame->format); |
||
188 | int planes = planar ? channels : 1; |
||
189 | int ret, i; |
||
190 | |||
191 | CHECK_CHANNELS_CONSISTENCY(frame); |
||
192 | if (!frame->linesize[0]) { |
||
193 | ret = av_samples_get_buffer_size(&frame->linesize[0], channels, |
||
194 | frame->nb_samples, frame->format, |
||
195 | align); |
||
196 | if (ret < 0) |
||
197 | return ret; |
||
198 | } |
||
199 | |||
200 | if (planes > AV_NUM_DATA_POINTERS) { |
||
201 | frame->extended_data = av_mallocz(planes * |
||
202 | sizeof(*frame->extended_data)); |
||
203 | frame->extended_buf = av_mallocz((planes - AV_NUM_DATA_POINTERS) * |
||
204 | sizeof(*frame->extended_buf)); |
||
205 | if (!frame->extended_data || !frame->extended_buf) { |
||
206 | av_freep(&frame->extended_data); |
||
207 | av_freep(&frame->extended_buf); |
||
208 | return AVERROR(ENOMEM); |
||
209 | } |
||
210 | frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; |
||
211 | } else |
||
212 | frame->extended_data = frame->data; |
||
213 | |||
214 | for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { |
||
215 | frame->buf[i] = av_buffer_alloc(frame->linesize[0]); |
||
216 | if (!frame->buf[i]) { |
||
217 | av_frame_unref(frame); |
||
218 | return AVERROR(ENOMEM); |
||
219 | } |
||
220 | frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; |
||
221 | } |
||
222 | for (i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) { |
||
223 | frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]); |
||
224 | if (!frame->extended_buf[i]) { |
||
225 | av_frame_unref(frame); |
||
226 | return AVERROR(ENOMEM); |
||
227 | } |
||
228 | frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; |
||
229 | } |
||
230 | return 0; |
||
231 | |||
232 | } |
||
233 | |||
234 | int av_frame_get_buffer(AVFrame *frame, int align) |
||
235 | { |
||
236 | if (frame->format < 0) |
||
237 | return AVERROR(EINVAL); |
||
238 | |||
239 | if (frame->width > 0 && frame->height > 0) |
||
240 | return get_video_buffer(frame, align); |
||
241 | else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0)) |
||
242 | return get_audio_buffer(frame, align); |
||
243 | |||
244 | return AVERROR(EINVAL); |
||
245 | } |
||
246 | |||
247 | int av_frame_ref(AVFrame *dst, AVFrame *src) |
||
248 | { |
||
249 | int i, ret = 0; |
||
250 | |||
251 | dst->format = src->format; |
||
252 | dst->width = src->width; |
||
253 | dst->height = src->height; |
||
254 | dst->channels = src->channels; |
||
255 | dst->channel_layout = src->channel_layout; |
||
256 | dst->nb_samples = src->nb_samples; |
||
257 | |||
258 | ret = av_frame_copy_props(dst, src); |
||
259 | if (ret < 0) |
||
260 | return ret; |
||
261 | |||
262 | /* duplicate the frame data if it's not refcounted */ |
||
263 | if (!src->buf[0]) { |
||
264 | ret = av_frame_get_buffer(dst, 32); |
||
265 | if (ret < 0) |
||
266 | return ret; |
||
267 | |||
268 | if (src->nb_samples) { |
||
269 | int ch = src->channels; |
||
270 | CHECK_CHANNELS_CONSISTENCY(src); |
||
271 | av_samples_copy(dst->extended_data, src->extended_data, 0, 0, |
||
272 | dst->nb_samples, ch, dst->format); |
||
273 | } else { |
||
274 | av_image_copy(dst->data, dst->linesize, src->data, src->linesize, |
||
275 | dst->format, dst->width, dst->height); |
||
276 | } |
||
277 | return 0; |
||
278 | } |
||
279 | |||
280 | /* ref the buffers */ |
||
281 | for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { |
||
282 | if (!src->buf[i]) |
||
283 | continue; |
||
284 | dst->buf[i] = av_buffer_ref(src->buf[i]); |
||
285 | if (!dst->buf[i]) { |
||
286 | ret = AVERROR(ENOMEM); |
||
287 | goto fail; |
||
288 | } |
||
289 | } |
||
290 | |||
291 | if (src->extended_buf) { |
||
292 | dst->extended_buf = av_mallocz(sizeof(*dst->extended_buf) * |
||
293 | src->nb_extended_buf); |
||
294 | if (!dst->extended_buf) { |
||
295 | ret = AVERROR(ENOMEM); |
||
296 | goto fail; |
||
297 | } |
||
298 | dst->nb_extended_buf = src->nb_extended_buf; |
||
299 | |||
300 | for (i = 0; i < src->nb_extended_buf; i++) { |
||
301 | dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]); |
||
302 | if (!dst->extended_buf[i]) { |
||
303 | ret = AVERROR(ENOMEM); |
||
304 | goto fail; |
||
305 | } |
||
306 | } |
||
307 | } |
||
308 | |||
309 | /* duplicate extended data */ |
||
310 | if (src->extended_data != src->data) { |
||
311 | int ch = src->channels; |
||
312 | |||
313 | if (!ch) { |
||
314 | ret = AVERROR(EINVAL); |
||
315 | goto fail; |
||
316 | } |
||
317 | CHECK_CHANNELS_CONSISTENCY(src); |
||
318 | |||
319 | dst->extended_data = av_malloc(sizeof(*dst->extended_data) * ch); |
||
320 | if (!dst->extended_data) { |
||
321 | ret = AVERROR(ENOMEM); |
||
322 | goto fail; |
||
323 | } |
||
324 | memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch); |
||
325 | } else |
||
326 | dst->extended_data = dst->data; |
||
327 | |||
328 | memcpy(dst->data, src->data, sizeof(src->data)); |
||
329 | memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); |
||
330 | |||
331 | return 0; |
||
332 | |||
333 | fail: |
||
334 | av_frame_unref(dst); |
||
335 | return ret; |
||
336 | } |
||
337 | |||
338 | AVFrame *av_frame_clone(AVFrame *src) |
||
339 | { |
||
340 | AVFrame *ret = av_frame_alloc(); |
||
341 | |||
342 | if (!ret) |
||
343 | return NULL; |
||
344 | |||
345 | if (av_frame_ref(ret, src) < 0) |
||
346 | av_frame_free(&ret); |
||
347 | |||
348 | return ret; |
||
349 | } |
||
350 | |||
351 | void av_frame_unref(AVFrame *frame) |
||
352 | { |
||
353 | int i; |
||
354 | |||
355 | for (i = 0; i < frame->nb_side_data; i++) { |
||
356 | av_freep(&frame->side_data[i]->data); |
||
357 | av_dict_free(&frame->side_data[i]->metadata); |
||
358 | av_freep(&frame->side_data[i]); |
||
359 | } |
||
360 | av_freep(&frame->side_data); |
||
361 | |||
362 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) |
||
363 | av_buffer_unref(&frame->buf[i]); |
||
364 | for (i = 0; i < frame->nb_extended_buf; i++) |
||
365 | av_buffer_unref(&frame->extended_buf[i]); |
||
366 | av_freep(&frame->extended_buf); |
||
367 | av_dict_free(&frame->metadata); |
||
368 | av_buffer_unref(&frame->qp_table_buf); |
||
369 | |||
370 | get_frame_defaults(frame); |
||
371 | } |
||
372 | |||
373 | void av_frame_move_ref(AVFrame *dst, AVFrame *src) |
||
374 | { |
||
375 | *dst = *src; |
||
376 | if (src->extended_data == src->data) |
||
377 | dst->extended_data = dst->data; |
||
378 | memset(src, 0, sizeof(*src)); |
||
379 | get_frame_defaults(src); |
||
380 | } |
||
381 | |||
382 | int av_frame_is_writable(AVFrame *frame) |
||
383 | { |
||
384 | int i, ret = 1; |
||
385 | |||
386 | /* assume non-refcounted frames are not writable */ |
||
387 | if (!frame->buf[0]) |
||
388 | return 0; |
||
389 | |||
390 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) |
||
391 | if (frame->buf[i]) |
||
392 | ret &= !!av_buffer_is_writable(frame->buf[i]); |
||
393 | for (i = 0; i < frame->nb_extended_buf; i++) |
||
394 | ret &= !!av_buffer_is_writable(frame->extended_buf[i]); |
||
395 | |||
396 | return ret; |
||
397 | } |
||
398 | |||
399 | int av_frame_make_writable(AVFrame *frame) |
||
400 | { |
||
401 | AVFrame tmp; |
||
402 | int ret; |
||
403 | |||
404 | if (!frame->buf[0]) |
||
405 | return AVERROR(EINVAL); |
||
406 | |||
407 | if (av_frame_is_writable(frame)) |
||
408 | return 0; |
||
409 | |||
410 | memset(&tmp, 0, sizeof(tmp)); |
||
411 | tmp.format = frame->format; |
||
412 | tmp.width = frame->width; |
||
413 | tmp.height = frame->height; |
||
414 | tmp.channels = frame->channels; |
||
415 | tmp.channel_layout = frame->channel_layout; |
||
416 | tmp.nb_samples = frame->nb_samples; |
||
417 | ret = av_frame_get_buffer(&tmp, 32); |
||
418 | if (ret < 0) |
||
419 | return ret; |
||
420 | |||
421 | if (tmp.nb_samples) { |
||
422 | int ch = tmp.channels; |
||
423 | CHECK_CHANNELS_CONSISTENCY(&tmp); |
||
424 | av_samples_copy(tmp.extended_data, frame->extended_data, 0, 0, |
||
425 | frame->nb_samples, ch, frame->format); |
||
426 | } else { |
||
427 | av_image_copy(tmp.data, tmp.linesize, frame->data, frame->linesize, |
||
428 | frame->format, frame->width, frame->height); |
||
429 | } |
||
430 | |||
431 | ret = av_frame_copy_props(&tmp, frame); |
||
432 | if (ret < 0) { |
||
433 | av_frame_unref(&tmp); |
||
434 | return ret; |
||
435 | } |
||
436 | |||
437 | av_frame_unref(frame); |
||
438 | |||
439 | *frame = tmp; |
||
440 | if (tmp.data == tmp.extended_data) |
||
441 | frame->extended_data = frame->data; |
||
442 | |||
443 | return 0; |
||
444 | } |
||
445 | |||
446 | int av_frame_copy_props(AVFrame *dst, const AVFrame *src) |
||
447 | { |
||
448 | int i; |
||
449 | |||
450 | dst->key_frame = src->key_frame; |
||
451 | dst->pict_type = src->pict_type; |
||
452 | dst->sample_aspect_ratio = src->sample_aspect_ratio; |
||
453 | dst->pts = src->pts; |
||
454 | dst->repeat_pict = src->repeat_pict; |
||
455 | dst->interlaced_frame = src->interlaced_frame; |
||
456 | dst->top_field_first = src->top_field_first; |
||
457 | dst->palette_has_changed = src->palette_has_changed; |
||
458 | dst->sample_rate = src->sample_rate; |
||
459 | dst->opaque = src->opaque; |
||
460 | #if FF_API_AVFRAME_LAVC |
||
461 | dst->type = src->type; |
||
462 | #endif |
||
463 | dst->pkt_pts = src->pkt_pts; |
||
464 | dst->pkt_dts = src->pkt_dts; |
||
465 | dst->pkt_pos = src->pkt_pos; |
||
466 | dst->pkt_size = src->pkt_size; |
||
467 | dst->pkt_duration = src->pkt_duration; |
||
468 | dst->reordered_opaque = src->reordered_opaque; |
||
469 | dst->quality = src->quality; |
||
470 | dst->best_effort_timestamp = src->best_effort_timestamp; |
||
471 | dst->coded_picture_number = src->coded_picture_number; |
||
472 | dst->display_picture_number = src->display_picture_number; |
||
473 | dst->decode_error_flags = src->decode_error_flags; |
||
474 | dst->colorspace = src->colorspace; |
||
475 | dst->color_range = src->color_range; |
||
476 | |||
477 | av_dict_copy(&dst->metadata, src->metadata, 0); |
||
478 | |||
479 | memcpy(dst->error, src->error, sizeof(dst->error)); |
||
480 | |||
481 | for (i = 0; i < src->nb_side_data; i++) { |
||
482 | const AVFrameSideData *sd_src = src->side_data[i]; |
||
483 | AVFrameSideData *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 | av_freep(&dst->side_data[i]->data); |
||
488 | av_freep(&dst->side_data[i]); |
||
489 | av_dict_free(&dst->side_data[i]->metadata); |
||
490 | } |
||
491 | av_freep(&dst->side_data); |
||
492 | return AVERROR(ENOMEM); |
||
493 | } |
||
494 | memcpy(sd_dst->data, sd_src->data, sd_src->size); |
||
495 | av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0); |
||
496 | } |
||
497 | |||
498 | dst->qscale_table = NULL; |
||
499 | dst->qstride = 0; |
||
500 | dst->qscale_type = 0; |
||
501 | if (src->qp_table_buf) { |
||
502 | dst->qp_table_buf = av_buffer_ref(src->qp_table_buf); |
||
503 | if (dst->qp_table_buf) { |
||
504 | dst->qscale_table = dst->qp_table_buf->data; |
||
505 | dst->qstride = src->qstride; |
||
506 | dst->qscale_type = src->qscale_type; |
||
507 | } |
||
508 | } |
||
509 | |||
510 | return 0; |
||
511 | } |
||
512 | |||
513 | AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) |
||
514 | { |
||
515 | uint8_t *data; |
||
516 | int planes, i; |
||
517 | |||
518 | if (frame->nb_samples) { |
||
519 | int channels = frame->channels; |
||
520 | if (!channels) |
||
521 | return NULL; |
||
522 | CHECK_CHANNELS_CONSISTENCY(frame); |
||
523 | planes = av_sample_fmt_is_planar(frame->format) ? channels : 1; |
||
524 | } else |
||
525 | planes = 4; |
||
526 | |||
527 | if (plane < 0 || plane >= planes || !frame->extended_data[plane]) |
||
528 | return NULL; |
||
529 | data = frame->extended_data[plane]; |
||
530 | |||
531 | for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) { |
||
532 | AVBufferRef *buf = frame->buf[i]; |
||
533 | if (data >= buf->data && data < buf->data + buf->size) |
||
534 | return buf; |
||
535 | } |
||
536 | for (i = 0; i < frame->nb_extended_buf; i++) { |
||
537 | AVBufferRef *buf = frame->extended_buf[i]; |
||
538 | if (data >= buf->data && data < buf->data + buf->size) |
||
539 | return buf; |
||
540 | } |
||
541 | return NULL; |
||
542 | } |
||
543 | |||
544 | AVFrameSideData *av_frame_new_side_data(AVFrame *frame, |
||
545 | enum AVFrameSideDataType type, |
||
546 | int size) |
||
547 | { |
||
548 | AVFrameSideData *ret, **tmp; |
||
549 | |||
550 | if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1) |
||
551 | return NULL; |
||
552 | |||
553 | tmp = av_realloc(frame->side_data, |
||
554 | (frame->nb_side_data + 1) * sizeof(*frame->side_data)); |
||
555 | if (!tmp) |
||
556 | return NULL; |
||
557 | frame->side_data = tmp; |
||
558 | |||
559 | ret = av_mallocz(sizeof(*ret)); |
||
560 | if (!ret) |
||
561 | return NULL; |
||
562 | |||
563 | ret->data = av_malloc(size); |
||
564 | if (!ret->data) { |
||
565 | av_freep(&ret); |
||
566 | return NULL; |
||
567 | } |
||
568 | |||
569 | ret->size = size; |
||
570 | ret->type = type; |
||
571 | |||
572 | frame->side_data[frame->nb_side_data++] = ret; |
||
573 | |||
574 | return ret; |
||
575 | } |
||
576 | |||
577 | AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, |
||
578 | enum AVFrameSideDataType type) |
||
579 | { |
||
580 | int i; |
||
581 | |||
582 | for (i = 0; i < frame->nb_side_data; i++) { |
||
583 | if (frame->side_data[i]->type == type) |
||
584 | return frame->side_data[i]; |
||
585 | } |
||
586 | return NULL; |
||
587 | }>>>>>>>>>>>>>>>>>>>>>>>>>>>=align;>> |