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
)
41 /* a dummy destruct callback for the callers that assume AVPacket.destruct ==
42 * NULL => static data */
43 static void dummy_destruct_packet(AVPacket
*pkt
)
49 void av_init_packet(AVPacket
*pkt
)
51 pkt
->pts
= AV_NOPTS_VALUE
;
52 pkt
->dts
= AV_NOPTS_VALUE
;
55 pkt
->convergence_duration
= 0;
57 pkt
->stream_index
= 0;
58 #if FF_API_DESTRUCT_PACKET
59 FF_DISABLE_DEPRECATION_WARNINGS
61 FF_ENABLE_DEPRECATION_WARNINGS
64 pkt
->side_data
= NULL
;
65 pkt
->side_data_elems
= 0;
68 static int packet_alloc(AVBufferRef
**buf
, int size
)
71 if ((unsigned)size
>= (unsigned)size
+ FF_INPUT_BUFFER_PADDING_SIZE
)
72 return AVERROR(EINVAL
);
74 ret
= av_buffer_realloc(buf
, size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
78 memset((*buf
)->data
+ size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
83 int av_new_packet(AVPacket
*pkt
, int size
)
85 AVBufferRef
*buf
= NULL
;
86 int ret
= packet_alloc(&buf
, size
);
92 pkt
->data
= buf
->data
;
94 #if FF_API_DESTRUCT_PACKET
95 FF_DISABLE_DEPRECATION_WARNINGS
96 pkt
->destruct
= dummy_destruct_packet
;
97 FF_ENABLE_DEPRECATION_WARNINGS
103 void av_shrink_packet(AVPacket
*pkt
, int size
)
105 if (pkt
->size
<= size
)
108 memset(pkt
->data
+ size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
111 int av_grow_packet(AVPacket
*pkt
, int grow_by
)
114 av_assert0((unsigned)pkt
->size
<= INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
);
116 return av_new_packet(pkt
, grow_by
);
117 if ((unsigned)grow_by
>
118 INT_MAX
- (pkt
->size
+ FF_INPUT_BUFFER_PADDING_SIZE
))
121 new_size
= pkt
->size
+ grow_by
+ FF_INPUT_BUFFER_PADDING_SIZE
;
123 int ret
= av_buffer_realloc(&pkt
->buf
, new_size
);
127 pkt
->buf
= av_buffer_alloc(new_size
);
129 return AVERROR(ENOMEM
);
130 memcpy(pkt
->buf
->data
, pkt
->data
, FFMIN(pkt
->size
, pkt
->size
+ grow_by
));
131 #if FF_API_DESTRUCT_PACKET
132 FF_DISABLE_DEPRECATION_WARNINGS
133 pkt
->destruct
= dummy_destruct_packet
;
134 FF_ENABLE_DEPRECATION_WARNINGS
137 pkt
->data
= pkt
->buf
->data
;
138 pkt
->size
+= grow_by
;
139 memset(pkt
->data
+ pkt
->size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
144 int av_packet_from_data(AVPacket
*pkt
, uint8_t *data
, int size
)
146 if (size
>= INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
)
147 return AVERROR(EINVAL
);
149 pkt
->buf
= av_buffer_create(data
, size
+ FF_INPUT_BUFFER_PADDING_SIZE
,
150 av_buffer_default_free
, NULL
, 0);
152 return AVERROR(ENOMEM
);
156 #if FF_API_DESTRUCT_PACKET
157 FF_DISABLE_DEPRECATION_WARNINGS
158 pkt
->destruct
= dummy_destruct_packet
;
159 FF_ENABLE_DEPRECATION_WARNINGS
165 #define ALLOC_MALLOC(data, size) data = av_malloc(size)
166 #define ALLOC_BUF(data, size) \
168 av_buffer_realloc(&pkt->buf, size); \
169 data = pkt->buf ? pkt->buf->data : NULL; \
172 #define DUP_DATA(dst, src, size, padding, ALLOC) \
176 if ((unsigned)(size) > \
177 (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \
179 ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \
185 memcpy(data, src, size); \
187 memset((uint8_t *)data + size, 0, \
188 FF_INPUT_BUFFER_PADDING_SIZE); \
192 /* Makes duplicates of data, side_data, but does not copy any other fields */
193 static int copy_packet_data(AVPacket
*pkt
, const AVPacket
*src
, int dup
)
196 pkt
->side_data
= NULL
;
198 AVBufferRef
*ref
= av_buffer_ref(src
->buf
);
200 return AVERROR(ENOMEM
);
202 pkt
->data
= ref
->data
;
204 DUP_DATA(pkt
->data
, src
->data
, pkt
->size
, 1, ALLOC_BUF
);
206 #if FF_API_DESTRUCT_PACKET
207 FF_DISABLE_DEPRECATION_WARNINGS
208 pkt
->destruct
= dummy_destruct_packet
;
209 FF_ENABLE_DEPRECATION_WARNINGS
211 if (pkt
->side_data_elems
&& dup
)
212 pkt
->side_data
= src
->side_data
;
213 if (pkt
->side_data_elems
&& !dup
) {
214 return av_copy_packet_side_data(pkt
, src
);
220 return AVERROR(ENOMEM
);
223 int av_copy_packet_side_data(AVPacket
*pkt
, const AVPacket
*src
)
225 if (src
->side_data_elems
) {
227 DUP_DATA(pkt
->side_data
, src
->side_data
,
228 src
->side_data_elems
* sizeof(*src
->side_data
), 0, ALLOC_MALLOC
);
230 memset(pkt
->side_data
, 0,
231 src
->side_data_elems
* sizeof(*src
->side_data
));
233 for (i
= 0; i
< src
->side_data_elems
; i
++) {
234 DUP_DATA(pkt
->side_data
[i
].data
, src
->side_data
[i
].data
,
235 src
->side_data
[i
].size
, 1, ALLOC_MALLOC
);
236 pkt
->side_data
[i
].size
= src
->side_data
[i
].size
;
237 pkt
->side_data
[i
].type
= src
->side_data
[i
].type
;
240 pkt
->side_data_elems
= src
->side_data_elems
;
245 return AVERROR(ENOMEM
);
248 int av_dup_packet(AVPacket
*pkt
)
252 FF_DISABLE_DEPRECATION_WARNINGS
253 if (!pkt
->buf
&& pkt
->data
254 #if FF_API_DESTRUCT_PACKET
258 FF_ENABLE_DEPRECATION_WARNINGS
260 return copy_packet_data(pkt
, &tmp_pkt
, 1);
265 int av_copy_packet(AVPacket
*dst
, const AVPacket
*src
)
268 return copy_packet_data(dst
, src
, 0);
271 void av_packet_free_side_data(AVPacket
*pkt
)
274 for (i
= 0; i
< pkt
->side_data_elems
; i
++)
275 av_freep(&pkt
->side_data
[i
].data
);
276 av_freep(&pkt
->side_data
);
277 pkt
->side_data_elems
= 0;
280 void av_free_packet(AVPacket
*pkt
)
283 FF_DISABLE_DEPRECATION_WARNINGS
285 av_buffer_unref(&pkt
->buf
);
286 #if FF_API_DESTRUCT_PACKET
287 else if (pkt
->destruct
)
289 pkt
->destruct
= NULL
;
291 FF_ENABLE_DEPRECATION_WARNINGS
295 av_packet_free_side_data(pkt
);
299 uint8_t *av_packet_new_side_data(AVPacket
*pkt
, enum AVPacketSideDataType type
,
302 int elems
= pkt
->side_data_elems
;
304 if ((unsigned)elems
+ 1 > INT_MAX
/ sizeof(*pkt
->side_data
))
306 if ((unsigned)size
> INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
)
309 pkt
->side_data
= av_realloc(pkt
->side_data
,
310 (elems
+ 1) * sizeof(*pkt
->side_data
));
314 pkt
->side_data
[elems
].data
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
315 if (!pkt
->side_data
[elems
].data
)
317 pkt
->side_data
[elems
].size
= size
;
318 pkt
->side_data
[elems
].type
= type
;
319 pkt
->side_data_elems
++;
321 return pkt
->side_data
[elems
].data
;
324 uint8_t *av_packet_get_side_data(AVPacket
*pkt
, enum AVPacketSideDataType type
,
329 for (i
= 0; i
< pkt
->side_data_elems
; i
++) {
330 if (pkt
->side_data
[i
].type
== type
) {
332 *size
= pkt
->side_data
[i
].size
;
333 return pkt
->side_data
[i
].data
;
339 #define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL
341 int av_packet_merge_side_data(AVPacket
*pkt
){
342 if(pkt
->side_data_elems
){
346 uint64_t size
= pkt
->size
+ 8LL + FF_INPUT_BUFFER_PADDING_SIZE
;
348 for (i
=0; i
<old
.side_data_elems
; i
++) {
349 size
+= old
.side_data
[i
].size
+ 5LL;
352 return AVERROR(EINVAL
);
353 buf
= av_buffer_alloc(size
);
355 return AVERROR(ENOMEM
);
357 pkt
->data
= p
= buf
->data
;
358 #if FF_API_DESTRUCT_PACKET
359 FF_DISABLE_DEPRECATION_WARNINGS
360 pkt
->destruct
= dummy_destruct_packet
;
361 FF_ENABLE_DEPRECATION_WARNINGS
363 pkt
->size
= size
- FF_INPUT_BUFFER_PADDING_SIZE
;
364 bytestream_put_buffer(&p
, old
.data
, old
.size
);
365 for (i
=old
.side_data_elems
-1; i
>=0; i
--) {
366 bytestream_put_buffer(&p
, old
.side_data
[i
].data
, old
.side_data
[i
].size
);
367 bytestream_put_be32(&p
, old
.side_data
[i
].size
);
368 *p
++ = old
.side_data
[i
].type
| ((i
==old
.side_data_elems
-1)*128);
370 bytestream_put_be64(&p
, FF_MERGE_MARKER
);
371 av_assert0(p
-pkt
->data
== pkt
->size
);
372 memset(p
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
373 av_free_packet(&old
);
374 pkt
->side_data_elems
= 0;
375 pkt
->side_data
= NULL
;
381 int av_packet_split_side_data(AVPacket
*pkt
){
382 if (!pkt
->side_data_elems
&& pkt
->size
>12 && AV_RB64(pkt
->data
+ pkt
->size
- 8) == FF_MERGE_MARKER
){
387 p
= pkt
->data
+ pkt
->size
- 8 - 5;
390 if (size
>INT_MAX
|| p
- pkt
->data
< size
)
397 pkt
->side_data
= av_malloc_array(i
, sizeof(*pkt
->side_data
));
399 return AVERROR(ENOMEM
);
401 p
= pkt
->data
+ pkt
->size
- 8 - 5;
404 av_assert0(size
<=INT_MAX
&& p
- pkt
->data
>= size
);
405 pkt
->side_data
[i
].data
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
406 pkt
->side_data
[i
].size
= size
;
407 pkt
->side_data
[i
].type
= p
[4]&127;
408 if (!pkt
->side_data
[i
].data
)
409 return AVERROR(ENOMEM
);
410 memcpy(pkt
->side_data
[i
].data
, p
-size
, size
);
411 pkt
->size
-= size
+ 5;
417 pkt
->side_data_elems
= i
+1;
423 uint8_t *av_packet_pack_dictionary(AVDictionary
*dict
, int *size
)
425 AVDictionaryEntry
*t
= NULL
;
426 uint8_t *data
= NULL
;
432 while ((t
= av_dict_get(dict
, "", t
, AV_DICT_IGNORE_SUFFIX
))) {
433 const size_t keylen
= strlen(t
->key
);
434 const size_t valuelen
= strlen(t
->value
);
435 const size_t new_size
= *size
+ keylen
+ 1 + valuelen
+ 1;
436 uint8_t *const new_data
= av_realloc(data
, new_size
);
441 if (new_size
> INT_MAX
)
444 memcpy(data
+ *size
, t
->key
, keylen
+ 1);
445 memcpy(data
+ *size
+ keylen
+ 1, t
->value
, valuelen
+ 1);
458 int av_packet_unpack_dictionary(const uint8_t *data
, int size
, AVDictionary
**dict
)
460 const uint8_t *end
= data
+ size
;
463 if (!dict
|| !data
|| !size
)
466 return AVERROR_INVALIDDATA
;
468 const uint8_t *key
= data
;
469 const uint8_t *val
= data
+ strlen(key
) + 1;
472 return AVERROR_INVALIDDATA
;
474 ret
= av_dict_set(dict
, key
, val
, 0);
477 data
= val
+ strlen(val
) + 1;
483 int av_packet_shrink_side_data(AVPacket
*pkt
, enum AVPacketSideDataType type
,
488 for (i
= 0; i
< pkt
->side_data_elems
; i
++) {
489 if (pkt
->side_data
[i
].type
== type
) {
490 if (size
> pkt
->side_data
[i
].size
)
491 return AVERROR(ENOMEM
);
492 pkt
->side_data
[i
].size
= size
;
496 return AVERROR(ENOENT
);
499 int av_packet_copy_props(AVPacket
*dst
, const AVPacket
*src
)
506 dst
->duration
= src
->duration
;
507 dst
->convergence_duration
= src
->convergence_duration
;
508 dst
->flags
= src
->flags
;
509 dst
->stream_index
= src
->stream_index
;
511 for (i
= 0; i
< src
->side_data_elems
; i
++) {
512 enum AVPacketSideDataType type
= src
->side_data
[i
].type
;
513 int size
= src
->side_data
[i
].size
;
514 uint8_t *src_data
= src
->side_data
[i
].data
;
515 uint8_t *dst_data
= av_packet_new_side_data(dst
, type
, size
);
518 av_packet_free_side_data(dst
);
519 return AVERROR(ENOMEM
);
521 memcpy(dst_data
, src_data
, size
);
527 void av_packet_unref(AVPacket
*pkt
)
529 av_packet_free_side_data(pkt
);
530 av_buffer_unref(&pkt
->buf
);
536 int av_packet_ref(AVPacket
*dst
, const AVPacket
*src
)
540 ret
= av_packet_copy_props(dst
, src
);
545 ret
= packet_alloc(&dst
->buf
, src
->size
);
548 memcpy(dst
->buf
->data
, src
->data
, src
->size
);
550 dst
->buf
= av_buffer_ref(src
->buf
);
552 dst
->size
= src
->size
;
553 dst
->data
= dst
->buf
->data
;
556 av_packet_free_side_data(dst
);
560 void av_packet_move_ref(AVPacket
*dst
, AVPacket
*src
)
566 void av_packet_rescale_ts(AVPacket
*pkt
, AVRational src_tb
, AVRational dst_tb
)
568 if (pkt
->pts
!= AV_NOPTS_VALUE
)
569 pkt
->pts
= av_rescale_q(pkt
->pts
, src_tb
, dst_tb
);
570 if (pkt
->dts
!= AV_NOPTS_VALUE
)
571 pkt
->dts
= av_rescale_q(pkt
->dts
, src_tb
, dst_tb
);
572 if (pkt
->duration
> 0)
573 pkt
->duration
= av_rescale_q(pkt
->duration
, src_tb
, dst_tb
);
574 if (pkt
->convergence_duration
> 0)
575 pkt
->convergence_duration
= av_rescale_q(pkt
->convergence_duration
, src_tb
, dst_tb
);