2 * AVPacket functions for libavcodec
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
5 * This file is part of FFmpeg.
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.
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.
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
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"
30 #include "bytestream.h"
33 #if FF_API_DESTRUCT_PACKET
35 void av_destruct_packet(AVPacket
*pkt
)
42 /* a dummy destruct callback for the callers that assume AVPacket.destruct ==
43 * NULL => static data */
44 static void dummy_destruct_packet(AVPacket
*pkt
)
50 void av_init_packet(AVPacket
*pkt
)
52 pkt
->pts
= AV_NOPTS_VALUE
;
53 pkt
->dts
= AV_NOPTS_VALUE
;
56 pkt
->convergence_duration
= 0;
58 pkt
->stream_index
= 0;
59 #if FF_API_DESTRUCT_PACKET
60 FF_DISABLE_DEPRECATION_WARNINGS
62 FF_ENABLE_DEPRECATION_WARNINGS
65 pkt
->side_data
= NULL
;
66 pkt
->side_data_elems
= 0;
69 static int packet_alloc(AVBufferRef
**buf
, int size
)
72 if ((unsigned)size
>= (unsigned)size
+ FF_INPUT_BUFFER_PADDING_SIZE
)
73 return AVERROR(EINVAL
);
75 ret
= av_buffer_realloc(buf
, size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
79 memset((*buf
)->data
+ size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
84 int av_new_packet(AVPacket
*pkt
, int size
)
86 AVBufferRef
*buf
= NULL
;
87 int ret
= packet_alloc(&buf
, size
);
93 pkt
->data
= buf
->data
;
95 #if FF_API_DESTRUCT_PACKET
96 FF_DISABLE_DEPRECATION_WARNINGS
97 pkt
->destruct
= dummy_destruct_packet
;
98 FF_ENABLE_DEPRECATION_WARNINGS
104 void av_shrink_packet(AVPacket
*pkt
, int size
)
106 if (pkt
->size
<= size
)
109 memset(pkt
->data
+ size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
112 int av_grow_packet(AVPacket
*pkt
, int grow_by
)
115 av_assert0((unsigned)pkt
->size
<= INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
);
117 return av_new_packet(pkt
, grow_by
);
118 if ((unsigned)grow_by
>
119 INT_MAX
- (pkt
->size
+ FF_INPUT_BUFFER_PADDING_SIZE
))
122 new_size
= pkt
->size
+ grow_by
+ FF_INPUT_BUFFER_PADDING_SIZE
;
124 int ret
= av_buffer_realloc(&pkt
->buf
, new_size
);
128 pkt
->buf
= av_buffer_alloc(new_size
);
130 return AVERROR(ENOMEM
);
131 memcpy(pkt
->buf
->data
, pkt
->data
, FFMIN(pkt
->size
, pkt
->size
+ grow_by
));
132 #if FF_API_DESTRUCT_PACKET
133 FF_DISABLE_DEPRECATION_WARNINGS
134 pkt
->destruct
= dummy_destruct_packet
;
135 FF_ENABLE_DEPRECATION_WARNINGS
138 pkt
->data
= pkt
->buf
->data
;
139 pkt
->size
+= grow_by
;
140 memset(pkt
->data
+ pkt
->size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
145 int av_packet_from_data(AVPacket
*pkt
, uint8_t *data
, int size
)
147 if (size
>= INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
)
148 return AVERROR(EINVAL
);
150 pkt
->buf
= av_buffer_create(data
, size
+ FF_INPUT_BUFFER_PADDING_SIZE
,
151 av_buffer_default_free
, NULL
, 0);
153 return AVERROR(ENOMEM
);
157 #if FF_API_DESTRUCT_PACKET
158 FF_DISABLE_DEPRECATION_WARNINGS
159 pkt
->destruct
= dummy_destruct_packet
;
160 FF_ENABLE_DEPRECATION_WARNINGS
166 #define ALLOC_MALLOC(data, size) data = av_malloc(size)
167 #define ALLOC_BUF(data, size) \
169 av_buffer_realloc(&pkt->buf, size); \
170 data = pkt->buf ? pkt->buf->data : NULL; \
173 #define DUP_DATA(dst, src, size, padding, ALLOC) \
177 if ((unsigned)(size) > \
178 (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \
180 ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \
186 memcpy(data, src, size); \
188 memset((uint8_t *)data + size, 0, \
189 FF_INPUT_BUFFER_PADDING_SIZE); \
193 /* Makes duplicates of data, side_data, but does not copy any other fields */
194 static int copy_packet_data(AVPacket
*pkt
, const AVPacket
*src
, int dup
)
197 pkt
->side_data
= NULL
;
199 AVBufferRef
*ref
= av_buffer_ref(src
->buf
);
201 return AVERROR(ENOMEM
);
203 pkt
->data
= ref
->data
;
205 DUP_DATA(pkt
->data
, src
->data
, pkt
->size
, 1, ALLOC_BUF
);
207 #if FF_API_DESTRUCT_PACKET
208 FF_DISABLE_DEPRECATION_WARNINGS
209 pkt
->destruct
= dummy_destruct_packet
;
210 FF_ENABLE_DEPRECATION_WARNINGS
212 if (pkt
->side_data_elems
&& dup
)
213 pkt
->side_data
= src
->side_data
;
214 if (pkt
->side_data_elems
&& !dup
) {
215 return av_copy_packet_side_data(pkt
, src
);
221 return AVERROR(ENOMEM
);
224 int av_copy_packet_side_data(AVPacket
*pkt
, const AVPacket
*src
)
226 if (src
->side_data_elems
) {
228 DUP_DATA(pkt
->side_data
, src
->side_data
,
229 src
->side_data_elems
* sizeof(*src
->side_data
), 0, ALLOC_MALLOC
);
231 memset(pkt
->side_data
, 0,
232 src
->side_data_elems
* sizeof(*src
->side_data
));
234 for (i
= 0; i
< src
->side_data_elems
; i
++) {
235 DUP_DATA(pkt
->side_data
[i
].data
, src
->side_data
[i
].data
,
236 src
->side_data
[i
].size
, 1, ALLOC_MALLOC
);
237 pkt
->side_data
[i
].size
= src
->side_data
[i
].size
;
238 pkt
->side_data
[i
].type
= src
->side_data
[i
].type
;
241 pkt
->side_data_elems
= src
->side_data_elems
;
246 return AVERROR(ENOMEM
);
249 int av_dup_packet(AVPacket
*pkt
)
253 FF_DISABLE_DEPRECATION_WARNINGS
254 if (!pkt
->buf
&& pkt
->data
255 #if FF_API_DESTRUCT_PACKET
259 FF_ENABLE_DEPRECATION_WARNINGS
261 return copy_packet_data(pkt
, &tmp_pkt
, 1);
266 int av_copy_packet(AVPacket
*dst
, const AVPacket
*src
)
269 return copy_packet_data(dst
, src
, 0);
272 void av_packet_free_side_data(AVPacket
*pkt
)
275 for (i
= 0; i
< pkt
->side_data_elems
; i
++)
276 av_free(pkt
->side_data
[i
].data
);
277 av_freep(&pkt
->side_data
);
278 pkt
->side_data_elems
= 0;
281 void av_free_packet(AVPacket
*pkt
)
284 FF_DISABLE_DEPRECATION_WARNINGS
286 av_buffer_unref(&pkt
->buf
);
287 #if FF_API_DESTRUCT_PACKET
288 else if (pkt
->destruct
)
290 pkt
->destruct
= NULL
;
292 FF_ENABLE_DEPRECATION_WARNINGS
296 av_packet_free_side_data(pkt
);
300 uint8_t *av_packet_new_side_data(AVPacket
*pkt
, enum AVPacketSideDataType type
,
303 int elems
= pkt
->side_data_elems
;
305 if ((unsigned)elems
+ 1 > INT_MAX
/ sizeof(*pkt
->side_data
))
307 if ((unsigned)size
> INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
)
310 pkt
->side_data
= av_realloc(pkt
->side_data
,
311 (elems
+ 1) * sizeof(*pkt
->side_data
));
315 pkt
->side_data
[elems
].data
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
316 if (!pkt
->side_data
[elems
].data
)
318 pkt
->side_data
[elems
].size
= size
;
319 pkt
->side_data
[elems
].type
= type
;
320 pkt
->side_data_elems
++;
322 return pkt
->side_data
[elems
].data
;
325 uint8_t *av_packet_get_side_data(AVPacket
*pkt
, enum AVPacketSideDataType type
,
330 for (i
= 0; i
< pkt
->side_data_elems
; i
++) {
331 if (pkt
->side_data
[i
].type
== type
) {
333 *size
= pkt
->side_data
[i
].size
;
334 return pkt
->side_data
[i
].data
;
340 #define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL
342 int av_packet_merge_side_data(AVPacket
*pkt
){
343 if(pkt
->side_data_elems
){
347 uint64_t size
= pkt
->size
+ 8LL + FF_INPUT_BUFFER_PADDING_SIZE
;
349 for (i
=0; i
<old
.side_data_elems
; i
++) {
350 size
+= old
.side_data
[i
].size
+ 5LL;
353 return AVERROR(EINVAL
);
354 buf
= av_buffer_alloc(size
);
356 return AVERROR(ENOMEM
);
358 pkt
->data
= p
= buf
->data
;
359 #if FF_API_DESTRUCT_PACKET
360 FF_DISABLE_DEPRECATION_WARNINGS
361 pkt
->destruct
= dummy_destruct_packet
;
362 FF_ENABLE_DEPRECATION_WARNINGS
364 pkt
->size
= size
- FF_INPUT_BUFFER_PADDING_SIZE
;
365 bytestream_put_buffer(&p
, old
.data
, old
.size
);
366 for (i
=old
.side_data_elems
-1; i
>=0; i
--) {
367 bytestream_put_buffer(&p
, old
.side_data
[i
].data
, old
.side_data
[i
].size
);
368 bytestream_put_be32(&p
, old
.side_data
[i
].size
);
369 *p
++ = old
.side_data
[i
].type
| ((i
==old
.side_data_elems
-1)*128);
371 bytestream_put_be64(&p
, FF_MERGE_MARKER
);
372 av_assert0(p
-pkt
->data
== pkt
->size
);
373 memset(p
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
374 av_free_packet(&old
);
375 pkt
->side_data_elems
= 0;
376 pkt
->side_data
= NULL
;
382 int av_packet_split_side_data(AVPacket
*pkt
){
383 if (!pkt
->side_data_elems
&& pkt
->size
>12 && AV_RB64(pkt
->data
+ pkt
->size
- 8) == FF_MERGE_MARKER
){
388 p
= pkt
->data
+ pkt
->size
- 8 - 5;
391 if (size
>INT_MAX
|| p
- pkt
->data
< size
)
398 pkt
->side_data
= av_malloc_array(i
, sizeof(*pkt
->side_data
));
400 return AVERROR(ENOMEM
);
402 p
= pkt
->data
+ pkt
->size
- 8 - 5;
405 av_assert0(size
<=INT_MAX
&& p
- pkt
->data
>= size
);
406 pkt
->side_data
[i
].data
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
407 pkt
->side_data
[i
].size
= size
;
408 pkt
->side_data
[i
].type
= p
[4]&127;
409 if (!pkt
->side_data
[i
].data
)
410 return AVERROR(ENOMEM
);
411 memcpy(pkt
->side_data
[i
].data
, p
-size
, size
);
412 pkt
->size
-= size
+ 5;
418 pkt
->side_data_elems
= i
+1;
424 uint8_t *av_packet_pack_dictionary(AVDictionary
*dict
, int *size
)
426 AVDictionaryEntry
*t
= NULL
;
427 uint8_t *data
= NULL
;
433 while ((t
= av_dict_get(dict
, "", t
, AV_DICT_IGNORE_SUFFIX
))) {
434 const size_t keylen
= strlen(t
->key
);
435 const size_t valuelen
= strlen(t
->value
);
436 const size_t new_size
= *size
+ keylen
+ 1 + valuelen
+ 1;
437 uint8_t *const new_data
= av_realloc(data
, new_size
);
442 if (new_size
> INT_MAX
)
445 memcpy(data
+ *size
, t
->key
, keylen
+ 1);
446 memcpy(data
+ *size
+ keylen
+ 1, t
->value
, valuelen
+ 1);
459 int av_packet_unpack_dictionary(const uint8_t *data
, int size
, AVDictionary
**dict
)
461 const uint8_t *end
= data
+ size
;
464 if (!dict
|| !data
|| !size
)
467 return AVERROR_INVALIDDATA
;
469 const uint8_t *key
= data
;
470 const uint8_t *val
= data
+ strlen(key
) + 1;
473 return AVERROR_INVALIDDATA
;
475 ret
= av_dict_set(dict
, key
, val
, 0);
478 data
= val
+ strlen(val
) + 1;
484 int av_packet_shrink_side_data(AVPacket
*pkt
, enum AVPacketSideDataType type
,
489 for (i
= 0; i
< pkt
->side_data_elems
; i
++) {
490 if (pkt
->side_data
[i
].type
== type
) {
491 if (size
> pkt
->side_data
[i
].size
)
492 return AVERROR(ENOMEM
);
493 pkt
->side_data
[i
].size
= size
;
497 return AVERROR(ENOENT
);
500 int av_packet_copy_props(AVPacket
*dst
, const AVPacket
*src
)
507 dst
->duration
= src
->duration
;
508 dst
->convergence_duration
= src
->convergence_duration
;
509 dst
->flags
= src
->flags
;
510 dst
->stream_index
= src
->stream_index
;
512 for (i
= 0; i
< src
->side_data_elems
; i
++) {
513 enum AVPacketSideDataType type
= src
->side_data
[i
].type
;
514 int size
= src
->side_data
[i
].size
;
515 uint8_t *src_data
= src
->side_data
[i
].data
;
516 uint8_t *dst_data
= av_packet_new_side_data(dst
, type
, size
);
519 av_packet_free_side_data(dst
);
520 return AVERROR(ENOMEM
);
522 memcpy(dst_data
, src_data
, size
);
528 void av_packet_unref(AVPacket
*pkt
)
530 av_packet_free_side_data(pkt
);
531 av_buffer_unref(&pkt
->buf
);
537 int av_packet_ref(AVPacket
*dst
, const AVPacket
*src
)
541 ret
= av_packet_copy_props(dst
, src
);
546 ret
= packet_alloc(&dst
->buf
, src
->size
);
549 memcpy(dst
->buf
->data
, src
->data
, src
->size
);
551 dst
->buf
= av_buffer_ref(src
->buf
);
553 dst
->size
= src
->size
;
554 dst
->data
= dst
->buf
->data
;
557 av_packet_free_side_data(dst
);
561 void av_packet_move_ref(AVPacket
*dst
, AVPacket
*src
)
567 void av_packet_rescale_ts(AVPacket
*pkt
, AVRational src_tb
, AVRational dst_tb
)
569 if (pkt
->pts
!= AV_NOPTS_VALUE
)
570 pkt
->pts
= av_rescale_q(pkt
->pts
, src_tb
, dst_tb
);
571 if (pkt
->dts
!= AV_NOPTS_VALUE
)
572 pkt
->dts
= av_rescale_q(pkt
->dts
, src_tb
, dst_tb
);
573 if (pkt
->duration
> 0)
574 pkt
->duration
= av_rescale_q(pkt
->duration
, src_tb
, dst_tb
);
575 if (pkt
->convergence_duration
> 0)
576 pkt
->convergence_duration
= av_rescale_q(pkt
->convergence_duration
, src_tb
, dst_tb
);