mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
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>
This commit is contained in:
commit
2653e12520
1
ffmpeg.c
1
ffmpeg.c
@ -570,6 +570,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
|
|||||||
memcpy(t, new_pkt.data, new_pkt.size);
|
memcpy(t, new_pkt.data, new_pkt.size);
|
||||||
memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
new_pkt.data = t;
|
new_pkt.data = t;
|
||||||
|
new_pkt.buf = NULL;
|
||||||
a = 1;
|
a = 1;
|
||||||
} else
|
} else
|
||||||
a = AVERROR(ENOMEM);
|
a = AVERROR(ENOMEM);
|
||||||
|
@ -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/channel_layout.h"
|
#include "libavutil/channel_layout.h"
|
||||||
#include "libavutil/dict.h"
|
#include "libavutil/dict.h"
|
||||||
@ -1009,17 +1010,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.
|
||||||
@ -1059,8 +1066,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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3776,10 +3787,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.
|
||||||
@ -3817,6 +3832,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,6 +22,7 @@
|
|||||||
#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"
|
||||||
#include "bytestream.h"
|
#include "bytestream.h"
|
||||||
@ -36,6 +37,7 @@ void ff_packet_free_side_data(AVPacket *pkt)
|
|||||||
pkt->side_data_elems = 0;
|
pkt->side_data_elems = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
@ -43,6 +45,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;
|
||||||
@ -52,27 +62,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,33 +104,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) {
|
||||||
return AVERROR(ENOMEM);
|
int ret = av_buffer_realloc(&pkt->buf, new_size);
|
||||||
pkt->data = new_ptr;
|
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;
|
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; \
|
||||||
@ -124,31 +180,33 @@ int av_grow_packet(AVPacket *pkt, int grow_by)
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* Makes duplicates of data, side_data, but does not copy any other fields */
|
/* 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;
|
pkt->data = NULL;
|
||||||
dst->side_data = NULL;
|
pkt->side_data = NULL;
|
||||||
DUP_DATA(dst->data, src->data, dst->size, 1);
|
DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF);
|
||||||
dst->destruct = av_destruct_packet;
|
#if FF_API_DESTRUCT_PACKET
|
||||||
|
pkt->destruct = dummy_destruct_packet;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dst->side_data_elems) {
|
if (pkt->side_data_elems) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DUP_DATA(dst->side_data, src->side_data,
|
DUP_DATA(pkt->side_data, src->side_data,
|
||||||
dst->side_data_elems * sizeof(*dst->side_data), 0);
|
pkt->side_data_elems * sizeof(*pkt->side_data), 0, ALLOC_MALLOC);
|
||||||
memset(dst->side_data, 0,
|
memset(pkt->side_data, 0,
|
||||||
dst->side_data_elems * sizeof(*dst->side_data));
|
pkt->side_data_elems * sizeof(*pkt->side_data));
|
||||||
for (i = 0; i < dst->side_data_elems; i++) {
|
for (i = 0; i < pkt->side_data_elems; i++) {
|
||||||
DUP_DATA(dst->side_data[i].data, src->side_data[i].data,
|
DUP_DATA(pkt->side_data[i].data, src->side_data[i].data,
|
||||||
src->side_data[i].size, 1);
|
src->side_data[i].size, 1, ALLOC_MALLOC);
|
||||||
dst->side_data[i].size = src->side_data[i].size;
|
pkt->side_data[i].size = src->side_data[i].size;
|
||||||
dst->side_data[i].type = src->side_data[i].type;
|
pkt->side_data[i].type = src->side_data[i].type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_alloc:
|
failed_alloc:
|
||||||
av_destruct_packet(dst);
|
av_destruct_packet(pkt);
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +214,11 @@ 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;
|
||||||
return copy_packet_data(pkt, &tmp_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)
|
int av_copy_packet(AVPacket *dst, AVPacket *src)
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
dst->buf = av_buffer_ref(src->buf);
|
||||||
return copy_packet_data(dst, src);
|
return copy_packet_data(dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +237,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;
|
||||||
|
|
||||||
@ -230,6 +298,7 @@ uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
|
|||||||
|
|
||||||
int av_packet_merge_side_data(AVPacket *pkt){
|
int av_packet_merge_side_data(AVPacket *pkt){
|
||||||
if(pkt->side_data_elems){
|
if(pkt->side_data_elems){
|
||||||
|
AVBufferRef *buf;
|
||||||
int i;
|
int i;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE;
|
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)
|
if (size > INT_MAX)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
p = av_malloc(size);
|
buf = av_buffer_alloc(size);
|
||||||
if (!p)
|
if (!buf)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
pkt->data = p;
|
pkt->buf = buf;
|
||||||
pkt->destruct = av_destruct_packet;
|
pkt->data = p = buf->data;
|
||||||
|
#if FF_API_DESTRUCT_PACKET
|
||||||
|
pkt->destruct = dummy_destruct_packet;
|
||||||
|
#endif
|
||||||
pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE;
|
pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE;
|
||||||
bytestream_put_buffer(&p, old.data, old.size);
|
bytestream_put_buffer(&p, old.data, old.size);
|
||||||
for (i=old.side_data_elems-1; i>=0; i--) {
|
for (i=old.side_data_elems-1; i>=0; i--) {
|
||||||
|
@ -1162,7 +1162,10 @@ int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "User packet is too small (%d < %d)\n", 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);
|
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 {
|
||||||
@ -1318,6 +1324,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
|
|||||||
avpkt->size = user_pkt.size;
|
avpkt->size = user_pkt.size;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
avpkt->buf = user_pkt.buf;
|
||||||
avpkt->data = user_pkt.data;
|
avpkt->data = user_pkt.data;
|
||||||
avpkt->destruct = user_pkt.destruct;
|
avpkt->destruct = user_pkt.destruct;
|
||||||
} else {
|
} else {
|
||||||
@ -1329,9 +1336,9 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
|
|||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (needs_realloc && avpkt->data) {
|
if (needs_realloc && avpkt->data) {
|
||||||
uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
|
ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
if (new_data)
|
if (ret >= 0)
|
||||||
avpkt->data = new_data;
|
avpkt->data = avpkt->buf->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
avctx->frame_number++;
|
avctx->frame_number++;
|
||||||
@ -1515,6 +1522,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx,
|
|||||||
avpkt->size = user_pkt.size;
|
avpkt->size = user_pkt.size;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
avpkt->buf = user_pkt.buf;
|
||||||
avpkt->data = user_pkt.data;
|
avpkt->data = user_pkt.data;
|
||||||
avpkt->destruct = user_pkt.destruct;
|
avpkt->destruct = user_pkt.destruct;
|
||||||
} else {
|
} else {
|
||||||
@ -1530,11 +1538,10 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx,
|
|||||||
else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY))
|
else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY))
|
||||||
avpkt->pts = avpkt->dts = frame->pts;
|
avpkt->pts = avpkt->dts = frame->pts;
|
||||||
|
|
||||||
if (needs_realloc && avpkt->data &&
|
if (needs_realloc && avpkt->data) {
|
||||||
avpkt->destruct == av_destruct_packet) {
|
ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
|
if (ret >= 0)
|
||||||
if (new_data)
|
avpkt->data = avpkt->buf->data;
|
||||||
avpkt->data = new_data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
avctx->frame_number++;
|
avctx->frame_number++;
|
||||||
|
@ -109,5 +109,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 */
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "libavutil/atomic.h"
|
||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
#include "libavutil/log.h"
|
#include "libavutil/log.h"
|
||||||
@ -109,9 +110,9 @@ struct video_data {
|
|||||||
int64_t last_time_m;
|
int64_t last_time_m;
|
||||||
|
|
||||||
int buffers;
|
int buffers;
|
||||||
|
volatile int buffers_queued;
|
||||||
void **buf_start;
|
void **buf_start;
|
||||||
unsigned int *buf_len;
|
unsigned int *buf_len;
|
||||||
int *buf_dequeued;
|
|
||||||
char *standard;
|
char *standard;
|
||||||
v4l2_std_id std_id;
|
v4l2_std_id std_id;
|
||||||
int channel;
|
int channel;
|
||||||
@ -122,9 +123,9 @@ struct video_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct buff_data {
|
struct buff_data {
|
||||||
|
struct video_data *s;
|
||||||
int index;
|
int index;
|
||||||
int fd;
|
int fd;
|
||||||
int *buf_dequeued;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fmt_map {
|
struct fmt_map {
|
||||||
@ -438,11 +439,6 @@ static int mmap_init(AVFormatContext *ctx)
|
|||||||
av_free(s->buf_start);
|
av_free(s->buf_start);
|
||||||
return AVERROR(ENOMEM);
|
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++) {
|
for (i = 0; i < req.count; i++) {
|
||||||
struct v4l2_buffer buf = {
|
struct v4l2_buffer buf = {
|
||||||
@ -477,40 +473,33 @@ static int mmap_init(AVFormatContext *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enqueue_buffer(int fd, int index)
|
#if FF_API_DESTRUCT_PACKET
|
||||||
|
static void dummy_release_buffer(AVPacket *pkt)
|
||||||
{
|
{
|
||||||
int res;
|
av_assert0(0);
|
||||||
struct v4l2_buffer buf = { 0 };
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
static void mmap_release_buffer(void *opaque, uint8_t *data)
|
||||||
|
{
|
||||||
|
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.memory = V4L2_MEMORY_MMAP;
|
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) {
|
if (v4l2_ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
|
||||||
res = AVERROR(errno);
|
res = AVERROR(errno);
|
||||||
av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
|
av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
|
||||||
return res;
|
av_err2str(res));
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mmap_release_buffer(AVPacket *pkt)
|
avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
|
#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,
|
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||||
.memory = V4L2_MEMORY_MMAP
|
.memory = V4L2_MEMORY_MMAP
|
||||||
};
|
};
|
||||||
struct buff_data *buf_descriptor;
|
int res;
|
||||||
int res, i, free_buffers;
|
|
||||||
|
|
||||||
/* FIXME: Some special treatment might be needed in case of loss of signal... */
|
/* 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));
|
while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN) {
|
||||||
|
pkt->size = 0;
|
||||||
return AVERROR(EAGAIN);
|
return AVERROR(EAGAIN);
|
||||||
|
}
|
||||||
res = AVERROR(errno);
|
res = AVERROR(errno);
|
||||||
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", av_err2str(res));
|
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", av_err2str(res));
|
||||||
return 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");
|
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);
|
||||||
|
|
||||||
/* CPIA is a compressed format and we don't know the exact number of bytes
|
/* 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.
|
* 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,
|
av_log(ctx, AV_LOG_ERROR,
|
||||||
"The v4l2 frame is %d bytes, but %d bytes are expected\n",
|
"The v4l2 frame is %d bytes, but %d bytes are expected\n",
|
||||||
buf.bytesused, s->frame_size);
|
buf.bytesused, s->frame_size);
|
||||||
enqueue_buffer(s->fd, buf.index);
|
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_descriptor = av_malloc(sizeof(struct buff_data));
|
/* Image is at s->buff_start[buf.index] */
|
||||||
if (buf_descriptor == NULL) {
|
if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) {
|
||||||
/* Something went wrong... Since av_malloc() failed, we cannot even
|
/* when we start getting low on queued buffers, fallback to copying data */
|
||||||
* allocate a buffer for memcopying into it
|
res = av_new_packet(pkt, buf.bytesused);
|
||||||
*/
|
if (res < 0) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
|
av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\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);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);
|
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 {
|
} else {
|
||||||
/* Image is at s->buff_start[buf.index] */
|
struct buff_data *buf_descriptor;
|
||||||
pkt->data = s->buf_start[buf.index];
|
|
||||||
|
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->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;
|
pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
|
||||||
res = convert_timestamp(ctx, &pkt->pts);
|
convert_timestamp(ctx, &pkt->pts);
|
||||||
if (res < 0) {
|
|
||||||
mmap_release_buffer(pkt);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s->buf_len[buf.index];
|
return s->buf_len[buf.index];
|
||||||
}
|
}
|
||||||
@ -675,6 +676,7 @@ static int mmap_start(AVFormatContext *ctx)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s->buffers_queued = s->buffers;
|
||||||
|
|
||||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) {
|
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_start);
|
||||||
av_free(s->buf_len);
|
av_free(s->buf_len);
|
||||||
av_free(s->buf_dequeued);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int v4l2_set_parameters(AVFormatContext *s1)
|
static int v4l2_set_parameters(AVFormatContext *s1)
|
||||||
@ -1003,8 +1004,6 @@ static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
|
|||||||
int res;
|
int res;
|
||||||
|
|
||||||
av_init_packet(pkt);
|
av_init_packet(pkt);
|
||||||
pkt->data = NULL;
|
|
||||||
pkt->size = 0;
|
|
||||||
if ((res = mmap_read_frame(s1, pkt)) < 0) {
|
if ((res = mmap_read_frame(s1, pkt)) < 0) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -1021,6 +1020,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);
|
||||||
|
|
||||||
v4l2_close(s->fd);
|
v4l2_close(s->fd);
|
||||||
|
@ -1282,9 +1282,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);
|
||||||
@ -1300,13 +1301,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 @@
|
|||||||
* 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
|
||||||
@ -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
|
* 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
|
||||||
@ -1777,10 +1777,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
|
||||||
@ -2125,7 +2125,7 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea
|
|||||||
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
|
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
|
||||||
const char *spec);
|
const char *spec);
|
||||||
|
|
||||||
void avformat_queue_attached_pictures(AVFormatContext *s);
|
int avformat_queue_attached_pictures(AVFormatContext *s);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1057,7 +1057,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);
|
||||||
@ -1162,10 +1164,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->pos);
|
pkt->data, pkt->size, pkt->pos);
|
||||||
|
#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);
|
||||||
|
@ -34,7 +34,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,10 +111,10 @@ 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))) {
|
||||||
RETURN_ERROR(AVERROR(ENOMEM));
|
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");
|
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);
|
||||||
@ -126,9 +127,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;
|
||||||
|
|
||||||
@ -146,8 +147,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;
|
||||||
|
|
||||||
|
@ -433,7 +433,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);
|
||||||
}
|
}
|
||||||
@ -489,9 +489,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 || !taglen || avio_read(pb, apic->buf->data, taglen) != taglen)
|
||||||
if (!apic->data || !apic->len || avio_read(pb, apic->data, taglen) != taglen)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
new_extra->tag = "APIC";
|
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_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 {
|
|||||||
} 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;
|
||||||
|
@ -1198,7 +1198,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 == ',')
|
||||||
ptr++;
|
ptr++;
|
||||||
@ -1217,13 +1218,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,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;
|
||||||
@ -1043,7 +1042,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;
|
|
||||||
mkv->cluster_pos = -1;
|
mkv->cluster_pos = -1;
|
||||||
|
|
||||||
avio_flush(pb);
|
avio_flush(pb);
|
||||||
@ -1262,19 +1260,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;
|
||||||
@ -1301,7 +1286,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;
|
||||||
@ -1310,9 +1295,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;
|
||||||
}
|
}
|
||||||
@ -1327,7 +1314,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;
|
||||||
@ -1364,7 +1351,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;
|
||||||
}
|
}
|
||||||
|
@ -422,7 +422,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 @@
|
|||||||
* 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"
|
||||||
@ -176,7 +177,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;
|
||||||
|
|
||||||
@ -406,7 +407,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) {
|
||||||
@ -703,8 +704,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 &&
|
||||||
@ -869,7 +870,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);
|
||||||
|
|
||||||
@ -971,7 +973,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;
|
||||||
@ -980,7 +982,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;
|
||||||
@ -1880,7 +1882,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 */
|
||||||
}
|
}
|
||||||
|
@ -540,7 +540,10 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
|
|||||||
if (!this_pktl)
|
if (!this_pktl)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
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-allocated memory
|
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) {
|
if (s->streams[pkt->stream_index]->last_in_packet_buffer) {
|
||||||
|
@ -170,7 +170,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;
|
||||||
|
|
||||||
@ -208,7 +211,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;
|
||||||
|
|
||||||
|
@ -235,6 +235,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,6 +730,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,
|
|||||||
|
|
||||||
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,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "subtitles.h"
|
#include "subtitles.h"
|
||||||
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
|
|
||||||
AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
|
AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
|
||||||
@ -49,7 +50,6 @@ AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
|
|||||||
sub = &subs[q->nb_subs++];
|
sub = &subs[q->nb_subs++];
|
||||||
if (av_new_packet(sub, len) < 0)
|
if (av_new_packet(sub, len) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
sub->destruct = NULL;
|
|
||||||
sub->flags |= AV_PKT_FLAG_KEY;
|
sub->flags |= AV_PKT_FLAG_KEY;
|
||||||
sub->pts = sub->dts = 0;
|
sub->pts = sub->dts = 0;
|
||||||
memcpy(sub->data, event, len);
|
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)
|
if (q->current_sub_idx == q->nb_subs)
|
||||||
return AVERROR_EOF;
|
return AVERROR_EOF;
|
||||||
*pkt = *sub;
|
av_copy_packet(pkt, sub);
|
||||||
|
|
||||||
pkt->dts = pkt->pts;
|
pkt->dts = pkt->pts;
|
||||||
q->current_sub_idx++;
|
q->current_sub_idx++;
|
||||||
return 0;
|
return 0;
|
||||||
@ -135,7 +136,7 @@ void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < q->nb_subs; 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);
|
av_freep(&q->subs);
|
||||||
q->nb_subs = q->allocated_size = q->current_sub_idx = 0;
|
q->nb_subs = q->allocated_size = q->current_sub_idx = 0;
|
||||||
}
|
}
|
||||||
|
@ -555,16 +555,20 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
|
|||||||
return &pktl->pkt;
|
return &pktl->pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avformat_queue_attached_pictures(AVFormatContext *s)
|
int avformat_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, ©, &s->raw_packet_buffer_end);
|
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)
|
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);
|
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)
|
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset)
|
||||||
s->data_offset = avio_tell(s->pb);
|
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);
|
compute_pkt_fields(s, st, st->parser, &out_pkt);
|
||||||
|
|
||||||
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;
|
||||||
@ -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);
|
int ret = seek_frame_internal(s, stream_index, timestamp, flags);
|
||||||
|
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
avformat_queue_attached_pictures(s);
|
ret = avformat_queue_attached_pictures(s);
|
||||||
|
|
||||||
return ret;
|
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);
|
ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
|
||||||
|
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
avformat_queue_attached_pictures(s);
|
ret = avformat_queue_attached_pictures(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user