diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-03-08 17:28:42 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-03-08 19:12:03 +0100 |
commit | 2653e125204569b1e9439ee2671c6ebb23a94b80 (patch) | |
tree | 4176f76bccc8cdd1c85b9d329a82867eda37d397 | |
parent | 532f31a695c9530ce67a847be00d72e6e8acfd11 (diff) | |
parent | 1afddbe59e96af75f1c07605afc95615569f388f (diff) | |
download | ffmpeg-2653e125204569b1e9439ee2671c6ebb23a94b80.tar.gz |
Merge commit '1afddbe59e96af75f1c07605afc95615569f388f'
* commit '1afddbe59e96af75f1c07605afc95615569f388f':
avpacket: use AVBuffer to allow refcounting the packets.
Conflicts:
libavcodec/avpacket.c
libavcodec/utils.c
libavdevice/v4l2.c
libavformat/avidec.c
libavformat/flacdec.c
libavformat/id3v2.c
libavformat/matroskaenc.c
libavformat/mux.c
libavformat/utils.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | ffmpeg.c | 1 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 42 | ||||
-rw-r--r-- | libavcodec/avpacket.c | 158 | ||||
-rw-r--r-- | libavcodec/utils.c | 23 | ||||
-rw-r--r-- | libavcodec/version.h | 3 | ||||
-rw-r--r-- | libavdevice/v4l2.c | 147 | ||||
-rw-r--r-- | libavformat/asfdec.c | 16 | ||||
-rw-r--r-- | libavformat/avformat.h | 16 | ||||
-rw-r--r-- | libavformat/avidec.c | 8 | ||||
-rw-r--r-- | libavformat/flacdec.c | 13 | ||||
-rw-r--r-- | libavformat/id3v2.c | 16 | ||||
-rw-r--r-- | libavformat/id3v2.h | 3 | ||||
-rw-r--r-- | libavformat/matroskadec.c | 14 | ||||
-rw-r--r-- | libavformat/matroskaenc.c | 28 | ||||
-rw-r--r-- | libavformat/mp3enc.c | 6 | ||||
-rw-r--r-- | libavformat/mpegts.c | 18 | ||||
-rw-r--r-- | libavformat/mux.c | 3 | ||||
-rw-r--r-- | libavformat/mxg.c | 6 | ||||
-rw-r--r-- | libavformat/psxstr.c | 4 | ||||
-rw-r--r-- | libavformat/rmdec.c | 4 | ||||
-rw-r--r-- | libavformat/rtpdec.c | 8 | ||||
-rw-r--r-- | libavformat/rtpdec_qt.c | 6 | ||||
-rw-r--r-- | libavformat/subtitles.c | 7 | ||||
-rw-r--r-- | libavformat/utils.c | 19 |
24 files changed, 362 insertions, 207 deletions
@@ -570,6 +570,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) memcpy(t, new_pkt.data, new_pkt.size); memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE); new_pkt.data = t; + new_pkt.buf = NULL; a = 1; } else a = AVERROR(ENOMEM); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c4db4d761f..2d338f0a45 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -29,6 +29,7 @@ #include <errno.h> #include "libavutil/samplefmt.h" #include "libavutil/avutil.h" +#include "libavutil/buffer.h" #include "libavutil/cpu.h" #include "libavutil/channel_layout.h" #include "libavutil/dict.h" @@ -1009,18 +1010,24 @@ enum AVPacketSideDataType { * ABI. Thus it may be allocated on stack and no new fields can be added to it * without libavcodec and libavformat major bump. * - * The semantics of data ownership depends on the destruct field. - * If it is set, the packet data is dynamically allocated and is valid - * indefinitely until av_free_packet() is called (which in turn calls the - * destruct callback to free the data). If destruct is not set, the packet data - * is typically backed by some static buffer somewhere and is only valid for a - * limited time (e.g. until the next read call when demuxing). + * The semantics of data ownership depends on the buf or destruct (deprecated) + * fields. If either is set, the packet data is dynamically allocated and is + * valid indefinitely until av_free_packet() is called (which in turn calls + * av_buffer_unref()/the destruct callback to free the data). If neither is set, + * the packet data is typically backed by some static buffer somewhere and is + * only valid for a limited time (e.g. until the next read call when demuxing). * * The side data is always allocated with av_malloc() and is freed in * av_free_packet(). */ typedef struct AVPacket { /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** * Presentation timestamp in AVStream->time_base units; the time at which * the decompressed packet will be presented to the user. * Can be AV_NOPTS_VALUE if it is not stored in the file. @@ -1059,8 +1066,12 @@ typedef struct AVPacket { * Equals next_pts - this_pts in presentation order. */ int duration; +#if FF_API_DESTRUCT_PACKET + attribute_deprecated void (*destruct)(struct AVPacket *); + attribute_deprecated void *priv; +#endif int64_t pos; ///< byte position in stream, -1 if unknown /** @@ -3776,10 +3787,14 @@ void avsubtitle_free(AVSubtitle *sub); * @{ */ +#if FF_API_DESTRUCT_PACKET /** * Default packet destructor. + * @deprecated use the AVBuffer API instead */ +attribute_deprecated void av_destruct_packet(AVPacket *pkt); +#endif /** * Initialize optional fields of a packet with default values. @@ -3818,6 +3833,21 @@ void av_shrink_packet(AVPacket *pkt, int size); int av_grow_packet(AVPacket *pkt, int grow_by); /** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * buf and destruct fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + FF_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +/** * @warning This is a hack - the packet memory allocation stuff is broken. The * packet is allocated if it was not really allocated. */ diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index dea72e5d73..16496e28c4 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -22,6 +22,7 @@ #include <string.h> #include "libavutil/avassert.h" +#include "libavutil/common.h" #include "libavutil/mem.h" #include "avcodec.h" #include "bytestream.h" @@ -36,6 +37,7 @@ void ff_packet_free_side_data(AVPacket *pkt) pkt->side_data_elems = 0; } +#if FF_API_DESTRUCT_PACKET void av_destruct_packet(AVPacket *pkt) { av_free(pkt->data); @@ -43,6 +45,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; @@ -52,27 +62,35 @@ void av_init_packet(AVPacket *pkt) pkt->convergence_duration = 0; pkt->flags = 0; pkt->stream_index = 0; +#if FF_API_DESTRUCT_PACKET pkt->destruct = NULL; +#endif + pkt->buf = NULL; pkt->side_data = NULL; pkt->side_data_elems = 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; + + if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + av_buffer_realloc(&buf, size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!buf) + return AVERROR(ENOMEM); + + memset(buf->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 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 + pkt->destruct = dummy_destruct_packet; +#endif + return 0; } @@ -86,33 +104,71 @@ 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 + pkt->destruct = dummy_destruct_packet; +#endif + } + pkt->data = pkt->buf->data; pkt->size += grow_by; memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + return 0; +} + +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 + pkt->destruct = dummy_destruct_packet; +#endif + return 0; } -#define DUP_DATA(dst, src, size, padding) \ +#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; \ @@ -124,31 +180,33 @@ int av_grow_packet(AVPacket *pkt, int grow_by) } while (0) /* Makes duplicates of data, side_data, but does not copy any other fields */ -static int copy_packet_data(AVPacket *dst, AVPacket *src) +static int copy_packet_data(AVPacket *pkt, AVPacket *src) { - dst->data = NULL; - dst->side_data = NULL; - DUP_DATA(dst->data, src->data, dst->size, 1); - dst->destruct = av_destruct_packet; - - if (dst->side_data_elems) { + pkt->data = NULL; + pkt->side_data = NULL; + DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif + + if (pkt->side_data_elems) { int i; - DUP_DATA(dst->side_data, src->side_data, - dst->side_data_elems * sizeof(*dst->side_data), 0); - memset(dst->side_data, 0, - dst->side_data_elems * sizeof(*dst->side_data)); - for (i = 0; i < dst->side_data_elems; i++) { - DUP_DATA(dst->side_data[i].data, src->side_data[i].data, - src->side_data[i].size, 1); - dst->side_data[i].size = src->side_data[i].size; - dst->side_data[i].type = src->side_data[i].type; + DUP_DATA(pkt->side_data, src->side_data, + 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++) { + DUP_DATA(pkt->side_data[i].data, src->side_data[i].data, + src->side_data[i].size, 1, ALLOC_MALLOC); + pkt->side_data[i].size = src->side_data[i].size; + pkt->side_data[i].type = src->side_data[i].type; } } return 0; failed_alloc: - av_destruct_packet(dst); + av_destruct_packet(pkt); return AVERROR(ENOMEM); } @@ -156,7 +214,11 @@ int av_dup_packet(AVPacket *pkt) { AVPacket tmp_pkt; - if (pkt->destruct == NULL && pkt->data) { + if (!pkt->buf && pkt->data +#if FF_API_DESTRUCT_PACKET + && !pkt->destruct +#endif + ) { tmp_pkt = *pkt; return copy_packet_data(pkt, &tmp_pkt); } @@ -166,6 +228,7 @@ int av_dup_packet(AVPacket *pkt) int av_copy_packet(AVPacket *dst, AVPacket *src) { *dst = *src; + dst->buf = av_buffer_ref(src->buf); return copy_packet_data(dst, src); } @@ -174,8 +237,13 @@ void av_free_packet(AVPacket *pkt) if (pkt) { int i; - if (pkt->destruct) + if (pkt->buf) + av_buffer_unref(&pkt->buf); +#if FF_API_DESTRUCT_PACKET + else if (pkt->destruct) pkt->destruct(pkt); + pkt->destruct = NULL; +#endif pkt->data = NULL; pkt->size = 0; @@ -230,6 +298,7 @@ uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int av_packet_merge_side_data(AVPacket *pkt){ if(pkt->side_data_elems){ + AVBufferRef *buf; int i; uint8_t *p; uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE; @@ -239,11 +308,14 @@ int av_packet_merge_side_data(AVPacket *pkt){ } if (size > INT_MAX) return AVERROR(EINVAL); - p = av_malloc(size); - if (!p) + buf = av_buffer_alloc(size); + if (!buf) return AVERROR(ENOMEM); - pkt->data = p; - pkt->destruct = av_destruct_packet; + pkt->buf = buf; + pkt->data = p = buf->data; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE; bytestream_put_buffer(&p, old.data, old.size); for (i=old.side_data_elems-1; i>=0; i--) { diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 72450decfd..c077b8a385 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1162,7 +1162,10 @@ int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size) } if (avpkt->data) { + AVBufferRef *buf = avpkt->buf; +#if FF_API_DESTRUCT_PACKET void *destruct = avpkt->destruct; +#endif if (avpkt->size < size) { av_log(avctx, AV_LOG_ERROR, "User packet is too small (%d < %d)\n", avpkt->size, size); @@ -1170,7 +1173,10 @@ int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size) } av_init_packet(avpkt); +#if FF_API_DESTRUCT_PACKET avpkt->destruct = destruct; +#endif + avpkt->buf = buf; avpkt->size = size; return 0; } else { @@ -1318,6 +1324,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, avpkt->size = user_pkt.size; ret = -1; } + avpkt->buf = user_pkt.buf; avpkt->data = user_pkt.data; avpkt->destruct = user_pkt.destruct; } else { @@ -1329,9 +1336,9 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, if (!ret) { if (needs_realloc && avpkt->data) { - uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); - if (new_data) - avpkt->data = new_data; + ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (ret >= 0) + avpkt->data = avpkt->buf->data; } avctx->frame_number++; @@ -1515,6 +1522,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, avpkt->size = user_pkt.size; ret = -1; } + avpkt->buf = user_pkt.buf; avpkt->data = user_pkt.data; avpkt->destruct = user_pkt.destruct; } else { @@ -1530,11 +1538,10 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) avpkt->pts = avpkt->dts = frame->pts; - if (needs_realloc && avpkt->data && - avpkt->destruct == av_destruct_packet) { - uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); - if (new_data) - avpkt->data = new_data; + if (needs_realloc && avpkt->data) { + ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (ret >= 0) + avpkt->data = avpkt->buf->data; } avctx->frame_number++; diff --git a/libavcodec/version.h b/libavcodec/version.h index 67fdc25215..3e5fa945ee 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -109,5 +109,8 @@ #ifndef FF_API_DEINTERLACE #define FF_API_DEINTERLACE (LIBAVCODEC_VERSION_MAJOR < 56) #endif +#ifndef FF_API_DESTRUCT_PACKET +#define FF_API_DESTRUCT_PACKET (LIBAVCODEC_VERSION_MAJOR < 56) +#endif #endif /* AVCODEC_VERSION_H */ diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 6726b0b89f..14306bd1a2 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -46,6 +46,7 @@ #endif #include <linux/videodev2.h> #endif +#include "libavutil/atomic.h" #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/log.h" @@ -109,9 +110,9 @@ struct video_data { int64_t last_time_m; int buffers; + volatile int buffers_queued; void **buf_start; unsigned int *buf_len; - int *buf_dequeued; char *standard; v4l2_std_id std_id; int channel; @@ -122,9 +123,9 @@ struct video_data { }; struct buff_data { + struct video_data *s; int index; int fd; - int *buf_dequeued; }; struct fmt_map { @@ -438,11 +439,6 @@ static int mmap_init(AVFormatContext *ctx) av_free(s->buf_start); return AVERROR(ENOMEM); } - s->buf_dequeued = av_mallocz(sizeof(int) * s->buffers); - if (s->buf_dequeued == NULL) { - av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer array\n"); - return AVERROR(ENOMEM); - } for (i = 0; i < req.count; i++) { struct v4l2_buffer buf = { @@ -477,40 +473,33 @@ static int mmap_init(AVFormatContext *ctx) return 0; } -static int enqueue_buffer(int fd, int index) +#if FF_API_DESTRUCT_PACKET +static void dummy_release_buffer(AVPacket *pkt) +{ + av_assert0(0); +} +#endif + +static void mmap_release_buffer(void *opaque, uint8_t *data) { - int res; struct v4l2_buffer buf = { 0 }; + int res, fd; + struct buff_data *buf_descriptor = opaque; + struct video_data *s = buf_descriptor->s; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; - buf.index = index; + buf.index = buf_descriptor->index; + fd = buf_descriptor->fd; + av_free(buf_descriptor); if (v4l2_ioctl(fd, VIDIOC_QBUF, &buf) < 0) { res = AVERROR(errno); - av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res)); - return res; + av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", + av_err2str(res)); } - return 0; -} -static void mmap_release_buffer(AVPacket *pkt) -{ - struct buff_data *buf_descriptor = pkt->priv; - - if (pkt->data == NULL) - return; - - if (buf_descriptor->index == -1) { - av_free(pkt->data); - } else { - if (!enqueue_buffer(buf_descriptor->fd, buf_descriptor->index)) - buf_descriptor->buf_dequeued[buf_descriptor->index] = 0; - } - av_free(buf_descriptor); - - pkt->data = NULL; - pkt->size = 0; + avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); } #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) @@ -580,14 +569,15 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .memory = V4L2_MEMORY_MMAP }; - struct buff_data *buf_descriptor; - int res, i, free_buffers; + int res; /* FIXME: Some special treatment might be needed in case of loss of signal... */ while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR)); if (res < 0) { - if (errno == EAGAIN) + if (errno == EAGAIN) { + pkt->size = 0; return AVERROR(EAGAIN); + } res = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", av_err2str(res)); return res; @@ -597,6 +587,9 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n"); return AVERROR(EINVAL); } + avpriv_atomic_int_add_and_fetch(&s->buffers_queued, -1); + // always keep at least one buffer queued + av_assert0(avpriv_atomic_int_get(&s->buffers_queued) >= 1); /* CPIA is a compressed format and we don't know the exact number of bytes * used by a frame, so set it here as the driver announces it. @@ -608,50 +601,58 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size); - enqueue_buffer(s->fd, buf.index); return AVERROR_INVALIDDATA; } - buf_descriptor = av_malloc(sizeof(struct buff_data)); - if (buf_descriptor == NULL) { - /* Something went wrong... Since av_malloc() failed, we cannot even - * allocate a buffer for memcopying into it - */ - av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); - res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); - return AVERROR(ENOMEM); - } - buf_descriptor->fd = s->fd; - buf_descriptor->buf_dequeued = s->buf_dequeued; - - free_buffers = -1; /* start from -1 because we just dequeued a buffer */ - for (i = 0; i < s->buffers; i++) - if (s->buf_dequeued[i] == 0) - free_buffers++; - - if (free_buffers == 0) { - if ((res = av_new_packet(pkt, buf.bytesused)) < 0) { - enqueue_buffer(s->fd, buf.index); + /* Image is at s->buff_start[buf.index] */ + if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) { + /* when we start getting low on queued buffers, fallback to copying data */ + res = av_new_packet(pkt, buf.bytesused); + if (res < 0) { + av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n"); return res; } memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused); - enqueue_buffer(s->fd, buf.index); - buf_descriptor->index = -1; + + res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); + if (res < 0) { + av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n"); + av_free_packet(pkt); + return AVERROR(errno); + } + avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); } else { - /* Image is at s->buff_start[buf.index] */ - pkt->data = s->buf_start[buf.index]; + struct buff_data *buf_descriptor; + + pkt->data = s->buf_start[buf.index]; + pkt->size = buf.bytesused; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_release_buffer; +#endif + + buf_descriptor = av_malloc(sizeof(struct buff_data)); + if (buf_descriptor == NULL) { + /* Something went wrong... Since av_malloc() failed, we cannot even + * allocate a buffer for memcpying into it + */ + av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); + res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); + + return AVERROR(ENOMEM); + } + buf_descriptor->fd = s->fd; buf_descriptor->index = buf.index; - buf_descriptor->buf_dequeued[buf.index] = 1; + buf_descriptor->s = s; + + pkt->buf = av_buffer_create(pkt->data, pkt->size, mmap_release_buffer, + buf_descriptor, 0); + if (!pkt->buf) { + av_freep(&buf_descriptor); + return AVERROR(ENOMEM); + } } - pkt->size = buf.bytesused; - pkt->priv = buf_descriptor; - pkt->destruct = mmap_release_buffer; pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec; - res = convert_timestamp(ctx, &pkt->pts); - if (res < 0) { - mmap_release_buffer(pkt); - return res; - } + convert_timestamp(ctx, &pkt->pts); return s->buf_len[buf.index]; } @@ -675,6 +676,7 @@ static int mmap_start(AVFormatContext *ctx) return res; } } + s->buffers_queued = s->buffers; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) { @@ -701,7 +703,6 @@ static void mmap_close(struct video_data *s) } av_free(s->buf_start); av_free(s->buf_len); - av_free(s->buf_dequeued); } static int v4l2_set_parameters(AVFormatContext *s1) @@ -1003,8 +1004,6 @@ static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) int res; av_init_packet(pkt); - pkt->data = NULL; - pkt->size = 0; if ((res = mmap_read_frame(s1, pkt)) < 0) { return res; } @@ -1021,6 +1020,10 @@ static int v4l2_read_close(AVFormatContext *s1) { struct video_data *s = s1->priv_data; + if (avpriv_atomic_int_get(&s->buffers_queued) != s->buffers) + av_log(s1, AV_LOG_WARNING, "Some buffers are still owned by the caller on " + "close.\n"); + mmap_close(s); v4l2_close(s->fd); diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index de42b45a8e..1d7f26cefe 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -1282,9 +1282,10 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk asf_st->ds_span); } else { /* packet descrambling */ - uint8_t *newdata = av_malloc(asf_st->pkt.size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (newdata) { + AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (buf) { + uint8_t *newdata = buf->data; int offset = 0; memset(newdata + asf_st->pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE); @@ -1300,13 +1301,18 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk asf_st->ds_chunk_size); offset += asf_st->ds_chunk_size; } - av_free(asf_st->pkt.data); - asf_st->pkt.data = newdata; + av_buffer_unref(&asf_st->pkt.buf); + asf_st->pkt.buf = buf; + asf_st->pkt.data = buf->data; } } } asf_st->frag_offset = 0; *pkt = asf_st->pkt; +#if FF_API_DESTRUCT_PACKET + asf_st->pkt.destruct = NULL; +#endif + asf_st->pkt.buf = 0; asf_st->pkt.size = 0; asf_st->pkt.data = 0; asf_st->pkt.side_data_elems = 0; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index d23d0e87f1..9a53905f95 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -158,9 +158,9 @@ * information will be in AVStream.time_base units, i.e. it has to be * multiplied by the timebase to convert them to seconds. * - * If AVPacket.destruct is set on the returned packet, then the packet is + * If AVPacket.buf is set on the returned packet, then the packet is * allocated dynamically and the user may keep it indefinitely. - * Otherwise, if AVPacket.destruct is NULL, the packet data is backed by a + * Otherwise, if AVPacket.buf is NULL, the packet data is backed by a * static storage somewhere inside the demuxer and the packet is only valid * until the next av_read_frame() call or closing the file. If the caller * requires a longer lifetime, av_dup_packet() will make an av_malloc()ed copy @@ -1605,7 +1605,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt); * omit invalid data between valid frames so as to give the decoder the maximum * information possible for decoding. * - * If pkt->destruct is NULL, then the packet is valid until the next + * If pkt->buf is NULL, then the packet is valid until the next * av_read_frame() or until av_close_input_file(). Otherwise the packet is valid * indefinitely. In both cases the packet must be freed with * av_free_packet when it is no longer needed. For video, the packet contains @@ -1777,10 +1777,10 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt); * demuxer level. * * @param s media file handle - * @param pkt The packet containing the data to be written. Libavformat takes - * ownership of the data and will free it when it sees fit using the packet's - * @ref AVPacket.destruct "destruct" field. The caller must not access the data - * after this function returns, as it may already be freed. + * @param pkt The packet containing the data to be written. pkt->buf must be set + * to a valid AVBufferRef describing the packet data. Libavformat takes + * ownership of this reference and will unref it when it sees fit. The caller + * must not access the data through this reference after this function returns. * This can be NULL (at any time, not just at the end), to flush the * interleaving queues. * Packet's @ref AVPacket.stream_index "stream_index" field must be set to the @@ -2125,7 +2125,7 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec); -void avformat_queue_attached_pictures(AVFormatContext *s); +int avformat_queue_attached_pictures(AVFormatContext *s); /** diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 00ac3de2af..f648f4f019 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -1057,7 +1057,9 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; int err; +#if FF_API_DESTRUCT_PACKET void* dstr; +#endif if (CONFIG_DV_DEMUXER && avi->dv_demux) { int size = avpriv_dv_get_packet(avi->dv_demux, pkt); @@ -1162,10 +1164,16 @@ resync: } if (CONFIG_DV_DEMUXER && avi->dv_demux) { + AVBufferRef *avbuf = pkt->buf; +#if FF_API_DESTRUCT_PACKET dstr = pkt->destruct; +#endif size = avpriv_dv_produce_packet(avi->dv_demux, pkt, pkt->data, pkt->size, pkt->pos); +#if FF_API_DESTRUCT_PACKET pkt->destruct = dstr; +#endif + pkt->buf = avbuf; pkt->flags |= AV_PKT_FLAG_KEY; if (size < 0) av_free_packet(pkt); diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c index ecc47e6ccd..93f8f9df49 100644 --- a/libavformat/flacdec.c +++ b/libavformat/flacdec.c @@ -34,7 +34,8 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) { const CodecMime *mime = ff_id3v2_mime_tags; enum AVCodecID id = AV_CODEC_ID_NONE; - uint8_t mimetype[64], *desc = NULL, *data = NULL; + AVBufferRef *data = NULL; + uint8_t mimetype[64], *desc = NULL; AVIOContext *pb = NULL; AVStream *st; int type, width, height; @@ -110,10 +111,10 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) ret = AVERROR_INVALIDDATA; goto fail; } - if (!(data = av_malloc(len))) { + if (!(data = av_buffer_alloc(len))) { RETURN_ERROR(AVERROR(ENOMEM)); } - if (avio_read(pb, data, len) != len) { + if (avio_read(pb, data->data, len) != len) { av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n"); if (s->error_recognition & AV_EF_EXPLODE) ret = AVERROR(EIO); @@ -126,9 +127,9 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) } av_init_packet(&st->attached_pic); - st->attached_pic.data = data; + st->attached_pic.buf = data; + st->attached_pic.data = data->data; st->attached_pic.size = len; - st->attached_pic.destruct = av_destruct_packet; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; @@ -146,8 +147,8 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) return 0; fail: + av_buffer_unref(&data); av_freep(&desc); - av_freep(&data); av_freep(&pb); return ret; diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 2cab5ac304..3e347d1e77 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -433,7 +433,7 @@ finish: static void free_apic(void *obj) { ID3v2ExtraMetaAPIC *apic = obj; - av_freep(&apic->data); + av_buffer_unref(&apic->buf); av_freep(&apic->description); av_freep(&apic); } @@ -489,9 +489,8 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag goto fail; } - apic->len = taglen; - apic->data = av_malloc(taglen); - if (!apic->data || !apic->len || avio_read(pb, apic->data, taglen) != taglen) + apic->buf = av_buffer_alloc(taglen); + if (!apic->buf || !taglen || avio_read(pb, apic->buf->data, taglen) != taglen) goto fail; new_extra->tag = "APIC"; @@ -846,14 +845,13 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) av_dict_set(&st->metadata, "comment", apic->type, 0); av_init_packet(&st->attached_pic); - st->attached_pic.data = apic->data; - st->attached_pic.size = apic->len; - st->attached_pic.destruct = av_destruct_packet; + st->attached_pic.buf = apic->buf; + st->attached_pic.data = apic->buf->data; + st->attached_pic.size = apic->buf->size; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; - apic->data = NULL; - apic->len = 0; + apic->buf = NULL; } return 0; diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index f7270106a1..e893922133 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -67,8 +67,7 @@ typedef struct ID3v2ExtraMetaGEOB { } ID3v2ExtraMetaGEOB; typedef struct ID3v2ExtraMetaAPIC { - uint8_t *data; - int len; + AVBufferRef *buf; const char *type; uint8_t *description; enum AVCodecID id; diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 249a023471..dd61962127 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1198,7 +1198,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, AVPacket *pkt, uint64_t display_duration) { - char *line, *layer, *ptr = pkt->data, *end = ptr+pkt->size; + AVBufferRef *line; + char *layer, *ptr = pkt->data, *end = ptr+pkt->size; for (; *ptr!=',' && ptr<end-1; ptr++); if (*ptr == ',') ptr++; @@ -1217,13 +1218,14 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, es = ec/ 100; ec -= 100*es; *ptr++ = '\0'; len = 50 + end-ptr + FF_INPUT_BUFFER_PADDING_SIZE; - if (!(line = av_malloc(len))) + if (!(line = av_buffer_alloc(len))) return; - snprintf(line,len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n", + snprintf(line->data, len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n", layer, sh, sm, ss, sc, eh, em, es, ec, ptr); - av_free(pkt->data); - pkt->data = line; - pkt->size = strlen(line); + av_buffer_unref(&pkt->buf); + pkt->buf = line; + pkt->data = line->data; + pkt->size = strlen(line->data); } } diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 4544f8e871..a151eef457 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -92,7 +92,6 @@ typedef struct MatroskaMuxContext { mkv_cues *cues; mkv_track *tracks; - unsigned int audio_buffer_size; AVPacket cur_audio_pkt; int have_attachments; @@ -1043,7 +1042,6 @@ static int mkv_write_header(AVFormatContext *s) av_init_packet(&mkv->cur_audio_pkt); mkv->cur_audio_pkt.size = 0; - mkv->audio_buffer_size = 0; mkv->cluster_pos = -1; avio_flush(pb); @@ -1262,19 +1260,6 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) return 0; } -static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt) -{ - uint8_t *data = mkv->cur_audio_pkt.data; - mkv->cur_audio_pkt = *pkt; - mkv->cur_audio_pkt.data = av_fast_realloc(data, &mkv->audio_buffer_size, pkt->size); - if (!mkv->cur_audio_pkt.data) - return AVERROR(ENOMEM); - - memcpy(mkv->cur_audio_pkt.data, pkt->data, pkt->size); - mkv->cur_audio_pkt.size = pkt->size; - return 0; -} - static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; @@ -1301,7 +1286,7 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) // check if we have an audio packet cached if (mkv->cur_audio_pkt.size > 0) { ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); - mkv->cur_audio_pkt.size = 0; + av_free_packet(&mkv->cur_audio_pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); return ret; @@ -1310,9 +1295,11 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) // buffer an audio packet to ensure the packet containing the video // keyframe's timecode is contained in the same cluster for WebM - if (codec->codec_type == AVMEDIA_TYPE_AUDIO) - ret = mkv_copy_packet(mkv, pkt); - else + if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { + mkv->cur_audio_pkt = *pkt; + mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf); + ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); + } else ret = mkv_write_packet_internal(s, pkt); return ret; } @@ -1327,7 +1314,7 @@ static int mkv_write_trailer(AVFormatContext *s) // check if we have an audio packet cached if (mkv->cur_audio_pkt.size > 0) { ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); - mkv->cur_audio_pkt.size = 0; + av_free_packet(&mkv->cur_audio_pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); return ret; @@ -1364,7 +1351,6 @@ static int mkv_write_trailer(AVFormatContext *s) av_free(mkv->tracks); av_freep(&mkv->cues->entries); av_freep(&mkv->cues); - av_destruct_packet(&mkv->cur_audio_pkt); return 0; } diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index cc9f0d0919..ee0956e8b9 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -422,7 +422,11 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(ENOMEM); pktl->pkt = *pkt; - pkt->destruct = NULL; + pktl->pkt.buf = av_buffer_ref(pkt->buf); + if (!pktl->pkt.buf) { + av_freep(&pktl); + return AVERROR(ENOMEM); + } if (mp3->queue_end) mp3->queue_end->next = pktl; diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 8b92bc421e..d639623f8b 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/buffer.h" #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" @@ -176,7 +177,7 @@ typedef struct PESContext { int64_t pts, dts; int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */ uint8_t header[MAX_PES_HEADER_SIZE]; - uint8_t *buffer; + AVBufferRef *buffer; SLConfigDescr sl; } PESContext; @@ -406,7 +407,7 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) av_freep(&filter->u.section_filter.section_buf); else if (filter->type == MPEGTS_PES) { PESContext *pes = filter->u.pes_filter.opaque; - av_freep(&pes->buffer); + av_buffer_unref(&pes->buffer); /* referenced private data will be freed later in * avformat_close_input */ if (!((PESContext *)filter->u.pes_filter.opaque)->st) { @@ -703,8 +704,8 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) { av_init_packet(pkt); - pkt->destruct = av_destruct_packet; - pkt->data = pes->buffer; + pkt->buf = pes->buffer; + pkt->data = pes->buffer->data; pkt->size = pes->data_index; if(pes->total_size != MAX_PES_PAYLOAD && @@ -869,7 +870,8 @@ static int mpegts_push_data(MpegTSFilter *filter, pes->total_size = MAX_PES_PAYLOAD; /* allocate pes buffer */ - pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); + pes->buffer = av_buffer_alloc(pes->total_size + + FF_INPUT_BUFFER_PADDING_SIZE); if (!pes->buffer) return AVERROR(ENOMEM); @@ -971,7 +973,7 @@ static int mpegts_push_data(MpegTSFilter *filter, if (pes->data_index > 0 && pes->data_index+buf_size > pes->total_size) { new_pes_packet(pes, ts->pkt); pes->total_size = MAX_PES_PAYLOAD; - pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); + pes->buffer = av_buffer_alloc(pes->total_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!pes->buffer) return AVERROR(ENOMEM); ts->stop_parse = 1; @@ -980,7 +982,7 @@ static int mpegts_push_data(MpegTSFilter *filter, // not sure if this is legal in ts but see issue #2392 buf_size = pes->total_size; } - memcpy(pes->buffer+pes->data_index, p, buf_size); + memcpy(pes->buffer->data + pes->data_index, p, buf_size); pes->data_index += buf_size; } buf_size = 0; @@ -1880,7 +1882,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) if (ts->pids[i]) { if (ts->pids[i]->type == MPEGTS_PES) { PESContext *pes = ts->pids[i]->u.pes_filter.opaque; - av_freep(&pes->buffer); + av_buffer_unref(&pes->buffer); pes->data_index = 0; pes->state = MPEGTS_SKIP; /* skip until pes header */ } diff --git a/libavformat/mux.c b/libavformat/mux.c index 98ec7a4cf2..0d74d96ab8 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -540,7 +540,10 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (!this_pktl) return AVERROR(ENOMEM); this_pktl->pkt = *pkt; +#if FF_API_DESTRUCT_PACKET pkt->destruct = NULL; // do not free original but only the copy +#endif + pkt->buf = NULL; av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-allocated memory if (s->streams[pkt->stream_index]->last_in_packet_buffer) { diff --git a/libavformat/mxg.c b/libavformat/mxg.c index e9a6f22b20..604be785bc 100644 --- a/libavformat/mxg.c +++ b/libavformat/mxg.c @@ -170,7 +170,10 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pts = pkt->dts = mxg->dts; pkt->stream_index = 0; +#if FF_API_DESTRUCT_PACKET pkt->destruct = NULL; +#endif + pkt->buf = NULL; pkt->size = mxg->buffer_ptr - mxg->soi_ptr; pkt->data = mxg->soi_ptr; @@ -208,7 +211,10 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) /* time (GMT) of first sample in usec since 1970, little-endian */ pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8); pkt->stream_index = 1; +#if FF_API_DESTRUCT_PACKET pkt->destruct = NULL; +#endif + pkt->buf = NULL; pkt->size = size - 14; pkt->data = startmarker_ptr + 16; diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c index a2a629ffb4..90c933ecd6 100644 --- a/libavformat/psxstr.c +++ b/libavformat/psxstr.c @@ -235,6 +235,10 @@ static int str_read_packet(AVFormatContext *s, *ret_pkt = *pkt; pkt->data= NULL; pkt->size= -1; + pkt->buf = NULL; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = NULL; +#endif return 0; } diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index ee1e0ff30a..d5e40948eb 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -730,6 +730,10 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, *pkt= vst->pkt; vst->pkt.data= NULL; vst->pkt.size= 0; + vst->pkt.buf = NULL; +#if FF_API_DESTRUCT_PACKET + vst->pkt.destruct = NULL; +#endif if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices, vst->videobufpos - 1 - 8*vst->slices); diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 3d74f59729..b512b8975f 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -864,11 +864,15 @@ int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, int ff_rtp_finalize_packet(AVPacket *pkt, AVIOContext **dyn_buf, int stream_idx) { + int ret; av_init_packet(pkt); pkt->size = avio_close_dyn_buf(*dyn_buf, &pkt->data); pkt->stream_index = stream_idx; - pkt->destruct = av_destruct_packet; - *dyn_buf = NULL; + *dyn_buf = NULL; + if ((ret = av_packet_from_data(pkt, pkt->data, pkt->size)) < 0) { + av_freep(&pkt->data); + return ret; + } return pkt->size; } diff --git a/libavformat/rtpdec_qt.c b/libavformat/rtpdec_qt.c index 9631b0ae19..2d2c0fe43b 100644 --- a/libavformat/rtpdec_qt.c +++ b/libavformat/rtpdec_qt.c @@ -186,12 +186,14 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, memcpy(qt->pkt.data + qt->pkt.size, buf + avio_tell(&pb), alen); qt->pkt.size += alen; if (has_marker_bit) { - *pkt = qt->pkt; + int ret = av_packet_from_data(pkt, qt->pkt.data, qt->pkt.size); + if (ret < 0) + return ret; + qt->pkt.size = 0; qt->pkt.data = NULL; pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0; pkt->stream_index = st->index; - pkt->destruct = av_destruct_packet; memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); return 0; } diff --git a/libavformat/subtitles.c b/libavformat/subtitles.c index 37ba0cb0b6..2af0450e86 100644 --- a/libavformat/subtitles.c +++ b/libavformat/subtitles.c @@ -20,6 +20,7 @@ #include "avformat.h" #include "subtitles.h" +#include "libavutil/avassert.h" #include "libavutil/avstring.h" AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, @@ -49,7 +50,6 @@ AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, sub = &subs[q->nb_subs++]; if (av_new_packet(sub, len) < 0) return NULL; - sub->destruct = NULL; sub->flags |= AV_PKT_FLAG_KEY; sub->pts = sub->dts = 0; memcpy(sub->data, event, len); @@ -85,7 +85,8 @@ int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt) if (q->current_sub_idx == q->nb_subs) return AVERROR_EOF; - *pkt = *sub; + av_copy_packet(pkt, sub); + pkt->dts = pkt->pts; q->current_sub_idx++; return 0; @@ -135,7 +136,7 @@ void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q) int i; for (i = 0; i < q->nb_subs; i++) - av_destruct_packet(&q->subs[i]); + av_free_packet(&q->subs[i]); av_freep(&q->subs); q->nb_subs = q->allocated_size = q->current_sub_idx = 0; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 7383cdeb9d..9b44166255 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -555,16 +555,20 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, return &pktl->pkt; } -void avformat_queue_attached_pictures(AVFormatContext *s) +int avformat_queue_attached_pictures(AVFormatContext *s) { int i; for (i = 0; i < s->nb_streams; i++) if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && s->streams[i]->discard < AVDISCARD_ALL) { AVPacket copy = s->streams[i]->attached_pic; - copy.destruct = NULL; + copy.buf = av_buffer_ref(copy.buf); + if (!copy.buf) + return AVERROR(ENOMEM); + add_to_pktbuf(&s->raw_packet_buffer, ©, &s->raw_packet_buffer_end); } + return 0; } int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options) @@ -635,7 +639,8 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma } ff_id3v2_free_extra_meta(&id3v2_extra_meta); - avformat_queue_attached_pictures(s); + if ((ret = avformat_queue_attached_pictures(s)) < 0) + goto fail; if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset) s->data_offset = avio_tell(s->pb); @@ -1333,8 +1338,12 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) compute_pkt_fields(s, st, st->parser, &out_pkt); if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) { + out_pkt.buf = pkt->buf; + pkt->buf = NULL; +#if FF_API_DESTRUCT_PACKET out_pkt.destruct = pkt->destruct; pkt->destruct = NULL; +#endif } if ((ret = av_dup_packet(&out_pkt)) < 0) goto fail; @@ -2085,7 +2094,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f int ret = seek_frame_internal(s, stream_index, timestamp, flags); if (ret >= 0) - avformat_queue_attached_pictures(s); + ret = avformat_queue_attached_pictures(s); return ret; } @@ -2116,7 +2125,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); if (ret >= 0) - avformat_queue_attached_pictures(s); + ret = avformat_queue_attached_pictures(s); return ret; } |