Commit 1afddbe5 authored by Anton Khirnov's avatar Anton Khirnov

avpacket: use AVBuffer to allow refcounting the packets.

This will allow us to avoid copying the packets in many cases.

This breaks ABI.
parent 1cec0624
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <errno.h> #include <errno.h>
#include "libavutil/samplefmt.h" #include "libavutil/samplefmt.h"
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#include "libavutil/buffer.h"
#include "libavutil/cpu.h" #include "libavutil/cpu.h"
#include "libavutil/dict.h" #include "libavutil/dict.h"
#include "libavutil/log.h" #include "libavutil/log.h"
...@@ -892,17 +893,23 @@ enum AVPacketSideDataType { ...@@ -892,17 +893,23 @@ enum AVPacketSideDataType {
* ABI. Thus it may be allocated on stack and no new fields can be added to it * ABI. Thus it may be allocated on stack and no new fields can be added to it
* without libavcodec and libavformat major bump. * without libavcodec and libavformat major bump.
* *
* The semantics of data ownership depends on the destruct field. * The semantics of data ownership depends on the buf or destruct (deprecated)
* If it is set, the packet data is dynamically allocated and is valid * fields. If either is set, the packet data is dynamically allocated and is
* indefinitely until av_free_packet() is called (which in turn calls the * valid indefinitely until av_free_packet() is called (which in turn calls
* destruct callback to free the data). If destruct is not set, the packet data * av_buffer_unref()/the destruct callback to free the data). If neither is set,
* is typically backed by some static buffer somewhere and is only valid for a * the packet data is typically backed by some static buffer somewhere and is
* limited time (e.g. until the next read call when demuxing). * 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 * The side data is always allocated with av_malloc() and is freed in
* av_free_packet(). * av_free_packet().
*/ */
typedef struct AVPacket { 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 * Presentation timestamp in AVStream->time_base units; the time at which
* the decompressed packet will be presented to the user. * the decompressed packet will be presented to the user.
...@@ -942,8 +949,12 @@ typedef struct AVPacket { ...@@ -942,8 +949,12 @@ typedef struct AVPacket {
* Equals next_pts - this_pts in presentation order. * Equals next_pts - this_pts in presentation order.
*/ */
int duration; int duration;
#if FF_API_DESTRUCT_PACKET
attribute_deprecated
void (*destruct)(struct AVPacket *); void (*destruct)(struct AVPacket *);
attribute_deprecated
void *priv; void *priv;
#endif
int64_t pos; ///< byte position in stream, -1 if unknown int64_t pos; ///< byte position in stream, -1 if unknown
/** /**
...@@ -3413,10 +3424,14 @@ void avsubtitle_free(AVSubtitle *sub); ...@@ -3413,10 +3424,14 @@ void avsubtitle_free(AVSubtitle *sub);
* @{ * @{
*/ */
#if FF_API_DESTRUCT_PACKET
/** /**
* Default packet destructor. * Default packet destructor.
* @deprecated use the AVBuffer API instead
*/ */
attribute_deprecated
void av_destruct_packet(AVPacket *pkt); void av_destruct_packet(AVPacket *pkt);
#endif
/** /**
* Initialize optional fields of a packet with default values. * Initialize optional fields of a packet with default values.
...@@ -3454,6 +3469,21 @@ void av_shrink_packet(AVPacket *pkt, int size); ...@@ -3454,6 +3469,21 @@ void av_shrink_packet(AVPacket *pkt, int size);
*/ */
int av_grow_packet(AVPacket *pkt, int grow_by); 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 * @warning This is a hack - the packet memory allocation stuff is broken. The
* packet is allocated if it was not really allocated. * packet is allocated if it was not really allocated.
......
...@@ -22,9 +22,11 @@ ...@@ -22,9 +22,11 @@
#include <string.h> #include <string.h>
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/mem.h" #include "libavutil/mem.h"
#include "avcodec.h" #include "avcodec.h"
#if FF_API_DESTRUCT_PACKET
void av_destruct_packet(AVPacket *pkt) void av_destruct_packet(AVPacket *pkt)
{ {
av_free(pkt->data); av_free(pkt->data);
...@@ -32,6 +34,14 @@ void av_destruct_packet(AVPacket *pkt) ...@@ -32,6 +34,14 @@ void av_destruct_packet(AVPacket *pkt)
pkt->size = 0; 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) void av_init_packet(AVPacket *pkt)
{ {
pkt->pts = AV_NOPTS_VALUE; pkt->pts = AV_NOPTS_VALUE;
...@@ -41,27 +51,35 @@ void av_init_packet(AVPacket *pkt) ...@@ -41,27 +51,35 @@ void av_init_packet(AVPacket *pkt)
pkt->convergence_duration = 0; pkt->convergence_duration = 0;
pkt->flags = 0; pkt->flags = 0;
pkt->stream_index = 0; pkt->stream_index = 0;
#if FF_API_DESTRUCT_PACKET
pkt->destruct = NULL; pkt->destruct = NULL;
#endif
pkt->buf = NULL;
pkt->side_data = NULL; pkt->side_data = NULL;
pkt->side_data_elems = 0; pkt->side_data_elems = 0;
} }
int av_new_packet(AVPacket *pkt, int size) int av_new_packet(AVPacket *pkt, int size)
{ {
uint8_t *data = NULL; AVBufferRef *buf = NULL;
if ((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
if (data) { return AVERROR(EINVAL);
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
} else av_buffer_realloc(&buf, size + FF_INPUT_BUFFER_PADDING_SIZE);
size = 0; if (!buf)
return AVERROR(ENOMEM);
memset(buf->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
av_init_packet(pkt); av_init_packet(pkt);
pkt->data = data; pkt->buf = buf;
pkt->data = buf->data;
pkt->size = size; pkt->size = size;
pkt->destruct = av_destruct_packet; #if FF_API_DESTRUCT_PACKET
if (!data) pkt->destruct = dummy_destruct_packet;
return AVERROR(ENOMEM); #endif
return 0; return 0;
} }
...@@ -75,33 +93,71 @@ void av_shrink_packet(AVPacket *pkt, int size) ...@@ -75,33 +93,71 @@ void av_shrink_packet(AVPacket *pkt, int size)
int av_grow_packet(AVPacket *pkt, int grow_by) 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); av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
if (!pkt->size) if (!pkt->size)
return av_new_packet(pkt, grow_by); return av_new_packet(pkt, grow_by);
if ((unsigned)grow_by > if ((unsigned)grow_by >
INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE))
return -1; return -1;
new_ptr = av_realloc(pkt->data,
pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE); new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE;
if (!new_ptr) 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); return AVERROR(ENOMEM);
pkt->data = new_ptr; 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; pkt->size += grow_by;
memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
return 0; 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
pkt->destruct = dummy_destruct_packet;
#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 { \ do { \
void *data; \ void *data; \
if (padding) { \ if (padding) { \
if ((unsigned)(size) > \ if ((unsigned)(size) > \
(unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \
goto failed_alloc; \ goto failed_alloc; \
data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \ ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \
} else { \ } else { \
data = av_malloc(size); \ ALLOC(data, size); \
} \ } \
if (!data) \ if (!data) \
goto failed_alloc; \ goto failed_alloc; \
...@@ -116,30 +172,36 @@ int av_dup_packet(AVPacket *pkt) ...@@ -116,30 +172,36 @@ int av_dup_packet(AVPacket *pkt)
{ {
AVPacket tmp_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; tmp_pkt = *pkt;
pkt->data = NULL; pkt->data = NULL;
pkt->side_data = NULL; pkt->side_data = NULL;
DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1); DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1, ALLOC_BUF);
pkt->destruct = av_destruct_packet; #if FF_API_DESTRUCT_PACKET
pkt->destruct = dummy_destruct_packet;
#endif
if (pkt->side_data_elems) { if (pkt->side_data_elems) {
int i; int i;
DUP_DATA(pkt->side_data, tmp_pkt.side_data, 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, memset(pkt->side_data, 0,
pkt->side_data_elems * sizeof(*pkt->side_data)); 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, 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);
} }
} }
return 0; return 0;
failed_alloc: failed_alloc:
av_destruct_packet(pkt); av_free_packet(pkt);
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
...@@ -148,8 +210,13 @@ void av_free_packet(AVPacket *pkt) ...@@ -148,8 +210,13 @@ void av_free_packet(AVPacket *pkt)
if (pkt) { if (pkt) {
int i; 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(pkt);
pkt->destruct = NULL;
#endif
pkt->data = NULL; pkt->data = NULL;
pkt->size = 0; pkt->size = 0;
......
...@@ -887,13 +887,19 @@ int ff_alloc_packet(AVPacket *avpkt, int size) ...@@ -887,13 +887,19 @@ int ff_alloc_packet(AVPacket *avpkt, int size)
return AVERROR(EINVAL); return AVERROR(EINVAL);
if (avpkt->data) { if (avpkt->data) {
AVBufferRef *buf = avpkt->buf;
#if FF_API_DESTRUCT_PACKET
void *destruct = avpkt->destruct; void *destruct = avpkt->destruct;
#endif
if (avpkt->size < size) if (avpkt->size < size)
return AVERROR(EINVAL); return AVERROR(EINVAL);
av_init_packet(avpkt); av_init_packet(avpkt);
#if FF_API_DESTRUCT_PACKET
avpkt->destruct = destruct; avpkt->destruct = destruct;
#endif
avpkt->buf = buf;
avpkt->size = size; avpkt->size = size;
return 0; return 0;
} else { } else {
...@@ -1020,9 +1026,9 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, ...@@ -1020,9 +1026,9 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
} }
if (!user_packet && avpkt->size) { if (!user_packet && avpkt->size) {
uint8_t *new_data = av_realloc(avpkt->data, avpkt->size); ret = av_buffer_realloc(&avpkt->buf, avpkt->size);
if (new_data) if (ret >= 0)
avpkt->data = new_data; avpkt->data = avpkt->buf->data;
} }
avctx->frame_number++; avctx->frame_number++;
...@@ -1197,9 +1203,9 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, ...@@ -1197,9 +1203,9 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx,
avpkt->pts = avpkt->dts = frame->pts; avpkt->pts = avpkt->dts = frame->pts;
if (!user_packet && avpkt->size) { if (!user_packet && avpkt->size) {
uint8_t *new_data = av_realloc(avpkt->data, avpkt->size); ret = av_buffer_realloc(&avpkt->buf, avpkt->size);
if (new_data) if (ret >= 0)
avpkt->data = new_data; avpkt->data = avpkt->buf->data;
} }
avctx->frame_number++; avctx->frame_number++;
......
...@@ -100,5 +100,8 @@ ...@@ -100,5 +100,8 @@
#ifndef FF_API_DEINTERLACE #ifndef FF_API_DEINTERLACE
#define FF_API_DEINTERLACE (LIBAVCODEC_VERSION_MAJOR < 56) #define FF_API_DEINTERLACE (LIBAVCODEC_VERSION_MAJOR < 56)
#endif #endif
#ifndef FF_API_DESTRUCT_PACKET
#define FF_API_DESTRUCT_PACKET (LIBAVCODEC_VERSION_MAJOR < 56)
#endif
#endif /* AVCODEC_VERSION_H */ #endif /* AVCODEC_VERSION_H */
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#else #else
#include <linux/videodev2.h> #include <linux/videodev2.h>
#endif #endif
#include "libavutil/atomic.h"
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/log.h" #include "libavutil/log.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
...@@ -67,6 +69,7 @@ struct video_data { ...@@ -67,6 +69,7 @@ struct video_data {
int top_field_first; int top_field_first;
int buffers; int buffers;
volatile int buffers_queued;
void **buf_start; void **buf_start;
unsigned int *buf_len; unsigned int *buf_len;
char *standard; char *standard;
...@@ -79,6 +82,7 @@ struct video_data { ...@@ -79,6 +82,7 @@ struct video_data {
}; };
struct buff_data { struct buff_data {
struct video_data *s;
int index; int index;
int fd; int fd;
}; };
...@@ -405,14 +409,19 @@ static int mmap_init(AVFormatContext *ctx) ...@@ -405,14 +409,19 @@ static int mmap_init(AVFormatContext *ctx)
return 0; return 0;
} }
static void mmap_release_buffer(AVPacket *pkt) #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)
{ {
struct v4l2_buffer buf = { 0 }; struct v4l2_buffer buf = { 0 };
int res, fd; int res, fd;
struct buff_data *buf_descriptor = pkt->priv; struct buff_data *buf_descriptor = opaque;
struct video_data *s = buf_descriptor->s;
if (pkt->data == NULL)
return;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP; buf.memory = V4L2_MEMORY_MMAP;
...@@ -424,9 +433,7 @@ static void mmap_release_buffer(AVPacket *pkt) ...@@ -424,9 +433,7 @@ static void mmap_release_buffer(AVPacket *pkt)
if (res < 0) if (res < 0)
av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
strerror(errno)); strerror(errno));
avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
pkt->data = NULL;
pkt->size = 0;
} }
static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
...@@ -436,7 +443,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) ...@@ -436,7 +443,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.memory = V4L2_MEMORY_MMAP .memory = V4L2_MEMORY_MMAP
}; };
struct buff_data *buf_descriptor;
struct pollfd p = { .fd = s->fd, .events = POLLIN }; struct pollfd p = { .fd = s->fd, .events = POLLIN };
int res; int res;
...@@ -465,6 +471,9 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) ...@@ -465,6 +471,9 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n"); av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n");
return AVERROR(EINVAL); 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);
if (s->frame_size > 0 && buf.bytesused != s->frame_size) { if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
av_log(ctx, AV_LOG_ERROR, av_log(ctx, AV_LOG_ERROR,
...@@ -475,14 +484,35 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) ...@@ -475,14 +484,35 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
} }
/* Image is at s->buff_start[buf.index] */ /* Image is at s->buff_start[buf.index] */
pkt->data= s->buf_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);
res = 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 {
struct buff_data *buf_descriptor;
pkt->data = s->buf_start[buf.index];
pkt->size = buf.bytesused; pkt->size = buf.bytesused;
pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec; #if FF_API_DESTRUCT_PACKET
pkt->destruct = mmap_release_buffer; pkt->destruct = dummy_release_buffer;
#endif
buf_descriptor = av_malloc(sizeof(struct buff_data)); buf_descriptor = av_malloc(sizeof(struct buff_data));
if (buf_descriptor == NULL) { if (buf_descriptor == NULL) {
/* Something went wrong... Since av_malloc() failed, we cannot even /* Something went wrong... Since av_malloc() failed, we cannot even
* allocate a buffer for memcopying into it * allocate a buffer for memcpying into it
*/ */
av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
res = ioctl(s->fd, VIDIOC_QBUF, &buf); res = ioctl(s->fd, VIDIOC_QBUF, &buf);
...@@ -491,7 +521,16 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) ...@@ -491,7 +521,16 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
} }
buf_descriptor->fd = s->fd; buf_descriptor->fd = s->fd;
buf_descriptor->index = buf.index; buf_descriptor->index = buf.index;
pkt->priv = buf_descriptor; 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->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
return s->buf_len[buf.index]; return s->buf_len[buf.index];
} }
...@@ -517,6 +556,7 @@ static int mmap_start(AVFormatContext *ctx) ...@@ -517,6 +556,7 @@ static int mmap_start(AVFormatContext *ctx)
return AVERROR(errno); return AVERROR(errno);
} }
} }
s->buffers_queued = s->buffers;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
res = ioctl(s->fd, VIDIOC_STREAMON, &type); res = ioctl(s->fd, VIDIOC_STREAMON, &type);
...@@ -812,6 +852,10 @@ static int v4l2_read_close(AVFormatContext *s1) ...@@ -812,6 +852,10 @@ static int v4l2_read_close(AVFormatContext *s1)
{ {
struct video_data *s = s1->priv_data; 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); mmap_close(s);
close(s->fd); close(s->fd);
......
...@@ -1232,9 +1232,10 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk ...@@ -1232,9 +1232,10 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk
asf_st->ds_span); asf_st->ds_span);
} else { } else {
/* packet descrambling */ /* packet descrambling */
uint8_t *newdata = av_malloc(asf_st->pkt.size + AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size +
FF_INPUT_BUFFER_PADDING_SIZE); FF_INPUT_BUFFER_PADDING_SIZE);
if (newdata) { if (buf) {
uint8_t *newdata = buf->data;
int offset = 0; int offset = 0;
memset(newdata + asf_st->pkt.size, 0, memset(newdata + asf_st->pkt.size, 0,
FF_INPUT_BUFFER_PADDING_SIZE); FF_INPUT_BUFFER_PADDING_SIZE);
...@@ -1250,13 +1251,18 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk ...@@ -1250,13 +1251,18 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk
asf_st->ds_chunk_size); asf_st->ds_chunk_size);
offset += asf_st->ds_chunk_size; offset += asf_st->ds_chunk_size;
} }
av_free(asf_st->pkt.data); av_buffer_unref(&asf_st->pkt.buf);
asf_st->pkt.data = newdata; asf_st->pkt.buf = buf;
asf_st->pkt.data = buf->data;
} }
} }
} }
asf_st->frag_offset = 0; asf_st->frag_offset = 0;
*pkt = asf_st->pkt; *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.size = 0;
asf_st->pkt.data = 0; asf_st->pkt.data = 0;
asf_st->pkt.side_data_elems = 0; asf_st->pkt.side_data_elems = 0;
......
...@@ -158,9 +158,9 @@ ...@@ -158,9 +158,9 @@
* information will be in AVStream.time_base units, i.e. it has to be * information will be in AVStream.time_base units, i.e. it has to be
* multiplied by the timebase to convert them to seconds. * 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. * 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 * 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 * 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 * requires a longer lifetime, av_dup_packet() will make an av_malloc()ed copy
...@@ -1313,7 +1313,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt); ...@@ -1313,7 +1313,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt);
* omit invalid data between valid frames so as to give the decoder the maximum * omit invalid data between valid frames so as to give the decoder the maximum
* information possible for decoding. * 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 * av_read_frame() or until av_close_input_file(). Otherwise the packet is valid
* indefinitely. In both cases the packet must be freed with * indefinitely. In both cases the packet must be freed with
* av_free_packet when it is no longer needed. For video, the packet contains * av_free_packet when it is no longer needed. For video, the packet contains
...@@ -1461,10 +1461,10 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt); ...@@ -1461,10 +1461,10 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
* demuxer level. * demuxer level.
* *
* @param s media file handle * @param s media file handle
* @param pkt The packet containing the data to be written. Libavformat takes * @param pkt The packet containing the data to be written. pkt->buf must be set
* ownership of the data and will free it when it sees fit using the packet's * to a valid AVBufferRef describing the packet data. Libavformat takes
* @ref AVPacket.destruct "destruct" field. The caller must not access the data * ownership of this reference and will unref it when it sees fit. The caller
* after this function returns, as it may already be freed. * 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 * This can be NULL (at any time, not just at the end), to flush the
* interleaving queues. * interleaving queues.
* Packet's @ref AVPacket.stream_index "stream_index" field must be set to the * Packet's @ref AVPacket.stream_index "stream_index" field must be set to the
......
...@@ -980,7 +980,9 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -980,7 +980,9 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
AVIContext *avi = s->priv_data; AVIContext *avi = s->priv_data;
AVIOContext *pb = s->pb; AVIOContext *pb = s->pb;
int err; int err;
#if FF_API_DESTRUCT_PACKET
void* dstr; void* dstr;
#endif
if (CONFIG_DV_DEMUXER && avi->dv_demux) { if (CONFIG_DV_DEMUXER && avi->dv_demux) {
int size = avpriv_dv_get_packet(avi->dv_demux, pkt); int size = avpriv_dv_get_packet(avi->dv_demux, pkt);
...@@ -1081,10 +1083,16 @@ resync: ...@@ -1081,10 +1083,16 @@ resync:
} }
if (CONFIG_DV_DEMUXER && avi->dv_demux) { if (CONFIG_DV_DEMUXER && avi->dv_demux) {
AVBufferRef *avbuf = pkt->buf;
#if FF_API_DESTRUCT_PACKET
dstr = pkt->destruct; dstr = pkt->destruct;
#endif
size = avpriv_dv_produce_packet(avi->dv_demux, pkt, size = avpriv_dv_produce_packet(avi->dv_demux, pkt,
pkt->data, pkt->size); pkt->data, pkt->size);
#if FF_API_DESTRUCT_PACKET
pkt->destruct = dstr; pkt->destruct = dstr;
#endif
pkt->buf = avbuf;
pkt->flags |= AV_PKT_FLAG_KEY; pkt->flags |= AV_PKT_FLAG_KEY;
if (size < 0) if (size < 0)
av_free_packet(pkt); av_free_packet(pkt);
......
...@@ -32,7 +32,8 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) ...@@ -32,7 +32,8 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
{ {
const CodecMime *mime = ff_id3v2_mime_tags; const CodecMime *mime = ff_id3v2_mime_tags;
enum AVCodecID id = AV_CODEC_ID_NONE; 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; AVIOContext *pb = NULL;
AVStream *st; AVStream *st;
int type, width, height; int type, width, height;
...@@ -110,11 +111,11 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) ...@@ -110,11 +111,11 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
ret = AVERROR_INVALIDDATA; ret = AVERROR_INVALIDDATA;
goto fail; goto fail;
} }
if (!(data = av_malloc(len))) { if (!(data = av_buffer_alloc(len))) {
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto fail; goto fail;
} }
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"); av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n");
if (s->error_recognition & AV_EF_EXPLODE) if (s->error_recognition & AV_EF_EXPLODE)
ret = AVERROR(EIO); ret = AVERROR(EIO);
...@@ -128,9 +129,9 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) ...@@ -128,9 +129,9 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
} }
av_init_packet(&st->attached_pic); 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.size = len;
st->attached_pic.destruct = av_destruct_packet;
st->attached_pic.stream_index = st->index; st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY; st->attached_pic.flags |= AV_PKT_FLAG_KEY;
...@@ -148,8 +149,8 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) ...@@ -148,8 +149,8 @@ static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
return 0; return 0;
fail: fail:
av_buffer_unref(&data);
av_freep(&desc); av_freep(&desc);
av_freep(&data);
av_freep(&pb); av_freep(&pb);
return ret; return ret;
......
...@@ -420,7 +420,7 @@ finish: ...@@ -420,7 +420,7 @@ finish:
static void free_apic(void *obj) static void free_apic(void *obj)
{ {
ID3v2ExtraMetaAPIC *apic = obj; ID3v2ExtraMetaAPIC *apic = obj;
av_freep(&apic->data); av_buffer_unref(&apic->buf);
av_freep(&apic->description); av_freep(&apic->description);
av_freep(&apic); av_freep(&apic);
} }
...@@ -476,9 +476,8 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag ...@@ -476,9 +476,8 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag
goto fail; goto fail;
} }
apic->len = taglen; apic->buf = av_buffer_alloc(taglen);
apic->data = av_malloc(taglen); if (!apic->buf || avio_read(pb, apic->buf->data, taglen) != taglen)
if (!apic->data || avio_read(pb, apic->data, taglen) != taglen)
goto fail; goto fail;
new_extra->tag = "APIC"; new_extra->tag = "APIC";
...@@ -734,14 +733,13 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) ...@@ -734,14 +733,13 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
av_dict_set(&st->metadata, "comment", apic->type, 0); av_dict_set(&st->metadata, "comment", apic->type, 0);
av_init_packet(&st->attached_pic); av_init_packet(&st->attached_pic);
st->attached_pic.data = apic->data; st->attached_pic.buf = apic->buf;
st->attached_pic.size = apic->len; st->attached_pic.data = apic->buf->data;
st->attached_pic.destruct = av_destruct_packet; st->attached_pic.size = apic->buf->size;
st->attached_pic.stream_index = st->index; st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY; st->attached_pic.flags |= AV_PKT_FLAG_KEY;
apic->data = NULL; apic->buf = NULL;
apic->len = 0;
} }
return 0; return 0;
......
...@@ -67,8 +67,7 @@ typedef struct ID3v2ExtraMetaGEOB { ...@@ -67,8 +67,7 @@ typedef struct ID3v2ExtraMetaGEOB {
} ID3v2ExtraMetaGEOB; } ID3v2ExtraMetaGEOB;
typedef struct ID3v2ExtraMetaAPIC { typedef struct ID3v2ExtraMetaAPIC {
uint8_t *data; AVBufferRef *buf;
int len;
const char *type; const char *type;
uint8_t *description; uint8_t *description;
enum AVCodecID id; enum AVCodecID id;
......
...@@ -1107,7 +1107,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, ...@@ -1107,7 +1107,8 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska,
AVPacket *pkt, uint64_t display_duration) 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++); for (; *ptr!=',' && ptr<end-1; ptr++);
if (*ptr == ',') if (*ptr == ',')
layer = ++ptr; layer = ++ptr;
...@@ -1125,13 +1126,14 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, ...@@ -1125,13 +1126,14 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska,
es = ec/ 100; ec -= 100*es; es = ec/ 100; ec -= 100*es;
*ptr++ = '\0'; *ptr++ = '\0';
len = 50 + end-ptr + FF_INPUT_BUFFER_PADDING_SIZE; len = 50 + end-ptr + FF_INPUT_BUFFER_PADDING_SIZE;
if (!(line = av_malloc(len))) if (!(line = av_buffer_alloc(len)))
return; 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); layer, sh, sm, ss, sc, eh, em, es, ec, ptr);
av_free(pkt->data); av_buffer_unref(&pkt->buf);
pkt->data = line; pkt->buf = line;
pkt->size = strlen(line); pkt->data = line->data;
pkt->size = strlen(line->data);
} }
} }
......
...@@ -90,7 +90,6 @@ typedef struct MatroskaMuxContext { ...@@ -90,7 +90,6 @@ typedef struct MatroskaMuxContext {
mkv_cues *cues; mkv_cues *cues;
mkv_track *tracks; mkv_track *tracks;
unsigned int audio_buffer_size;
AVPacket cur_audio_pkt; AVPacket cur_audio_pkt;
int have_attachments; int have_attachments;
...@@ -969,7 +968,6 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -969,7 +968,6 @@ static int mkv_write_header(AVFormatContext *s)
av_init_packet(&mkv->cur_audio_pkt); av_init_packet(&mkv->cur_audio_pkt);
mkv->cur_audio_pkt.size = 0; mkv->cur_audio_pkt.size = 0;
mkv->audio_buffer_size = 0;
avio_flush(pb); avio_flush(pb);
return 0; return 0;
...@@ -1180,19 +1178,6 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) ...@@ -1180,19 +1178,6 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
return 0; 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) static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
{ {
MatroskaMuxContext *mkv = s->priv_data; MatroskaMuxContext *mkv = s->priv_data;
...@@ -1219,7 +1204,7 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1219,7 +1204,7 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
// check if we have an audio packet cached // check if we have an audio packet cached
if (mkv->cur_audio_pkt.size > 0) { if (mkv->cur_audio_pkt.size > 0) {
ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); 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) { if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
return ret; return ret;
...@@ -1228,9 +1213,11 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1228,9 +1213,11 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
// buffer an audio packet to ensure the packet containing the video // buffer an audio packet to ensure the packet containing the video
// keyframe's timecode is contained in the same cluster for WebM // keyframe's timecode is contained in the same cluster for WebM
if (codec->codec_type == AVMEDIA_TYPE_AUDIO) if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
ret = mkv_copy_packet(mkv, pkt); mkv->cur_audio_pkt = *pkt;
else 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); ret = mkv_write_packet_internal(s, pkt);
return ret; return ret;
} }
...@@ -1245,7 +1232,7 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -1245,7 +1232,7 @@ static int mkv_write_trailer(AVFormatContext *s)
// check if we have an audio packet cached // check if we have an audio packet cached
if (mkv->cur_audio_pkt.size > 0) { if (mkv->cur_audio_pkt.size > 0) {
ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); 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) { if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
return ret; return ret;
...@@ -1282,7 +1269,6 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -1282,7 +1269,6 @@ static int mkv_write_trailer(AVFormatContext *s)
av_free(mkv->tracks); av_free(mkv->tracks);
av_freep(&mkv->cues->entries); av_freep(&mkv->cues->entries);
av_freep(&mkv->cues); av_freep(&mkv->cues);
av_destruct_packet(&mkv->cur_audio_pkt);
return 0; return 0;
} }
......
...@@ -343,7 +343,11 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -343,7 +343,11 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
pktl->pkt = *pkt; 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) if (mp3->queue_end)
mp3->queue_end->next = pktl; mp3->queue_end->next = pktl;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "libavutil/buffer.h"
#include "libavutil/crc.h" #include "libavutil/crc.h"
#include "libavutil/intreadwrite.h" #include "libavutil/intreadwrite.h"
#include "libavutil/log.h" #include "libavutil/log.h"
...@@ -173,7 +174,7 @@ typedef struct PESContext { ...@@ -173,7 +174,7 @@ typedef struct PESContext {
int64_t pts, dts; int64_t pts, dts;
int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */ int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */
uint8_t header[MAX_PES_HEADER_SIZE]; uint8_t header[MAX_PES_HEADER_SIZE];
uint8_t *buffer; AVBufferRef *buffer;
SLConfigDescr sl; SLConfigDescr sl;
} PESContext; } PESContext;
...@@ -364,7 +365,7 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) ...@@ -364,7 +365,7 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
av_freep(&filter->u.section_filter.section_buf); av_freep(&filter->u.section_filter.section_buf);
else if (filter->type == MPEGTS_PES) { else if (filter->type == MPEGTS_PES) {
PESContext *pes = filter->u.pes_filter.opaque; PESContext *pes = filter->u.pes_filter.opaque;
av_freep(&pes->buffer); av_buffer_unref(&pes->buffer);
/* referenced private data will be freed later in /* referenced private data will be freed later in
* avformat_close_input */ * avformat_close_input */
if (!((PESContext *)filter->u.pes_filter.opaque)->st) { if (!((PESContext *)filter->u.pes_filter.opaque)->st) {
...@@ -635,8 +636,8 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) ...@@ -635,8 +636,8 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
{ {
av_init_packet(pkt); av_init_packet(pkt);
pkt->destruct = av_destruct_packet; pkt->buf = pes->buffer;
pkt->data = pes->buffer; pkt->data = pes->buffer->data;
pkt->size = pes->data_index; pkt->size = pes->data_index;
if(pes->total_size != MAX_PES_PAYLOAD && if(pes->total_size != MAX_PES_PAYLOAD &&
...@@ -793,7 +794,8 @@ static int mpegts_push_data(MpegTSFilter *filter, ...@@ -793,7 +794,8 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes->total_size = MAX_PES_PAYLOAD; pes->total_size = MAX_PES_PAYLOAD;
/* allocate pes buffer */ /* 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) if (!pes->buffer)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
...@@ -895,7 +897,7 @@ static int mpegts_push_data(MpegTSFilter *filter, ...@@ -895,7 +897,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
if (pes->data_index > 0 && pes->data_index+buf_size > pes->total_size) { if (pes->data_index > 0 && pes->data_index+buf_size > pes->total_size) {
new_pes_packet(pes, ts->pkt); new_pes_packet(pes, ts->pkt);
pes->total_size = MAX_PES_PAYLOAD; 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) if (!pes->buffer)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
ts->stop_parse = 1; ts->stop_parse = 1;
...@@ -904,7 +906,7 @@ static int mpegts_push_data(MpegTSFilter *filter, ...@@ -904,7 +906,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
// not sure if this is legal in ts but see issue #2392 // not sure if this is legal in ts but see issue #2392
buf_size = pes->total_size; 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; pes->data_index += buf_size;
} }
buf_size = 0; buf_size = 0;
...@@ -1781,7 +1783,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) ...@@ -1781,7 +1783,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
if (ts->pids[i]) { if (ts->pids[i]) {
if (ts->pids[i]->type == MPEGTS_PES) { if (ts->pids[i]->type == MPEGTS_PES) {
PESContext *pes = ts->pids[i]->u.pes_filter.opaque; PESContext *pes = ts->pids[i]->u.pes_filter.opaque;
av_freep(&pes->buffer); av_buffer_unref(&pes->buffer);
pes->data_index = 0; pes->data_index = 0;
pes->state = MPEGTS_SKIP; /* skip until pes header */ pes->state = MPEGTS_SKIP; /* skip until pes header */
} }
......
...@@ -420,7 +420,10 @@ void ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, ...@@ -420,7 +420,10 @@ void ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
this_pktl = av_mallocz(sizeof(AVPacketList)); this_pktl = av_mallocz(sizeof(AVPacketList));
this_pktl->pkt = *pkt; this_pktl->pkt = *pkt;
#if FF_API_DESTRUCT_PACKET
pkt->destruct = NULL; // do not free original but only the copy 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-alloced memory av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-alloced memory
if (s->streams[pkt->stream_index]->last_in_packet_buffer) { if (s->streams[pkt->stream_index]->last_in_packet_buffer) {
......
...@@ -168,7 +168,10 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -168,7 +168,10 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->pts = pkt->dts = mxg->dts; pkt->pts = pkt->dts = mxg->dts;
pkt->stream_index = 0; pkt->stream_index = 0;
#if FF_API_DESTRUCT_PACKET
pkt->destruct = NULL; pkt->destruct = NULL;
#endif
pkt->buf = NULL;
pkt->size = mxg->buffer_ptr - mxg->soi_ptr; pkt->size = mxg->buffer_ptr - mxg->soi_ptr;
pkt->data = mxg->soi_ptr; pkt->data = mxg->soi_ptr;
...@@ -206,7 +209,10 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -206,7 +209,10 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt)
/* time (GMT) of first sample in usec since 1970, little-endian */ /* time (GMT) of first sample in usec since 1970, little-endian */
pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8); pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8);
pkt->stream_index = 1; pkt->stream_index = 1;
#if FF_API_DESTRUCT_PACKET
pkt->destruct = NULL; pkt->destruct = NULL;
#endif
pkt->buf = NULL;
pkt->size = size - 14; pkt->size = size - 14;
pkt->data = startmarker_ptr + 16; pkt->data = startmarker_ptr + 16;
......
...@@ -201,6 +201,10 @@ static int str_read_packet(AVFormatContext *s, ...@@ -201,6 +201,10 @@ static int str_read_packet(AVFormatContext *s,
*ret_pkt = *pkt; *ret_pkt = *pkt;
pkt->data= NULL; pkt->data= NULL;
pkt->size= -1; pkt->size= -1;
pkt->buf = NULL;
#if FF_API_DESTRUCT_PACKET
pkt->destruct = NULL;
#endif
return 0; return 0;
} }
......
...@@ -678,6 +678,10 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, ...@@ -678,6 +678,10 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
*pkt= vst->pkt; *pkt= vst->pkt;
vst->pkt.data= NULL; vst->pkt.data= NULL;
vst->pkt.size= 0; 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 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, memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,
vst->videobufpos - 1 - 8*vst->slices); vst->videobufpos - 1 - 8*vst->slices);
......
...@@ -864,11 +864,15 @@ int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, ...@@ -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 ff_rtp_finalize_packet(AVPacket *pkt, AVIOContext **dyn_buf, int stream_idx)
{ {
int ret;
av_init_packet(pkt); av_init_packet(pkt);
pkt->size = avio_close_dyn_buf(*dyn_buf, &pkt->data); pkt->size = avio_close_dyn_buf(*dyn_buf, &pkt->data);
pkt->stream_index = stream_idx; 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; return pkt->size;
} }
...@@ -186,12 +186,14 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, ...@@ -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); memcpy(qt->pkt.data + qt->pkt.size, buf + avio_tell(&pb), alen);
qt->pkt.size += alen; qt->pkt.size += alen;
if (has_marker_bit) { 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.size = 0;
qt->pkt.data = NULL; qt->pkt.data = NULL;
pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0; pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0;
pkt->stream_index = st->index; pkt->stream_index = st->index;
pkt->destruct = av_destruct_packet;
memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
return 0; return 0;
} }
......
...@@ -464,16 +464,20 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, ...@@ -464,16 +464,20 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
return &pktl->pkt; return &pktl->pkt;
} }
static void queue_attached_pictures(AVFormatContext *s) static int queue_attached_pictures(AVFormatContext *s)
{ {
int i; int i;
for (i = 0; i < s->nb_streams; i++) for (i = 0; i < s->nb_streams; i++)
if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC &&
s->streams[i]->discard < AVDISCARD_ALL) { s->streams[i]->discard < AVDISCARD_ALL) {
AVPacket copy = s->streams[i]->attached_pic; 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, &copy, &s->raw_packet_buffer_end); add_to_pktbuf(&s->raw_packet_buffer, &copy, &s->raw_packet_buffer_end);
} }
return 0;
} }
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options) int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
...@@ -535,7 +539,8 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma ...@@ -535,7 +539,8 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
goto fail; goto fail;
ff_id3v2_free_extra_meta(&id3v2_extra_meta); ff_id3v2_free_extra_meta(&id3v2_extra_meta);
queue_attached_pictures(s); if ((ret = queue_attached_pictures(s)) < 0)
goto fail;
if (s->pb && !s->data_offset) if (s->pb && !s->data_offset)
s->data_offset = avio_tell(s->pb); s->data_offset = avio_tell(s->pb);
...@@ -1074,8 +1079,12 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) ...@@ -1074,8 +1079,12 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
} }
if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) { 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; out_pkt.destruct = pkt->destruct;
pkt->destruct = NULL; pkt->destruct = NULL;
#endif
} }
if ((ret = av_dup_packet(&out_pkt)) < 0) if ((ret = av_dup_packet(&out_pkt)) < 0)
goto fail; goto fail;
...@@ -1735,7 +1744,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f ...@@ -1735,7 +1744,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); int ret = seek_frame_internal(s, stream_index, timestamp, flags);
if (ret >= 0) if (ret >= 0)
queue_attached_pictures(s); ret = queue_attached_pictures(s);
return ret; return ret;
} }
...@@ -1751,7 +1760,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int ...@@ -1751,7 +1760,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); ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
if (ret >= 0) if (ret >= 0)
queue_attached_pictures(s); ret = queue_attached_pictures(s);
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment