blob: e633245a6287ba6d389fc20ece99a88f8befad7f
1 | /* |
2 | * AVPacket functions for libavcodec |
3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include <string.h> |
23 | |
24 | #include "libavutil/avassert.h" |
25 | #include "libavutil/common.h" |
26 | #include "libavutil/internal.h" |
27 | #include "libavutil/mathematics.h" |
28 | #include "libavutil/mem.h" |
29 | #include "avcodec.h" |
30 | #include "bytestream.h" |
31 | #include "internal.h" |
32 | |
33 | void av_init_packet(AVPacket *pkt) |
34 | { |
35 | pkt->pts = AV_NOPTS_VALUE; |
36 | pkt->dts = AV_NOPTS_VALUE; |
37 | pkt->pos = -1; |
38 | pkt->duration = 0; |
39 | #if FF_API_CONVERGENCE_DURATION |
40 | FF_DISABLE_DEPRECATION_WARNINGS |
41 | pkt->convergence_duration = 0; |
42 | FF_ENABLE_DEPRECATION_WARNINGS |
43 | #endif |
44 | pkt->flags = 0; |
45 | pkt->stream_index = 0; |
46 | pkt->buf = NULL; |
47 | pkt->side_data = NULL; |
48 | pkt->side_data_elems = 0; |
49 | } |
50 | |
51 | AVPacket *av_packet_alloc(void) |
52 | { |
53 | AVPacket *pkt = av_mallocz(sizeof(AVPacket)); |
54 | if (!pkt) |
55 | return pkt; |
56 | |
57 | av_packet_unref(pkt); |
58 | |
59 | return pkt; |
60 | } |
61 | |
62 | void av_packet_free(AVPacket **pkt) |
63 | { |
64 | if (!pkt || !*pkt) |
65 | return; |
66 | |
67 | av_packet_unref(*pkt); |
68 | av_freep(pkt); |
69 | } |
70 | |
71 | static int packet_alloc(AVBufferRef **buf, int size) |
72 | { |
73 | int ret; |
74 | if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
75 | return AVERROR(EINVAL); |
76 | |
77 | ret = av_buffer_realloc(buf, size + AV_INPUT_BUFFER_PADDING_SIZE); |
78 | if (ret < 0) |
79 | return ret; |
80 | |
81 | memset((*buf)->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
82 | |
83 | return 0; |
84 | } |
85 | |
86 | int av_new_packet(AVPacket *pkt, int size) |
87 | { |
88 | AVBufferRef *buf = NULL; |
89 | int ret = packet_alloc(&buf, size); |
90 | if (ret < 0) |
91 | return ret; |
92 | |
93 | av_init_packet(pkt); |
94 | pkt->buf = buf; |
95 | pkt->data = buf->data; |
96 | pkt->size = size; |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | void av_shrink_packet(AVPacket *pkt, int size) |
102 | { |
103 | if (pkt->size <= size) |
104 | return; |
105 | pkt->size = size; |
106 | memset(pkt->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
107 | } |
108 | |
109 | int av_grow_packet(AVPacket *pkt, int grow_by) |
110 | { |
111 | int new_size; |
112 | av_assert0((unsigned)pkt->size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); |
113 | if ((unsigned)grow_by > |
114 | INT_MAX - (pkt->size + AV_INPUT_BUFFER_PADDING_SIZE)) |
115 | return -1; |
116 | |
117 | new_size = pkt->size + grow_by + AV_INPUT_BUFFER_PADDING_SIZE; |
118 | if (pkt->buf) { |
119 | size_t data_offset; |
120 | uint8_t *old_data = pkt->data; |
121 | if (pkt->data == NULL) { |
122 | data_offset = 0; |
123 | pkt->data = pkt->buf->data; |
124 | } else { |
125 | data_offset = pkt->data - pkt->buf->data; |
126 | if (data_offset > INT_MAX - new_size) |
127 | return -1; |
128 | } |
129 | |
130 | if (new_size + data_offset > pkt->buf->size) { |
131 | int ret = av_buffer_realloc(&pkt->buf, new_size + data_offset); |
132 | if (ret < 0) { |
133 | pkt->data = old_data; |
134 | return ret; |
135 | } |
136 | pkt->data = pkt->buf->data + data_offset; |
137 | } |
138 | } else { |
139 | pkt->buf = av_buffer_alloc(new_size); |
140 | if (!pkt->buf) |
141 | return AVERROR(ENOMEM); |
142 | if (pkt->size > 0) |
143 | memcpy(pkt->buf->data, pkt->data, pkt->size); |
144 | pkt->data = pkt->buf->data; |
145 | } |
146 | pkt->size += grow_by; |
147 | memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
148 | |
149 | return 0; |
150 | } |
151 | |
152 | int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size) |
153 | { |
154 | if (size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
155 | return AVERROR(EINVAL); |
156 | |
157 | pkt->buf = av_buffer_create(data, size + AV_INPUT_BUFFER_PADDING_SIZE, |
158 | av_buffer_default_free, NULL, 0); |
159 | if (!pkt->buf) |
160 | return AVERROR(ENOMEM); |
161 | |
162 | pkt->data = data; |
163 | pkt->size = size; |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | #if FF_API_AVPACKET_OLD_API |
169 | FF_DISABLE_DEPRECATION_WARNINGS |
170 | #define ALLOC_MALLOC(data, size) data = av_malloc(size) |
171 | #define ALLOC_BUF(data, size) \ |
172 | do { \ |
173 | av_buffer_realloc(&pkt->buf, size); \ |
174 | data = pkt->buf ? pkt->buf->data : NULL; \ |
175 | } while (0) |
176 | |
177 | #define DUP_DATA(dst, src, size, padding, ALLOC) \ |
178 | do { \ |
179 | void *data; \ |
180 | if (padding) { \ |
181 | if ((unsigned)(size) > \ |
182 | (unsigned)(size) + AV_INPUT_BUFFER_PADDING_SIZE) \ |
183 | goto failed_alloc; \ |
184 | ALLOC(data, size + AV_INPUT_BUFFER_PADDING_SIZE); \ |
185 | } else { \ |
186 | ALLOC(data, size); \ |
187 | } \ |
188 | if (!data) \ |
189 | goto failed_alloc; \ |
190 | memcpy(data, src, size); \ |
191 | if (padding) \ |
192 | memset((uint8_t *)data + size, 0, \ |
193 | AV_INPUT_BUFFER_PADDING_SIZE); \ |
194 | dst = data; \ |
195 | } while (0) |
196 | |
197 | /* Makes duplicates of data, side_data, but does not copy any other fields */ |
198 | static int copy_packet_data(AVPacket *pkt, const AVPacket *src, int dup) |
199 | { |
200 | pkt->data = NULL; |
201 | pkt->side_data = NULL; |
202 | pkt->side_data_elems = 0; |
203 | if (pkt->buf) { |
204 | AVBufferRef *ref = av_buffer_ref(src->buf); |
205 | if (!ref) |
206 | return AVERROR(ENOMEM); |
207 | pkt->buf = ref; |
208 | pkt->data = ref->data; |
209 | } else { |
210 | DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); |
211 | } |
212 | if (src->side_data_elems && dup) { |
213 | pkt->side_data = src->side_data; |
214 | pkt->side_data_elems = src->side_data_elems; |
215 | } |
216 | if (src->side_data_elems && !dup) { |
217 | return av_copy_packet_side_data(pkt, src); |
218 | } |
219 | return 0; |
220 | |
221 | failed_alloc: |
222 | av_packet_unref(pkt); |
223 | return AVERROR(ENOMEM); |
224 | } |
225 | |
226 | int av_copy_packet_side_data(AVPacket *pkt, const AVPacket *src) |
227 | { |
228 | if (src->side_data_elems) { |
229 | int i; |
230 | DUP_DATA(pkt->side_data, src->side_data, |
231 | src->side_data_elems * sizeof(*src->side_data), 0, ALLOC_MALLOC); |
232 | if (src != pkt) { |
233 | memset(pkt->side_data, 0, |
234 | src->side_data_elems * sizeof(*src->side_data)); |
235 | } |
236 | for (i = 0; i < src->side_data_elems; i++) { |
237 | DUP_DATA(pkt->side_data[i].data, src->side_data[i].data, |
238 | src->side_data[i].size, 1, ALLOC_MALLOC); |
239 | pkt->side_data[i].size = src->side_data[i].size; |
240 | pkt->side_data[i].type = src->side_data[i].type; |
241 | } |
242 | } |
243 | pkt->side_data_elems = src->side_data_elems; |
244 | return 0; |
245 | |
246 | failed_alloc: |
247 | av_packet_unref(pkt); |
248 | return AVERROR(ENOMEM); |
249 | } |
250 | FF_ENABLE_DEPRECATION_WARNINGS |
251 | #endif |
252 | |
253 | int av_dup_packet(AVPacket *pkt) |
254 | { |
255 | AVPacket tmp_pkt; |
256 | |
257 | if (!pkt->buf && pkt->data) { |
258 | tmp_pkt = *pkt; |
259 | return copy_packet_data(pkt, &tmp_pkt, 1); |
260 | } |
261 | return 0; |
262 | } |
263 | |
264 | int av_copy_packet(AVPacket *dst, const AVPacket *src) |
265 | { |
266 | *dst = *src; |
267 | return copy_packet_data(dst, src, 0); |
268 | } |
269 | |
270 | void av_packet_free_side_data(AVPacket *pkt) |
271 | { |
272 | int i; |
273 | for (i = 0; i < pkt->side_data_elems; i++) |
274 | av_freep(&pkt->side_data[i].data); |
275 | av_freep(&pkt->side_data); |
276 | pkt->side_data_elems = 0; |
277 | } |
278 | |
279 | #if FF_API_AVPACKET_OLD_API |
280 | FF_DISABLE_DEPRECATION_WARNINGS |
281 | void av_free_packet(AVPacket *pkt) |
282 | { |
283 | if (pkt) { |
284 | if (pkt->buf) |
285 | av_buffer_unref(&pkt->buf); |
286 | pkt->data = NULL; |
287 | pkt->size = 0; |
288 | |
289 | av_packet_free_side_data(pkt); |
290 | } |
291 | } |
292 | FF_ENABLE_DEPRECATION_WARNINGS |
293 | #endif |
294 | |
295 | int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, |
296 | uint8_t *data, size_t size) |
297 | { |
298 | AVPacketSideData *tmp; |
299 | int elems = pkt->side_data_elems; |
300 | |
301 | if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data)) |
302 | return AVERROR(ERANGE); |
303 | |
304 | tmp = av_realloc(pkt->side_data, (elems + 1) * sizeof(*tmp)); |
305 | if (!tmp) |
306 | return AVERROR(ENOMEM); |
307 | |
308 | pkt->side_data = tmp; |
309 | pkt->side_data[elems].data = data; |
310 | pkt->side_data[elems].size = size; |
311 | pkt->side_data[elems].type = type; |
312 | pkt->side_data_elems++; |
313 | |
314 | return 0; |
315 | } |
316 | |
317 | |
318 | uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, |
319 | int size) |
320 | { |
321 | int ret; |
322 | uint8_t *data; |
323 | |
324 | if ((unsigned)size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
325 | return NULL; |
326 | data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); |
327 | if (!data) |
328 | return NULL; |
329 | |
330 | ret = av_packet_add_side_data(pkt, type, data, size); |
331 | if (ret < 0) { |
332 | av_freep(&data); |
333 | return NULL; |
334 | } |
335 | |
336 | return data; |
337 | } |
338 | |
339 | uint8_t *av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, |
340 | int *size) |
341 | { |
342 | int i; |
343 | |
344 | for (i = 0; i < pkt->side_data_elems; i++) { |
345 | if (pkt->side_data[i].type == type) { |
346 | if (size) |
347 | *size = pkt->side_data[i].size; |
348 | return pkt->side_data[i].data; |
349 | } |
350 | } |
351 | if (size) |
352 | *size = 0; |
353 | return NULL; |
354 | } |
355 | |
356 | const char *av_packet_side_data_name(enum AVPacketSideDataType type) |
357 | { |
358 | switch(type) { |
359 | case AV_PKT_DATA_PALETTE: return "Palette"; |
360 | case AV_PKT_DATA_NEW_EXTRADATA: return "New Extradata"; |
361 | case AV_PKT_DATA_PARAM_CHANGE: return "Param Change"; |
362 | case AV_PKT_DATA_H263_MB_INFO: return "H263 MB Info"; |
363 | case AV_PKT_DATA_REPLAYGAIN: return "Replay Gain"; |
364 | case AV_PKT_DATA_DISPLAYMATRIX: return "Display Matrix"; |
365 | case AV_PKT_DATA_STEREO3D: return "Stereo 3D"; |
366 | case AV_PKT_DATA_AUDIO_SERVICE_TYPE: return "Audio Service Type"; |
367 | case AV_PKT_DATA_SKIP_SAMPLES: return "Skip Samples"; |
368 | case AV_PKT_DATA_JP_DUALMONO: return "JP Dual Mono"; |
369 | case AV_PKT_DATA_STRINGS_METADATA: return "Strings Metadata"; |
370 | case AV_PKT_DATA_SUBTITLE_POSITION: return "Subtitle Position"; |
371 | case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL: return "Matroska BlockAdditional"; |
372 | case AV_PKT_DATA_WEBVTT_IDENTIFIER: return "WebVTT ID"; |
373 | case AV_PKT_DATA_WEBVTT_SETTINGS: return "WebVTT Settings"; |
374 | case AV_PKT_DATA_METADATA_UPDATE: return "Metadata Update"; |
375 | case AV_PKT_DATA_MPEGTS_STREAM_ID: return "MPEGTS Stream ID"; |
376 | case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata"; |
377 | case AV_PKT_DATA_SPHERICAL: return "Spherical Mapping"; |
378 | } |
379 | return NULL; |
380 | } |
381 | |
382 | #if FF_API_MERGE_SD_API |
383 | |
384 | #define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL |
385 | |
386 | int av_packet_merge_side_data(AVPacket *pkt){ |
387 | if(pkt->side_data_elems){ |
388 | AVBufferRef *buf; |
389 | int i; |
390 | uint8_t *p; |
391 | uint64_t size= pkt->size + 8LL + AV_INPUT_BUFFER_PADDING_SIZE; |
392 | AVPacket old= *pkt; |
393 | for (i=0; i<old.side_data_elems; i++) { |
394 | size += old.side_data[i].size + 5LL; |
395 | } |
396 | if (size > INT_MAX) |
397 | return AVERROR(EINVAL); |
398 | buf = av_buffer_alloc(size); |
399 | if (!buf) |
400 | return AVERROR(ENOMEM); |
401 | pkt->buf = buf; |
402 | pkt->data = p = buf->data; |
403 | pkt->size = size - AV_INPUT_BUFFER_PADDING_SIZE; |
404 | bytestream_put_buffer(&p, old.data, old.size); |
405 | for (i=old.side_data_elems-1; i>=0; i--) { |
406 | bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size); |
407 | bytestream_put_be32(&p, old.side_data[i].size); |
408 | *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128); |
409 | } |
410 | bytestream_put_be64(&p, FF_MERGE_MARKER); |
411 | av_assert0(p-pkt->data == pkt->size); |
412 | memset(p, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
413 | av_packet_unref(&old); |
414 | pkt->side_data_elems = 0; |
415 | pkt->side_data = NULL; |
416 | return 1; |
417 | } |
418 | return 0; |
419 | } |
420 | |
421 | int av_packet_split_side_data(AVPacket *pkt){ |
422 | if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){ |
423 | int i; |
424 | unsigned int size; |
425 | uint8_t *p; |
426 | |
427 | p = pkt->data + pkt->size - 8 - 5; |
428 | for (i=1; ; i++){ |
429 | size = AV_RB32(p); |
430 | if (size>INT_MAX - 5 || p - pkt->data < size) |
431 | return 0; |
432 | if (p[4]&128) |
433 | break; |
434 | if (p - pkt->data < size + 5) |
435 | return 0; |
436 | p-= size+5; |
437 | } |
438 | |
439 | pkt->side_data = av_malloc_array(i, sizeof(*pkt->side_data)); |
440 | if (!pkt->side_data) |
441 | return AVERROR(ENOMEM); |
442 | |
443 | p= pkt->data + pkt->size - 8 - 5; |
444 | for (i=0; ; i++){ |
445 | size= AV_RB32(p); |
446 | av_assert0(size<=INT_MAX - 5 && p - pkt->data >= size); |
447 | pkt->side_data[i].data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); |
448 | pkt->side_data[i].size = size; |
449 | pkt->side_data[i].type = p[4]&127; |
450 | if (!pkt->side_data[i].data) |
451 | return AVERROR(ENOMEM); |
452 | memcpy(pkt->side_data[i].data, p-size, size); |
453 | pkt->size -= size + 5; |
454 | if(p[4]&128) |
455 | break; |
456 | p-= size+5; |
457 | } |
458 | pkt->size -= 8; |
459 | pkt->side_data_elems = i+1; |
460 | return 1; |
461 | } |
462 | return 0; |
463 | } |
464 | |
465 | #endif |
466 | |
467 | uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size) |
468 | { |
469 | AVDictionaryEntry *t = NULL; |
470 | uint8_t *data = NULL; |
471 | *size = 0; |
472 | |
473 | if (!dict) |
474 | return NULL; |
475 | |
476 | while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) { |
477 | const size_t keylen = strlen(t->key); |
478 | const size_t valuelen = strlen(t->value); |
479 | const size_t new_size = *size + keylen + 1 + valuelen + 1; |
480 | uint8_t *const new_data = av_realloc(data, new_size); |
481 | |
482 | if (!new_data) |
483 | goto fail; |
484 | data = new_data; |
485 | if (new_size > INT_MAX) |
486 | goto fail; |
487 | |
488 | memcpy(data + *size, t->key, keylen + 1); |
489 | memcpy(data + *size + keylen + 1, t->value, valuelen + 1); |
490 | |
491 | *size = new_size; |
492 | } |
493 | |
494 | return data; |
495 | |
496 | fail: |
497 | av_freep(&data); |
498 | *size = 0; |
499 | return NULL; |
500 | } |
501 | |
502 | int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict) |
503 | { |
504 | const uint8_t *end = data + size; |
505 | int ret = 0; |
506 | |
507 | if (!dict || !data || !size) |
508 | return ret; |
509 | if (size && end[-1]) |
510 | return AVERROR_INVALIDDATA; |
511 | while (data < end) { |
512 | const uint8_t *key = data; |
513 | const uint8_t *val = data + strlen(key) + 1; |
514 | |
515 | if (val >= end || !*key) |
516 | return AVERROR_INVALIDDATA; |
517 | |
518 | ret = av_dict_set(dict, key, val, 0); |
519 | if (ret < 0) |
520 | break; |
521 | data = val + strlen(val) + 1; |
522 | } |
523 | |
524 | return ret; |
525 | } |
526 | |
527 | int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, |
528 | int size) |
529 | { |
530 | int i; |
531 | |
532 | for (i = 0; i < pkt->side_data_elems; i++) { |
533 | if (pkt->side_data[i].type == type) { |
534 | if (size > pkt->side_data[i].size) |
535 | return AVERROR(ENOMEM); |
536 | pkt->side_data[i].size = size; |
537 | return 0; |
538 | } |
539 | } |
540 | return AVERROR(ENOENT); |
541 | } |
542 | |
543 | int av_packet_copy_props(AVPacket *dst, const AVPacket *src) |
544 | { |
545 | int i; |
546 | |
547 | dst->pts = src->pts; |
548 | dst->dts = src->dts; |
549 | dst->pos = src->pos; |
550 | dst->duration = src->duration; |
551 | #if FF_API_CONVERGENCE_DURATION |
552 | FF_DISABLE_DEPRECATION_WARNINGS |
553 | dst->convergence_duration = src->convergence_duration; |
554 | FF_ENABLE_DEPRECATION_WARNINGS |
555 | #endif |
556 | dst->flags = src->flags; |
557 | dst->stream_index = src->stream_index; |
558 | |
559 | for (i = 0; i < src->side_data_elems; i++) { |
560 | enum AVPacketSideDataType type = src->side_data[i].type; |
561 | int size = src->side_data[i].size; |
562 | uint8_t *src_data = src->side_data[i].data; |
563 | uint8_t *dst_data = av_packet_new_side_data(dst, type, size); |
564 | |
565 | if (!dst_data) { |
566 | av_packet_free_side_data(dst); |
567 | return AVERROR(ENOMEM); |
568 | } |
569 | memcpy(dst_data, src_data, size); |
570 | } |
571 | |
572 | return 0; |
573 | } |
574 | |
575 | void av_packet_unref(AVPacket *pkt) |
576 | { |
577 | av_packet_free_side_data(pkt); |
578 | av_buffer_unref(&pkt->buf); |
579 | av_init_packet(pkt); |
580 | pkt->data = NULL; |
581 | pkt->size = 0; |
582 | } |
583 | |
584 | int av_packet_ref(AVPacket *dst, const AVPacket *src) |
585 | { |
586 | int ret; |
587 | |
588 | ret = av_packet_copy_props(dst, src); |
589 | if (ret < 0) |
590 | return ret; |
591 | |
592 | if (!src->buf) { |
593 | ret = packet_alloc(&dst->buf, src->size); |
594 | if (ret < 0) |
595 | goto fail; |
596 | if (src->size) |
597 | memcpy(dst->buf->data, src->data, src->size); |
598 | |
599 | dst->data = dst->buf->data; |
600 | } else { |
601 | dst->buf = av_buffer_ref(src->buf); |
602 | if (!dst->buf) { |
603 | ret = AVERROR(ENOMEM); |
604 | goto fail; |
605 | } |
606 | dst->data = src->data; |
607 | } |
608 | |
609 | dst->size = src->size; |
610 | |
611 | return 0; |
612 | fail: |
613 | av_packet_free_side_data(dst); |
614 | return ret; |
615 | } |
616 | |
617 | AVPacket *av_packet_clone(const AVPacket *src) |
618 | { |
619 | AVPacket *ret = av_packet_alloc(); |
620 | |
621 | if (!ret) |
622 | return ret; |
623 | |
624 | if (av_packet_ref(ret, src)) |
625 | av_packet_free(&ret); |
626 | |
627 | return ret; |
628 | } |
629 | |
630 | void av_packet_move_ref(AVPacket *dst, AVPacket *src) |
631 | { |
632 | *dst = *src; |
633 | av_init_packet(src); |
634 | src->data = NULL; |
635 | src->size = 0; |
636 | } |
637 | |
638 | void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) |
639 | { |
640 | if (pkt->pts != AV_NOPTS_VALUE) |
641 | pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); |
642 | if (pkt->dts != AV_NOPTS_VALUE) |
643 | pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); |
644 | if (pkt->duration > 0) |
645 | pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); |
646 | #if FF_API_CONVERGENCE_DURATION |
647 | FF_DISABLE_DEPRECATION_WARNINGS |
648 | if (pkt->convergence_duration > 0) |
649 | pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb); |
650 | FF_ENABLE_DEPRECATION_WARNINGS |
651 | #endif |
652 | } |
653 | |
654 | int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type) |
655 | { |
656 | uint8_t *side_data; |
657 | int side_data_size; |
658 | int i; |
659 | |
660 | side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, &side_data_size); |
661 | if (!side_data) { |
662 | side_data_size = 4+4+8*error_count; |
663 | side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, |
664 | side_data_size); |
665 | } |
666 | |
667 | if (!side_data || side_data_size < 4+4+8*error_count) |
668 | return AVERROR(ENOMEM); |
669 | |
670 | AV_WL32(side_data , quality ); |
671 | side_data[4] = pict_type; |
672 | side_data[5] = error_count; |
673 | for (i = 0; i<error_count; i++) |
674 | AV_WL64(side_data+8 + 8*i , error[i]); |
675 | |
676 | return 0; |
677 | } |
678 |