/src/ffmpeg/libavcodec/packet.c
Line | Count | Source |
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/avutil.h" |
26 | | #include "libavutil/container_fifo.h" |
27 | | #include "libavutil/mathematics.h" |
28 | | #include "libavutil/mem.h" |
29 | | #include "libavutil/rational.h" |
30 | | |
31 | | #include "defs.h" |
32 | | #include "packet.h" |
33 | | #include "packet_internal.h" |
34 | | |
35 | | #if FF_API_INIT_PACKET |
36 | | void av_init_packet(AVPacket *pkt) |
37 | 0 | { |
38 | 0 | pkt->pts = AV_NOPTS_VALUE; |
39 | 0 | pkt->dts = AV_NOPTS_VALUE; |
40 | 0 | pkt->pos = -1; |
41 | 0 | pkt->duration = 0; |
42 | 0 | pkt->flags = 0; |
43 | 0 | pkt->stream_index = 0; |
44 | 0 | pkt->buf = NULL; |
45 | 0 | pkt->side_data = NULL; |
46 | 0 | pkt->side_data_elems = 0; |
47 | 0 | pkt->opaque = NULL; |
48 | 0 | pkt->opaque_ref = NULL; |
49 | 0 | pkt->time_base = av_make_q(0, 1); |
50 | 0 | } |
51 | | #endif |
52 | | |
53 | | static void get_packet_defaults(AVPacket *pkt) |
54 | 5.45k | { |
55 | 5.45k | memset(pkt, 0, sizeof(*pkt)); |
56 | | |
57 | 5.45k | pkt->pts = AV_NOPTS_VALUE; |
58 | 5.45k | pkt->dts = AV_NOPTS_VALUE; |
59 | 5.45k | pkt->pos = -1; |
60 | 5.45k | pkt->time_base = av_make_q(0, 1); |
61 | 5.45k | } |
62 | | |
63 | | AVPacket *av_packet_alloc(void) |
64 | 2.72k | { |
65 | 2.72k | AVPacket *pkt = av_malloc(sizeof(AVPacket)); |
66 | 2.72k | if (!pkt) |
67 | 0 | return pkt; |
68 | | |
69 | 2.72k | get_packet_defaults(pkt); |
70 | | |
71 | 2.72k | return pkt; |
72 | 2.72k | } |
73 | | |
74 | | void av_packet_free(AVPacket **pkt) |
75 | 2.72k | { |
76 | 2.72k | if (!pkt || !*pkt) |
77 | 0 | return; |
78 | | |
79 | 2.72k | av_packet_unref(*pkt); |
80 | 2.72k | av_freep(pkt); |
81 | 2.72k | } |
82 | | |
83 | | static int packet_alloc(AVBufferRef **buf, int size) |
84 | 0 | { |
85 | 0 | int ret; |
86 | 0 | if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
87 | 0 | return AVERROR(EINVAL); |
88 | | |
89 | 0 | ret = av_buffer_realloc(buf, size + AV_INPUT_BUFFER_PADDING_SIZE); |
90 | 0 | if (ret < 0) |
91 | 0 | return ret; |
92 | | |
93 | 0 | memset((*buf)->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
94 | |
|
95 | 0 | return 0; |
96 | 0 | } |
97 | | |
98 | | int av_new_packet(AVPacket *pkt, int size) |
99 | 0 | { |
100 | 0 | AVBufferRef *buf = NULL; |
101 | 0 | int ret = packet_alloc(&buf, size); |
102 | 0 | if (ret < 0) |
103 | 0 | return ret; |
104 | | |
105 | 0 | get_packet_defaults(pkt); |
106 | 0 | pkt->buf = buf; |
107 | 0 | pkt->data = buf->data; |
108 | 0 | pkt->size = size; |
109 | |
|
110 | 0 | return 0; |
111 | 0 | } |
112 | | |
113 | | void av_shrink_packet(AVPacket *pkt, int size) |
114 | 0 | { |
115 | 0 | if (pkt->size <= size) |
116 | 0 | return; |
117 | 0 | pkt->size = size; |
118 | 0 | memset(pkt->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
119 | 0 | } |
120 | | |
121 | | int av_grow_packet(AVPacket *pkt, int grow_by) |
122 | 0 | { |
123 | 0 | int new_size; |
124 | 0 | av_assert0((unsigned)pkt->size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); |
125 | 0 | if ((unsigned)grow_by > |
126 | 0 | INT_MAX - (pkt->size + AV_INPUT_BUFFER_PADDING_SIZE)) |
127 | 0 | return AVERROR(ENOMEM); |
128 | | |
129 | 0 | new_size = pkt->size + grow_by + AV_INPUT_BUFFER_PADDING_SIZE; |
130 | 0 | if (pkt->buf) { |
131 | 0 | size_t data_offset; |
132 | 0 | uint8_t *old_data = pkt->data; |
133 | 0 | if (pkt->data == NULL) { |
134 | 0 | data_offset = 0; |
135 | 0 | pkt->data = pkt->buf->data; |
136 | 0 | } else { |
137 | 0 | data_offset = pkt->data - pkt->buf->data; |
138 | 0 | if (data_offset > INT_MAX - new_size) |
139 | 0 | return AVERROR(ENOMEM); |
140 | 0 | } |
141 | | |
142 | 0 | if (new_size + data_offset > pkt->buf->size || |
143 | 0 | !av_buffer_is_writable(pkt->buf)) { |
144 | 0 | int ret; |
145 | | |
146 | | // allocate slightly more than requested to avoid excessive |
147 | | // reallocations |
148 | 0 | if (new_size + data_offset < INT_MAX - new_size/16) |
149 | 0 | new_size += new_size/16; |
150 | |
|
151 | 0 | ret = av_buffer_realloc(&pkt->buf, new_size + data_offset); |
152 | 0 | if (ret < 0) { |
153 | 0 | pkt->data = old_data; |
154 | 0 | return ret; |
155 | 0 | } |
156 | 0 | pkt->data = pkt->buf->data + data_offset; |
157 | 0 | } |
158 | 0 | } else { |
159 | 0 | pkt->buf = av_buffer_alloc(new_size); |
160 | 0 | if (!pkt->buf) |
161 | 0 | return AVERROR(ENOMEM); |
162 | 0 | if (pkt->size > 0) |
163 | 0 | memcpy(pkt->buf->data, pkt->data, pkt->size); |
164 | 0 | pkt->data = pkt->buf->data; |
165 | 0 | } |
166 | 0 | pkt->size += grow_by; |
167 | 0 | memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
168 | |
|
169 | 0 | return 0; |
170 | 0 | } |
171 | | |
172 | | int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size) |
173 | 0 | { |
174 | 0 | if (size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
175 | 0 | return AVERROR(EINVAL); |
176 | | |
177 | 0 | pkt->buf = av_buffer_create(data, size + AV_INPUT_BUFFER_PADDING_SIZE, |
178 | 0 | av_buffer_default_free, NULL, 0); |
179 | 0 | if (!pkt->buf) |
180 | 0 | return AVERROR(ENOMEM); |
181 | | |
182 | 0 | pkt->data = data; |
183 | 0 | pkt->size = size; |
184 | |
|
185 | 0 | return 0; |
186 | 0 | } |
187 | | |
188 | | void av_packet_free_side_data(AVPacket *pkt) |
189 | 2.72k | { |
190 | 2.72k | int i; |
191 | 2.72k | for (i = 0; i < pkt->side_data_elems; i++) |
192 | 0 | av_freep(&pkt->side_data[i].data); |
193 | 2.72k | av_freep(&pkt->side_data); |
194 | 2.72k | pkt->side_data_elems = 0; |
195 | 2.72k | } |
196 | | |
197 | | int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, |
198 | | uint8_t *data, size_t size) |
199 | 0 | { |
200 | 0 | AVPacketSideData *tmp; |
201 | 0 | int i, elems = pkt->side_data_elems; |
202 | |
|
203 | 0 | for (i = 0; i < elems; i++) { |
204 | 0 | AVPacketSideData *sd = &pkt->side_data[i]; |
205 | |
|
206 | 0 | if (sd->type == type) { |
207 | 0 | av_free(sd->data); |
208 | 0 | sd->data = data; |
209 | 0 | sd->size = size; |
210 | 0 | return 0; |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | 0 | if ((unsigned)elems + 1 > AV_PKT_DATA_NB) |
215 | 0 | return AVERROR(ERANGE); |
216 | | |
217 | 0 | tmp = av_realloc(pkt->side_data, (elems + 1) * sizeof(*tmp)); |
218 | 0 | if (!tmp) |
219 | 0 | return AVERROR(ENOMEM); |
220 | | |
221 | 0 | pkt->side_data = tmp; |
222 | 0 | pkt->side_data[elems].data = data; |
223 | 0 | pkt->side_data[elems].size = size; |
224 | 0 | pkt->side_data[elems].type = type; |
225 | 0 | pkt->side_data_elems++; |
226 | |
|
227 | 0 | return 0; |
228 | 0 | } |
229 | | |
230 | | |
231 | | uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, |
232 | | size_t size) |
233 | 0 | { |
234 | 0 | int ret; |
235 | 0 | uint8_t *data; |
236 | |
|
237 | 0 | if (size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
238 | 0 | return NULL; |
239 | 0 | data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); |
240 | 0 | if (!data) |
241 | 0 | return NULL; |
242 | | |
243 | 0 | ret = av_packet_add_side_data(pkt, type, data, size); |
244 | 0 | if (ret < 0) { |
245 | 0 | av_freep(&data); |
246 | 0 | return NULL; |
247 | 0 | } |
248 | | |
249 | 0 | return data; |
250 | 0 | } |
251 | | |
252 | | uint8_t *av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, |
253 | | size_t *size) |
254 | 0 | { |
255 | 0 | int i; |
256 | |
|
257 | 0 | for (i = 0; i < pkt->side_data_elems; i++) { |
258 | 0 | if (pkt->side_data[i].type == type) { |
259 | 0 | if (size) |
260 | 0 | *size = pkt->side_data[i].size; |
261 | 0 | return pkt->side_data[i].data; |
262 | 0 | } |
263 | 0 | } |
264 | 0 | if (size) |
265 | 0 | *size = 0; |
266 | 0 | return NULL; |
267 | 0 | } |
268 | | |
269 | | const char *av_packet_side_data_name(enum AVPacketSideDataType type) |
270 | 0 | { |
271 | 0 | switch(type) { |
272 | 0 | case AV_PKT_DATA_PALETTE: return "Palette"; |
273 | 0 | case AV_PKT_DATA_NEW_EXTRADATA: return "New Extradata"; |
274 | 0 | case AV_PKT_DATA_PARAM_CHANGE: return "Param Change"; |
275 | 0 | case AV_PKT_DATA_H263_MB_INFO: return "H263 MB Info"; |
276 | 0 | case AV_PKT_DATA_REPLAYGAIN: return "Replay Gain"; |
277 | 0 | case AV_PKT_DATA_DISPLAYMATRIX: return "Display Matrix"; |
278 | 0 | case AV_PKT_DATA_STEREO3D: return "Stereo 3D"; |
279 | 0 | case AV_PKT_DATA_AUDIO_SERVICE_TYPE: return "Audio Service Type"; |
280 | 0 | case AV_PKT_DATA_QUALITY_STATS: return "Quality stats"; |
281 | 0 | case AV_PKT_DATA_FALLBACK_TRACK: return "Fallback track"; |
282 | 0 | case AV_PKT_DATA_CPB_PROPERTIES: return "CPB properties"; |
283 | 0 | case AV_PKT_DATA_SKIP_SAMPLES: return "Skip Samples"; |
284 | 0 | case AV_PKT_DATA_JP_DUALMONO: return "JP Dual Mono"; |
285 | 0 | case AV_PKT_DATA_STRINGS_METADATA: return "Strings Metadata"; |
286 | 0 | case AV_PKT_DATA_SUBTITLE_POSITION: return "Subtitle Position"; |
287 | 0 | case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL: return "Matroska BlockAdditional"; |
288 | 0 | case AV_PKT_DATA_WEBVTT_IDENTIFIER: return "WebVTT ID"; |
289 | 0 | case AV_PKT_DATA_WEBVTT_SETTINGS: return "WebVTT Settings"; |
290 | 0 | case AV_PKT_DATA_METADATA_UPDATE: return "Metadata Update"; |
291 | 0 | case AV_PKT_DATA_MPEGTS_STREAM_ID: return "MPEGTS Stream ID"; |
292 | 0 | case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata"; |
293 | 0 | case AV_PKT_DATA_CONTENT_LIGHT_LEVEL: return "Content light level metadata"; |
294 | 0 | case AV_PKT_DATA_SPHERICAL: return "Spherical Mapping"; |
295 | 0 | case AV_PKT_DATA_A53_CC: return "A53 Closed Captions"; |
296 | 0 | case AV_PKT_DATA_ENCRYPTION_INIT_INFO: return "Encryption initialization data"; |
297 | 0 | case AV_PKT_DATA_ENCRYPTION_INFO: return "Encryption info"; |
298 | 0 | case AV_PKT_DATA_AFD: return "Active Format Description data"; |
299 | 0 | case AV_PKT_DATA_PRFT: return "Producer Reference Time"; |
300 | 0 | case AV_PKT_DATA_ICC_PROFILE: return "ICC Profile"; |
301 | 0 | case AV_PKT_DATA_DOVI_CONF: return "DOVI configuration record"; |
302 | 0 | case AV_PKT_DATA_S12M_TIMECODE: return "SMPTE ST 12-1:2014 timecode"; |
303 | 0 | case AV_PKT_DATA_DYNAMIC_HDR10_PLUS: return "HDR10+ Dynamic Metadata (SMPTE 2094-40)"; |
304 | 0 | case AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT:return "Ambient viewing environment"; |
305 | 0 | case AV_PKT_DATA_IAMF_MIX_GAIN_PARAM: return "IAMF Mix Gain Parameter Data"; |
306 | 0 | case AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM: return "IAMF Demixing Info Parameter Data"; |
307 | 0 | case AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM: return "IAMF Recon Gain Info Parameter Data"; |
308 | 0 | case AV_PKT_DATA_FRAME_CROPPING: return "Frame Cropping"; |
309 | 0 | case AV_PKT_DATA_LCEVC: return "LCEVC NAL data"; |
310 | 0 | case AV_PKT_DATA_3D_REFERENCE_DISPLAYS: return "3D Reference Displays Info"; |
311 | 0 | case AV_PKT_DATA_RTCP_SR: return "RTCP Sender Report"; |
312 | 0 | case AV_PKT_DATA_EXIF: return "EXIF metadata"; |
313 | 0 | } |
314 | 0 | return NULL; |
315 | 0 | } |
316 | | |
317 | | uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size) |
318 | 0 | { |
319 | 0 | uint8_t *data = NULL; |
320 | 0 | *size = 0; |
321 | |
|
322 | 0 | if (!dict) |
323 | 0 | return NULL; |
324 | | |
325 | 0 | for (int pass = 0; pass < 2; pass++) { |
326 | 0 | const AVDictionaryEntry *t = NULL; |
327 | 0 | size_t total_length = 0; |
328 | |
|
329 | 0 | while ((t = av_dict_iterate(dict, t))) { |
330 | 0 | for (int i = 0; i < 2; i++) { |
331 | 0 | const char *str = i ? t->value : t->key; |
332 | 0 | const size_t len = strlen(str) + 1; |
333 | |
|
334 | 0 | if (pass) |
335 | 0 | memcpy(data + total_length, str, len); |
336 | 0 | else if (len > SIZE_MAX - total_length) |
337 | 0 | return NULL; |
338 | 0 | total_length += len; |
339 | 0 | } |
340 | 0 | } |
341 | 0 | if (pass) |
342 | 0 | break; |
343 | 0 | data = av_malloc(total_length); |
344 | 0 | if (!data) |
345 | 0 | return NULL; |
346 | 0 | *size = total_length; |
347 | 0 | } |
348 | | |
349 | 0 | return data; |
350 | 0 | } |
351 | | |
352 | | int av_packet_unpack_dictionary(const uint8_t *data, size_t size, |
353 | | AVDictionary **dict) |
354 | 0 | { |
355 | 0 | const uint8_t *end; |
356 | 0 | int ret; |
357 | |
|
358 | 0 | if (!dict || !data || !size) |
359 | 0 | return 0; |
360 | 0 | end = data + size; |
361 | 0 | if (size && end[-1]) |
362 | 0 | return AVERROR_INVALIDDATA; |
363 | 0 | while (data < end) { |
364 | 0 | const uint8_t *key = data; |
365 | 0 | const uint8_t *val = data + strlen(key) + 1; |
366 | |
|
367 | 0 | if (val >= end || !*key) |
368 | 0 | return AVERROR_INVALIDDATA; |
369 | | |
370 | 0 | ret = av_dict_set(dict, key, val, 0); |
371 | 0 | if (ret < 0) |
372 | 0 | return ret; |
373 | 0 | data = val + strlen(val) + 1; |
374 | 0 | } |
375 | | |
376 | 0 | return 0; |
377 | 0 | } |
378 | | |
379 | | int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, |
380 | | size_t size) |
381 | 0 | { |
382 | 0 | int i; |
383 | |
|
384 | 0 | for (i = 0; i < pkt->side_data_elems; i++) { |
385 | 0 | if (pkt->side_data[i].type == type) { |
386 | 0 | if (size > pkt->side_data[i].size) |
387 | 0 | return AVERROR(ENOMEM); |
388 | 0 | pkt->side_data[i].size = size; |
389 | 0 | return 0; |
390 | 0 | } |
391 | 0 | } |
392 | 0 | return AVERROR(ENOENT); |
393 | 0 | } |
394 | | |
395 | | int av_packet_copy_props(AVPacket *dst, const AVPacket *src) |
396 | 0 | { |
397 | 0 | int i, ret; |
398 | |
|
399 | 0 | dst->pts = src->pts; |
400 | 0 | dst->dts = src->dts; |
401 | 0 | dst->pos = src->pos; |
402 | 0 | dst->duration = src->duration; |
403 | 0 | dst->flags = src->flags; |
404 | 0 | dst->stream_index = src->stream_index; |
405 | 0 | dst->opaque = src->opaque; |
406 | 0 | dst->time_base = src->time_base; |
407 | 0 | dst->opaque_ref = NULL; |
408 | 0 | dst->side_data = NULL; |
409 | 0 | dst->side_data_elems = 0; |
410 | |
|
411 | 0 | ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref); |
412 | 0 | if (ret < 0) |
413 | 0 | return ret; |
414 | | |
415 | 0 | for (i = 0; i < src->side_data_elems; i++) { |
416 | 0 | enum AVPacketSideDataType type = src->side_data[i].type; |
417 | 0 | size_t size = src->side_data[i].size; |
418 | 0 | uint8_t *src_data = src->side_data[i].data; |
419 | 0 | uint8_t *dst_data = av_packet_new_side_data(dst, type, size); |
420 | |
|
421 | 0 | if (!dst_data) { |
422 | 0 | av_buffer_unref(&dst->opaque_ref); |
423 | 0 | av_packet_free_side_data(dst); |
424 | 0 | return AVERROR(ENOMEM); |
425 | 0 | } |
426 | 0 | memcpy(dst_data, src_data, size); |
427 | 0 | } |
428 | | |
429 | 0 | return 0; |
430 | 0 | } |
431 | | |
432 | | void av_packet_unref(AVPacket *pkt) |
433 | 2.72k | { |
434 | 2.72k | av_packet_free_side_data(pkt); |
435 | 2.72k | av_buffer_unref(&pkt->opaque_ref); |
436 | 2.72k | av_buffer_unref(&pkt->buf); |
437 | 2.72k | get_packet_defaults(pkt); |
438 | 2.72k | } |
439 | | |
440 | | int av_packet_ref(AVPacket *dst, const AVPacket *src) |
441 | 0 | { |
442 | 0 | int ret; |
443 | |
|
444 | 0 | dst->buf = NULL; |
445 | |
|
446 | 0 | ret = av_packet_copy_props(dst, src); |
447 | 0 | if (ret < 0) |
448 | 0 | goto fail; |
449 | | |
450 | 0 | if (!src->buf) { |
451 | 0 | ret = packet_alloc(&dst->buf, src->size); |
452 | 0 | if (ret < 0) |
453 | 0 | goto fail; |
454 | 0 | av_assert1(!src->size || src->data); |
455 | 0 | if (src->size) |
456 | 0 | memcpy(dst->buf->data, src->data, src->size); |
457 | |
|
458 | 0 | dst->data = dst->buf->data; |
459 | 0 | } else { |
460 | 0 | dst->buf = av_buffer_ref(src->buf); |
461 | 0 | if (!dst->buf) { |
462 | 0 | ret = AVERROR(ENOMEM); |
463 | 0 | goto fail; |
464 | 0 | } |
465 | 0 | dst->data = src->data; |
466 | 0 | } |
467 | | |
468 | 0 | dst->size = src->size; |
469 | |
|
470 | 0 | return 0; |
471 | 0 | fail: |
472 | 0 | av_packet_unref(dst); |
473 | 0 | return ret; |
474 | 0 | } |
475 | | |
476 | | AVPacket *av_packet_clone(const AVPacket *src) |
477 | 0 | { |
478 | 0 | AVPacket *ret = av_packet_alloc(); |
479 | |
|
480 | 0 | if (!ret) |
481 | 0 | return ret; |
482 | | |
483 | 0 | if (av_packet_ref(ret, src)) |
484 | 0 | av_packet_free(&ret); |
485 | |
|
486 | 0 | return ret; |
487 | 0 | } |
488 | | |
489 | | void av_packet_move_ref(AVPacket *dst, AVPacket *src) |
490 | 0 | { |
491 | 0 | *dst = *src; |
492 | 0 | get_packet_defaults(src); |
493 | 0 | } |
494 | | |
495 | | int av_packet_make_refcounted(AVPacket *pkt) |
496 | 0 | { |
497 | 0 | int ret; |
498 | |
|
499 | 0 | if (pkt->buf) |
500 | 0 | return 0; |
501 | | |
502 | 0 | ret = packet_alloc(&pkt->buf, pkt->size); |
503 | 0 | if (ret < 0) |
504 | 0 | return ret; |
505 | 0 | av_assert1(!pkt->size || pkt->data); |
506 | 0 | if (pkt->size) |
507 | 0 | memcpy(pkt->buf->data, pkt->data, pkt->size); |
508 | |
|
509 | 0 | pkt->data = pkt->buf->data; |
510 | |
|
511 | 0 | return 0; |
512 | 0 | } |
513 | | |
514 | | int av_packet_make_writable(AVPacket *pkt) |
515 | 0 | { |
516 | 0 | AVBufferRef *buf = NULL; |
517 | 0 | int ret; |
518 | |
|
519 | 0 | if (pkt->buf && av_buffer_is_writable(pkt->buf)) |
520 | 0 | return 0; |
521 | | |
522 | 0 | ret = packet_alloc(&buf, pkt->size); |
523 | 0 | if (ret < 0) |
524 | 0 | return ret; |
525 | 0 | av_assert1(!pkt->size || pkt->data); |
526 | 0 | if (pkt->size) |
527 | 0 | memcpy(buf->data, pkt->data, pkt->size); |
528 | |
|
529 | 0 | av_buffer_unref(&pkt->buf); |
530 | 0 | pkt->buf = buf; |
531 | 0 | pkt->data = buf->data; |
532 | |
|
533 | 0 | return 0; |
534 | 0 | } |
535 | | |
536 | | void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) |
537 | 0 | { |
538 | 0 | if (pkt->pts != AV_NOPTS_VALUE) |
539 | 0 | pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); |
540 | 0 | if (pkt->dts != AV_NOPTS_VALUE) |
541 | 0 | pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); |
542 | 0 | if (pkt->duration > 0) |
543 | 0 | pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); |
544 | 0 | } |
545 | | |
546 | | int avpriv_packet_list_put(PacketList *packet_buffer, |
547 | | AVPacket *pkt, |
548 | | int (*copy)(AVPacket *dst, const AVPacket *src), |
549 | | int flags) |
550 | 0 | { |
551 | 0 | PacketListEntry *pktl = av_malloc(sizeof(*pktl)); |
552 | 0 | unsigned int update_end_point = 1; |
553 | 0 | int ret; |
554 | |
|
555 | 0 | if (!pktl) |
556 | 0 | return AVERROR(ENOMEM); |
557 | | |
558 | 0 | if (copy) { |
559 | 0 | get_packet_defaults(&pktl->pkt); |
560 | 0 | ret = copy(&pktl->pkt, pkt); |
561 | 0 | if (ret < 0) { |
562 | 0 | av_free(pktl); |
563 | 0 | return ret; |
564 | 0 | } |
565 | 0 | } else { |
566 | 0 | ret = av_packet_make_refcounted(pkt); |
567 | 0 | if (ret < 0) { |
568 | 0 | av_free(pktl); |
569 | 0 | return ret; |
570 | 0 | } |
571 | 0 | av_packet_move_ref(&pktl->pkt, pkt); |
572 | 0 | } |
573 | | |
574 | 0 | pktl->next = NULL; |
575 | |
|
576 | 0 | if (packet_buffer->head) { |
577 | 0 | if (flags & FF_PACKETLIST_FLAG_PREPEND) { |
578 | 0 | pktl->next = packet_buffer->head; |
579 | 0 | packet_buffer->head = pktl; |
580 | 0 | update_end_point = 0; |
581 | 0 | } else { |
582 | 0 | packet_buffer->tail->next = pktl; |
583 | 0 | } |
584 | 0 | } else |
585 | 0 | packet_buffer->head = pktl; |
586 | |
|
587 | 0 | if (update_end_point) { |
588 | | /* Add the packet in the buffered packet list. */ |
589 | 0 | packet_buffer->tail = pktl; |
590 | 0 | } |
591 | |
|
592 | 0 | return 0; |
593 | 0 | } |
594 | | |
595 | | int avpriv_packet_list_get(PacketList *pkt_buffer, |
596 | | AVPacket *pkt) |
597 | 0 | { |
598 | 0 | PacketListEntry *pktl = pkt_buffer->head; |
599 | 0 | if (!pktl) |
600 | 0 | return AVERROR(EAGAIN); |
601 | 0 | *pkt = pktl->pkt; |
602 | 0 | pkt_buffer->head = pktl->next; |
603 | 0 | if (!pkt_buffer->head) |
604 | 0 | pkt_buffer->tail = NULL; |
605 | 0 | av_freep(&pktl); |
606 | 0 | return 0; |
607 | 0 | } |
608 | | |
609 | | void avpriv_packet_list_free(PacketList *pkt_buf) |
610 | 1.36k | { |
611 | 1.36k | PacketListEntry *tmp = pkt_buf->head; |
612 | | |
613 | 1.36k | while (tmp) { |
614 | 0 | PacketListEntry *pktl = tmp; |
615 | 0 | tmp = pktl->next; |
616 | 0 | av_packet_unref(&pktl->pkt); |
617 | 0 | av_freep(&pktl); |
618 | 0 | } |
619 | 1.36k | pkt_buf->head = pkt_buf->tail = NULL; |
620 | 1.36k | } |
621 | | |
622 | | int ff_side_data_set_prft(AVPacket *pkt, int64_t timestamp) |
623 | 0 | { |
624 | 0 | AVProducerReferenceTime *prft; |
625 | 0 | uint8_t *side_data; |
626 | 0 | size_t side_data_size; |
627 | |
|
628 | 0 | side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size); |
629 | 0 | if (!side_data) { |
630 | 0 | side_data_size = sizeof(AVProducerReferenceTime); |
631 | 0 | side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT, side_data_size); |
632 | 0 | } |
633 | |
|
634 | 0 | if (!side_data || side_data_size < sizeof(AVProducerReferenceTime)) |
635 | 0 | return AVERROR(ENOMEM); |
636 | | |
637 | 0 | prft = (AVProducerReferenceTime *)side_data; |
638 | 0 | prft->wallclock = timestamp; |
639 | 0 | prft->flags = 0; |
640 | |
|
641 | 0 | return 0; |
642 | 0 | } |
643 | | |
644 | | const AVPacketSideData *av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, |
645 | | enum AVPacketSideDataType type) |
646 | 0 | { |
647 | 0 | for (int i = 0; i < nb_sd; i++) |
648 | 0 | if (sd[i].type == type) |
649 | 0 | return &sd[i]; |
650 | | |
651 | 0 | return NULL; |
652 | 0 | } |
653 | | |
654 | | static AVPacketSideData *packet_side_data_add(AVPacketSideData **psd, int *pnb_sd, |
655 | | enum AVPacketSideDataType type, |
656 | | void *data, size_t size) |
657 | 0 | { |
658 | 0 | AVPacketSideData *sd = *psd, *tmp; |
659 | 0 | int nb_sd = *pnb_sd; |
660 | |
|
661 | 0 | for (int i = 0; i < nb_sd; i++) { |
662 | 0 | if (sd[i].type != type) |
663 | 0 | continue; |
664 | | |
665 | 0 | av_free(sd[i].data); |
666 | 0 | sd[i].data = data; |
667 | 0 | sd[i].size = size; |
668 | 0 | return &sd[i]; |
669 | 0 | } |
670 | | |
671 | 0 | if (nb_sd == INT_MAX) |
672 | 0 | return NULL; |
673 | | |
674 | 0 | tmp = av_realloc_array(sd, nb_sd + 1, sizeof(*tmp)); |
675 | 0 | if (!tmp) |
676 | 0 | return NULL; |
677 | | |
678 | 0 | *psd = sd = tmp; |
679 | 0 | sd[nb_sd].type = type; |
680 | 0 | sd[nb_sd].data = data; |
681 | 0 | sd[nb_sd].size = size; |
682 | 0 | *pnb_sd = nb_sd + 1; |
683 | |
|
684 | 0 | return &sd[nb_sd]; |
685 | 0 | } |
686 | | |
687 | | AVPacketSideData *av_packet_side_data_add(AVPacketSideData **psd, int *pnb_sd, |
688 | | enum AVPacketSideDataType type, |
689 | | void *data, size_t size, int flags) |
690 | 0 | { |
691 | 0 | return packet_side_data_add(psd, pnb_sd, type, data, size); |
692 | 0 | } |
693 | | |
694 | | AVPacketSideData *av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd, |
695 | | enum AVPacketSideDataType type, |
696 | | size_t size, int flags) |
697 | 0 | { |
698 | 0 | AVPacketSideData *sd = NULL; |
699 | 0 | uint8_t *data; |
700 | |
|
701 | 0 | if (size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
702 | 0 | return NULL; |
703 | | |
704 | 0 | data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); |
705 | 0 | if (!data) |
706 | 0 | return NULL; |
707 | 0 | memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
708 | |
|
709 | 0 | sd = packet_side_data_add(psd, pnb_sd, type, data, size); |
710 | 0 | if (!sd) |
711 | 0 | av_freep(&data); |
712 | |
|
713 | 0 | return sd; |
714 | 0 | } |
715 | | |
716 | | void av_packet_side_data_remove(AVPacketSideData *sd, int *pnb_sd, |
717 | | enum AVPacketSideDataType type) |
718 | 0 | { |
719 | 0 | int nb_sd = *pnb_sd; |
720 | |
|
721 | 0 | for (int i = nb_sd - 1; i >= 0; i--) { |
722 | 0 | if (sd[i].type != type) |
723 | 0 | continue; |
724 | 0 | av_free(sd[i].data); |
725 | 0 | sd[i] = sd[--nb_sd]; |
726 | 0 | break; |
727 | 0 | } |
728 | |
|
729 | 0 | *pnb_sd = nb_sd; |
730 | 0 | } |
731 | | |
732 | | void av_packet_side_data_free(AVPacketSideData **psd, int *pnb_sd) |
733 | 0 | { |
734 | 0 | AVPacketSideData *sd = *psd; |
735 | 0 | int nb_sd = *pnb_sd; |
736 | |
|
737 | 0 | for (int i = 0; i < nb_sd; i++) |
738 | 0 | av_free(sd[i].data); |
739 | |
|
740 | 0 | av_freep(psd); |
741 | 0 | *pnb_sd = 0; |
742 | 0 | } |
743 | | |
744 | | static void *container_packet_alloc(void *opaque) |
745 | 0 | { |
746 | 0 | return av_packet_alloc(); |
747 | 0 | } |
748 | | |
749 | | static void container_packet_reset(void *opaque, void *obj) |
750 | 0 | { |
751 | 0 | av_packet_unref(obj); |
752 | 0 | } |
753 | | |
754 | | static void container_packet_free(void *opaque, void *obj) |
755 | 0 | { |
756 | 0 | AVPacket *pkt = obj; |
757 | 0 | av_packet_free(&pkt); |
758 | 0 | } |
759 | | |
760 | | static int container_packet_transfer(void *opaque, void *dst, void *src, unsigned flags) |
761 | 0 | { |
762 | 0 | if (flags & AV_CONTAINER_FIFO_FLAG_REF) |
763 | 0 | return av_packet_ref(dst, src); |
764 | | |
765 | 0 | av_packet_move_ref(dst, src); |
766 | 0 | return 0; |
767 | 0 | } |
768 | | |
769 | | AVContainerFifo *av_container_fifo_alloc_avpacket(unsigned flags) |
770 | 0 | { |
771 | | return av_container_fifo_alloc(NULL, container_packet_alloc, |
772 | 0 | container_packet_reset, container_packet_free, |
773 | 0 | container_packet_transfer, 0); |
774 | 0 | } |