X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Favpacket.c;h=557258d83906298bd984f9669a0467278fab4afc;hb=5c4b98de4d101ea715ef86847306a510afd0db0c;hp=c26fb8e35c13d30db6e04f0d0368f9753054dd14;hpb=90cfc084e3e6d37ab88fc96a95f0401d8e8b4cd1;p=ffmpeg diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index c26fb8e35c1..557258d8390 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -22,8 +22,12 @@ #include #include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "avcodec.h" +#if FF_API_DESTRUCT_PACKET void av_destruct_packet(AVPacket *pkt) { @@ -32,6 +36,14 @@ void av_destruct_packet(AVPacket *pkt) pkt->size = 0; } +/* a dummy destruct callback for the callers that assume AVPacket.destruct == + * NULL => static data */ +static void dummy_destruct_packet(AVPacket *pkt) +{ + av_assert0(0); +} +#endif + void av_init_packet(AVPacket *pkt) { pkt->pts = AV_NOPTS_VALUE; @@ -41,27 +53,48 @@ void av_init_packet(AVPacket *pkt) pkt->convergence_duration = 0; pkt->flags = 0; pkt->stream_index = 0; +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + pkt->buf = NULL; pkt->side_data = NULL; pkt->side_data_elems = 0; } +static int packet_alloc(AVBufferRef **buf, int size) +{ + int ret; + if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + ret = av_buffer_realloc(buf, size + FF_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + return ret; + + memset((*buf)->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + return 0; +} + int av_new_packet(AVPacket *pkt, int size) { - uint8_t *data = NULL; - if ((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) - data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (data) { - memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - } else - size = 0; + AVBufferRef *buf = NULL; + int ret = packet_alloc(&buf, size); + if (ret < 0) + return ret; av_init_packet(pkt); - pkt->data = data; + pkt->buf = buf; + pkt->data = buf->data; pkt->size = size; - pkt->destruct = av_destruct_packet; - if (!data) - return AVERROR(ENOMEM); +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS + pkt->destruct = dummy_destruct_packet; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + return 0; } @@ -75,33 +108,75 @@ void av_shrink_packet(AVPacket *pkt, int size) int av_grow_packet(AVPacket *pkt, int grow_by) { - void *new_ptr; + int new_size; av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE); if (!pkt->size) return av_new_packet(pkt, grow_by); if ((unsigned)grow_by > INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) return -1; - new_ptr = av_realloc(pkt->data, - pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE); - if (!new_ptr) - return AVERROR(ENOMEM); - pkt->data = new_ptr; + + new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE; + if (pkt->buf) { + int ret = av_buffer_realloc(&pkt->buf, new_size); + if (ret < 0) + return ret; + } else { + pkt->buf = av_buffer_alloc(new_size); + if (!pkt->buf) + return AVERROR(ENOMEM); + memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by)); +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS + pkt->destruct = dummy_destruct_packet; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } + pkt->data = pkt->buf->data; pkt->size += grow_by; memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + return 0; } -#define DUP_DATA(dst, src, size, padding) \ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size) +{ + if (size >= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + pkt->buf = av_buffer_create(data, size + FF_INPUT_BUFFER_PADDING_SIZE, + av_buffer_default_free, NULL, 0); + if (!pkt->buf) + return AVERROR(ENOMEM); + + pkt->data = data; + pkt->size = size; +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS + pkt->destruct = dummy_destruct_packet; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + return 0; +} + +#define ALLOC_MALLOC(data, size) data = av_malloc(size) +#define ALLOC_BUF(data, size) \ +do { \ + av_buffer_realloc(&pkt->buf, size); \ + data = pkt->buf ? pkt->buf->data : NULL; \ +} while (0) + +#define DUP_DATA(dst, src, size, padding, ALLOC) \ do { \ void *data; \ if (padding) { \ if ((unsigned)(size) > \ (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ goto failed_alloc; \ - data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \ + ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \ } else { \ - data = av_malloc(size); \ + ALLOC(data, size); \ } \ if (!data) \ goto failed_alloc; \ @@ -116,47 +191,71 @@ int av_dup_packet(AVPacket *pkt) { AVPacket tmp_pkt; - if (pkt->destruct == NULL && pkt->data) { +FF_DISABLE_DEPRECATION_WARNINGS + if (!pkt->buf && pkt->data +#if FF_API_DESTRUCT_PACKET + && !pkt->destruct +#endif + ) { +FF_ENABLE_DEPRECATION_WARNINGS tmp_pkt = *pkt; pkt->data = NULL; pkt->side_data = NULL; - DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1); - pkt->destruct = av_destruct_packet; + DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1, ALLOC_BUF); +#if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS + pkt->destruct = dummy_destruct_packet; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (pkt->side_data_elems) { int i; DUP_DATA(pkt->side_data, tmp_pkt.side_data, - pkt->side_data_elems * sizeof(*pkt->side_data), 0); + pkt->side_data_elems * sizeof(*pkt->side_data), 0, ALLOC_MALLOC); memset(pkt->side_data, 0, pkt->side_data_elems * sizeof(*pkt->side_data)); - for (i = 0; i < pkt->side_data_elems; i++) + for (i = 0; i < pkt->side_data_elems; i++) { DUP_DATA(pkt->side_data[i].data, tmp_pkt.side_data[i].data, - tmp_pkt.side_data[i].size, 1); + tmp_pkt.side_data[i].size, 1, ALLOC_MALLOC); + pkt->side_data[i].size = tmp_pkt.side_data[i].size; + pkt->side_data[i].type = tmp_pkt.side_data[i].type; + } } } return 0; failed_alloc: - av_destruct_packet(pkt); + av_free_packet(pkt); return AVERROR(ENOMEM); } +void av_packet_free_side_data(AVPacket *pkt) +{ + int i; + for (i = 0; i < pkt->side_data_elems; i++) + av_free(pkt->side_data[i].data); + av_freep(&pkt->side_data); + pkt->side_data_elems = 0; +} + void av_free_packet(AVPacket *pkt) { if (pkt) { - int i; - - if (pkt->destruct) +FF_DISABLE_DEPRECATION_WARNINGS + if (pkt->buf) + av_buffer_unref(&pkt->buf); +#if FF_API_DESTRUCT_PACKET + else if (pkt->destruct) pkt->destruct(pkt); + pkt->destruct = NULL; +#endif +FF_ENABLE_DEPRECATION_WARNINGS pkt->data = NULL; pkt->size = 0; - for (i = 0; i < pkt->side_data_elems; i++) - av_free(pkt->side_data[i].data); - av_freep(&pkt->side_data); - pkt->side_data_elems = 0; + av_packet_free_side_data(pkt); } } @@ -215,3 +314,87 @@ int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, } return AVERROR(ENOENT); } + +int av_packet_copy_props(AVPacket *dst, const AVPacket *src) +{ + int i; + + dst->pts = src->pts; + dst->dts = src->dts; + dst->pos = src->pos; + dst->duration = src->duration; + dst->convergence_duration = src->convergence_duration; + dst->flags = src->flags; + dst->stream_index = src->stream_index; + + for (i = 0; i < src->side_data_elems; i++) { + enum AVPacketSideDataType type = src->side_data[i].type; + int size = src->side_data[i].size; + uint8_t *src_data = src->side_data[i].data; + uint8_t *dst_data = av_packet_new_side_data(dst, type, size); + + if (!dst_data) { + av_packet_free_side_data(dst); + return AVERROR(ENOMEM); + } + memcpy(dst_data, src_data, size); + } + + return 0; +} + +void av_packet_unref(AVPacket *pkt) +{ + av_packet_free_side_data(pkt); + av_buffer_unref(&pkt->buf); + av_init_packet(pkt); + pkt->data = NULL; + pkt->size = 0; +} + +int av_packet_ref(AVPacket *dst, AVPacket *src) +{ + int ret; + + ret = av_packet_copy_props(dst, src); + if (ret < 0) + return ret; + + if (!src->buf) { + ret = packet_alloc(&dst->buf, src->size); + if (ret < 0) + goto fail; + memcpy(dst->buf->data, src->data, src->size); + } else { + dst->buf = av_buffer_ref(src->buf); + if (!dst->buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + dst->size = src->size; + dst->data = dst->buf->data; + return 0; +fail: + av_packet_free_side_data(dst); + return ret; +} + +void av_packet_move_ref(AVPacket *dst, AVPacket *src) +{ + *dst = *src; + av_init_packet(src); +} + +void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) +{ + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); + if (pkt->duration > 0) + pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); + if (pkt->convergence_duration > 0) + pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb); +}