* 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>tags/n2.0
| @@ -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. | |||||
| * If it is set, the packet data is dynamically allocated and is valid | |||||
| * indefinitely until av_free_packet() is called (which in turn calls the | |||||
| * destruct callback to free the data). If destruct is not set, the packet data | |||||
| * is typically backed by some static buffer somewhere and is only valid for a | |||||
| * limited time (e.g. until the next read call when demuxing). | |||||
| * The semantics of data ownership depends on the buf or destruct (deprecated) | |||||
| * fields. If either is set, the packet data is dynamically allocated and is | |||||
| * valid indefinitely until av_free_packet() is called (which in turn calls | |||||
| * av_buffer_unref()/the destruct callback to free the data). If neither is set, | |||||
| * the packet data is typically backed by some static buffer somewhere and is | |||||
| * only valid for a limited time (e.g. until the next read call when demuxing). | |||||
| * | * | ||||
| * The side data is always allocated with av_malloc() and is freed in | * 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; | |||||
| if ((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) | |||||
| data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (data) { | |||||
| memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| } else | |||||
| size = 0; | |||||
| AVBufferRef *buf = NULL; | |||||
| if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) | |||||
| return AVERROR(EINVAL); | |||||
| av_buffer_realloc(&buf, size + FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (!buf) | |||||
| return AVERROR(ENOMEM); | |||||
| memset(buf->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| av_init_packet(pkt); | 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 (!data) | |||||
| return AVERROR(ENOMEM); | |||||
| #if FF_API_DESTRUCT_PACKET | |||||
| pkt->destruct = dummy_destruct_packet; | |||||
| #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); | |||||
| if (!new_ptr) | |||||
| return AVERROR(ENOMEM); | |||||
| pkt->data = new_ptr; | |||||
| new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE; | |||||
| if (pkt->buf) { | |||||
| int ret = av_buffer_realloc(&pkt->buf, new_size); | |||||
| if (ret < 0) | |||||
| return ret; | |||||
| } else { | |||||
| pkt->buf = av_buffer_alloc(new_size); | |||||
| if (!pkt->buf) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by)); | |||||
| #if FF_API_DESTRUCT_PACKET | |||||
| pkt->destruct = dummy_destruct_packet; | |||||
| #endif | |||||
| } | |||||
| pkt->data = pkt->buf->data; | |||||
| pkt->size += grow_by; | 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; | |||||
| } | |||||
| 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; | return 0; | ||||
| } | } | ||||
| #define DUP_DATA(dst, src, size, padding) \ | |||||
| #define ALLOC_MALLOC(data, size) data = av_malloc(size) | |||||
| #define ALLOC_BUF(data, size) \ | |||||
| do { \ | |||||
| av_buffer_realloc(&pkt->buf, size); \ | |||||
| data = pkt->buf ? pkt->buf->data : NULL; \ | |||||
| } while (0) | |||||
| #define DUP_DATA(dst, src, size, padding, ALLOC) \ | |||||
| do { \ | 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; | |||||
| dst->side_data = NULL; | |||||
| DUP_DATA(dst->data, src->data, dst->size, 1); | |||||
| dst->destruct = av_destruct_packet; | |||||
| if (dst->side_data_elems) { | |||||
| pkt->data = NULL; | |||||
| pkt->side_data = NULL; | |||||
| DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); | |||||
| #if FF_API_DESTRUCT_PACKET | |||||
| pkt->destruct = dummy_destruct_packet; | |||||
| #endif | |||||
| if (pkt->side_data_elems) { | |||||
| int i; | int i; | ||||
| DUP_DATA(dst->side_data, src->side_data, | |||||
| dst->side_data_elems * sizeof(*dst->side_data), 0); | |||||
| memset(dst->side_data, 0, | |||||
| dst->side_data_elems * sizeof(*dst->side_data)); | |||||
| for (i = 0; i < dst->side_data_elems; i++) { | |||||
| DUP_DATA(dst->side_data[i].data, src->side_data[i].data, | |||||
| src->side_data[i].size, 1); | |||||
| dst->side_data[i].size = src->side_data[i].size; | |||||
| dst->side_data[i].type = src->side_data[i].type; | |||||
| DUP_DATA(pkt->side_data, src->side_data, | |||||
| pkt->side_data_elems * sizeof(*pkt->side_data), 0, ALLOC_MALLOC); | |||||
| memset(pkt->side_data, 0, | |||||
| pkt->side_data_elems * sizeof(*pkt->side_data)); | |||||
| for (i = 0; i < pkt->side_data_elems; i++) { | |||||
| DUP_DATA(pkt->side_data[i].data, src->side_data[i].data, | |||||
| src->side_data[i].size, 1, ALLOC_MALLOC); | |||||
| pkt->side_data[i].size = src->side_data[i].size; | |||||
| pkt->side_data[i].type = src->side_data[i].type; | |||||
| } | } | ||||
| } | } | ||||
| return 0; | 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); | |||||
| if (!p) | |||||
| buf = av_buffer_alloc(size); | |||||
| if (!buf) | |||||
| return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
| pkt->data = p; | |||||
| pkt->destruct = av_destruct_packet; | |||||
| pkt->buf = buf; | |||||
| pkt->data = p = buf->data; | |||||
| #if FF_API_DESTRUCT_PACKET | |||||
| pkt->destruct = dummy_destruct_packet; | |||||
| #endif | |||||
| pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE; | 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); | |||||
| if (new_data) | |||||
| avpkt->data = new_data; | |||||
| ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (ret >= 0) | |||||
| avpkt->data = avpkt->buf->data; | |||||
| } | } | ||||
| avctx->frame_number++; | 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 && | |||||
| avpkt->destruct == av_destruct_packet) { | |||||
| uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (new_data) | |||||
| avpkt->data = new_data; | |||||
| if (needs_realloc && avpkt->data) { | |||||
| ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (ret >= 0) | |||||
| avpkt->data = avpkt->buf->data; | |||||
| } | } | ||||
| avctx->frame_number++; | 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) | |||||
| { | |||||
| av_assert0(0); | |||||
| } | |||||
| #endif | |||||
| static void mmap_release_buffer(void *opaque, uint8_t *data) | |||||
| { | { | ||||
| int res; | |||||
| struct v4l2_buffer buf = { 0 }; | struct v4l2_buffer buf = { 0 }; | ||||
| int res, fd; | |||||
| struct buff_data *buf_descriptor = opaque; | |||||
| struct video_data *s = buf_descriptor->s; | |||||
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |||||
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |||||
| buf.memory = V4L2_MEMORY_MMAP; | buf.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)); | |||||
| return res; | |||||
| av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", | |||||
| av_err2str(res)); | |||||
| } | } | ||||
| return 0; | |||||
| } | |||||
| static void mmap_release_buffer(AVPacket *pkt) | |||||
| { | |||||
| struct buff_data *buf_descriptor = pkt->priv; | |||||
| if (pkt->data == NULL) | |||||
| return; | |||||
| if (buf_descriptor->index == -1) { | |||||
| av_free(pkt->data); | |||||
| } else { | |||||
| if (!enqueue_buffer(buf_descriptor->fd, buf_descriptor->index)) | |||||
| buf_descriptor->buf_dequeued[buf_descriptor->index] = 0; | |||||
| } | |||||
| av_free(buf_descriptor); | |||||
| pkt->data = NULL; | |||||
| pkt->size = 0; | |||||
| avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); | |||||
| } | } | ||||
| #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) | #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, i, free_buffers; | |||||
| int res; | |||||
| /* 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)); | |||||
| if (buf_descriptor == NULL) { | |||||
| /* Something went wrong... Since av_malloc() failed, we cannot even | |||||
| * allocate a buffer for memcopying into it | |||||
| */ | |||||
| av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); | |||||
| res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); | |||||
| return AVERROR(ENOMEM); | |||||
| } | |||||
| buf_descriptor->fd = s->fd; | |||||
| buf_descriptor->buf_dequeued = s->buf_dequeued; | |||||
| free_buffers = -1; /* start from -1 because we just dequeued a buffer */ | |||||
| for (i = 0; i < s->buffers; i++) | |||||
| if (s->buf_dequeued[i] == 0) | |||||
| free_buffers++; | |||||
| if (free_buffers == 0) { | |||||
| if ((res = av_new_packet(pkt, buf.bytesused)) < 0) { | |||||
| enqueue_buffer(s->fd, buf.index); | |||||
| /* Image is at s->buff_start[buf.index] */ | |||||
| if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) { | |||||
| /* when we start getting low on queued buffers, fallback to copying data */ | |||||
| res = av_new_packet(pkt, buf.bytesused); | |||||
| if (res < 0) { | |||||
| av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n"); | |||||
| return res; | 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] */ | |||||
| pkt->data = s->buf_start[buf.index]; | |||||
| struct buff_data *buf_descriptor; | |||||
| pkt->data = s->buf_start[buf.index]; | |||||
| pkt->size = buf.bytesused; | |||||
| #if FF_API_DESTRUCT_PACKET | |||||
| pkt->destruct = dummy_release_buffer; | |||||
| #endif | |||||
| buf_descriptor = av_malloc(sizeof(struct buff_data)); | |||||
| if (buf_descriptor == NULL) { | |||||
| /* Something went wrong... Since av_malloc() failed, we cannot even | |||||
| * allocate a buffer for memcpying into it | |||||
| */ | |||||
| av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); | |||||
| res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); | |||||
| return AVERROR(ENOMEM); | |||||
| } | |||||
| buf_descriptor->fd = s->fd; | |||||
| buf_descriptor->index = buf.index; | buf_descriptor->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); | |||||
| if (res < 0) { | |||||
| mmap_release_buffer(pkt); | |||||
| return res; | |||||
| } | |||||
| convert_timestamp(ctx, &pkt->pts); | |||||
| 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 + | |||||
| FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (newdata) { | |||||
| AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size + | |||||
| FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (buf) { | |||||
| uint8_t *newdata = buf->data; | |||||
| int offset = 0; | 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); | |||||
| asf_st->pkt.data = newdata; | |||||
| av_buffer_unref(&asf_st->pkt.buf); | |||||
| asf_st->pkt.buf = buf; | |||||
| asf_st->pkt.data = buf->data; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| asf_st->frag_offset = 0; | 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 | |||||
| * ownership of the data and will free it when it sees fit using the packet's | |||||
| * @ref AVPacket.destruct "destruct" field. The caller must not access the data | |||||
| * after this function returns, as it may already be freed. | |||||
| * @param pkt The packet containing the data to be written. pkt->buf must be set | |||||
| * to a valid AVBufferRef describing the packet data. Libavformat takes | |||||
| * ownership of this reference and will unref it when it sees fit. The caller | |||||
| * must not access the data through this reference after this function returns. | |||||
| * This can be NULL (at any time, not just at the end), to flush the | * 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->data = av_malloc(taglen); | |||||
| if (!apic->data || !apic->len || avio_read(pb, apic->data, taglen) != taglen) | |||||
| apic->buf = av_buffer_alloc(taglen); | |||||
| if (!apic->buf || !taglen || avio_read(pb, apic->buf->data, taglen) != taglen) | |||||
| goto fail; | 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.size = apic->len; | |||||
| st->attached_pic.destruct = av_destruct_packet; | |||||
| st->attached_pic.buf = apic->buf; | |||||
| st->attached_pic.data = apic->buf->data; | |||||
| st->attached_pic.size = apic->buf->size; | |||||
| st->attached_pic.stream_index = st->index; | st->attached_pic.stream_index = st->index; | ||||
| st->attached_pic.flags |= AV_PKT_FLAG_KEY; | st->attached_pic.flags |= AV_PKT_FLAG_KEY; | ||||
| apic->data = NULL; | |||||
| apic->len = 0; | |||||
| apic->buf = NULL; | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -67,8 +67,7 @@ typedef struct ID3v2ExtraMetaGEOB { | |||||
| } ID3v2ExtraMetaGEOB; | } ID3v2ExtraMetaGEOB; | ||||
| typedef struct ID3v2ExtraMetaAPIC { | typedef struct ID3v2ExtraMetaAPIC { | ||||
| uint8_t *data; | |||||
| int len; | |||||
| AVBufferRef *buf; | |||||
| 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); | |||||
| pkt->data = line; | |||||
| pkt->size = strlen(line); | |||||
| av_buffer_unref(&pkt->buf); | |||||
| pkt->buf = 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) | |||||
| ret = mkv_copy_packet(mkv, pkt); | |||||
| else | |||||
| if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { | |||||
| mkv->cur_audio_pkt = *pkt; | |||||
| mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf); | |||||
| ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); | |||||
| } else | |||||
| ret = mkv_write_packet_internal(s, pkt); | 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->data = pes->buffer; | |||||
| pkt->buf = 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; | ||||
| } | } | ||||