summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/decode.c110
-rw-r--r--libavcodec/internal.h21
-rw-r--r--libavcodec/pthread_frame.c12
-rw-r--r--libavcodec/utils.c13
4 files changed, 99 insertions, 57 deletions
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index de1e9fa4a4..b7ae1fbb84 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -45,6 +45,25 @@
#include "internal.h"
#include "thread.h"
+typedef struct FramePool {
+ /**
+ * Pools for each data plane. For audio all the planes have the same size,
+ * so only pools[0] is used.
+ */
+ AVBufferPool *pools[4];
+
+ /*
+ * Pool parameters
+ */
+ int format;
+ int width, height;
+ int stride_align[AV_NUM_DATA_POINTERS];
+ int linesize[4];
+ int planes;
+ int channels;
+ int samples;
+} FramePool;
+
static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt)
{
int size = 0, ret;
@@ -1504,10 +1523,61 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
return ret;
}
+static void frame_pool_free(void *opaque, uint8_t *data)
+{
+ FramePool *pool = (FramePool*)data;
+ int i;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
+ av_buffer_pool_uninit(&pool->pools[i]);
+
+ av_freep(&data);
+}
+
+static AVBufferRef *frame_pool_alloc(void)
+{
+ FramePool *pool = av_mallocz(sizeof(*pool));
+ AVBufferRef *buf;
+
+ if (!pool)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t*)pool, sizeof(*pool),
+ frame_pool_free, NULL, 0);
+ if (!buf) {
+ av_freep(&pool);
+ return NULL;
+ }
+
+ return buf;
+}
+
static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
{
- FramePool *pool = avctx->internal->pool;
- int i, ret;
+ FramePool *pool = avctx->internal->pool ?
+ (FramePool*)avctx->internal->pool->data : NULL;
+ AVBufferRef *pool_buf;
+ int i, ret, ch, planes;
+
+ if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+ int planar = av_sample_fmt_is_planar(frame->format);
+ ch = frame->channels;
+ planes = planar ? ch : 1;
+ }
+
+ if (pool && pool->format == frame->format) {
+ if (avctx->codec_type == AVMEDIA_TYPE_VIDEO &&
+ pool->width == frame->width && pool->height == frame->height)
+ return 0;
+ if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pool->planes == planes &&
+ pool->channels == ch && frame->nb_samples == pool->samples)
+ return 0;
+ }
+
+ pool_buf = frame_pool_alloc();
+ if (!pool_buf)
+ return AVERROR(ENOMEM);
+ pool = (FramePool*)pool_buf->data;
switch (avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO: {
@@ -1518,10 +1588,6 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
int h = frame->height;
int tmpsize, unaligned;
- if (pool->format == frame->format &&
- pool->width == frame->width && pool->height == frame->height)
- return 0;
-
avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
do {
@@ -1529,7 +1595,7 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
// that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
if (ret < 0)
- return ret;
+ goto fail;
// increase alignment of w for next try (rhs gives the lowest bit set in w)
w += w & ~(w - 1);
@@ -1540,15 +1606,16 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
tmpsize = av_image_fill_pointers(data, avctx->pix_fmt, h,
NULL, linesize);
- if (tmpsize < 0)
- return tmpsize;
+ if (tmpsize < 0) {
+ ret = tmpsize;
+ goto fail;
+ }
for (i = 0; i < 3 && data[i + 1]; i++)
size[i] = data[i + 1] - data[i];
size[i] = tmpsize - (data[i] - data[0]);
for (i = 0; i < 4; i++) {
- av_buffer_pool_uninit(&pool->pools[i]);
pool->linesize[i] = linesize[i];
if (size[i]) {
pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1,
@@ -1568,15 +1635,6 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
break;
}
case AVMEDIA_TYPE_AUDIO: {
- int ch = frame->channels; //av_get_channel_layout_nb_channels(frame->channel_layout);
- int planar = av_sample_fmt_is_planar(frame->format);
- int planes = planar ? ch : 1;
-
- if (pool->format == frame->format && pool->planes == planes &&
- pool->channels == ch && frame->nb_samples == pool->samples)
- return 0;
-
- av_buffer_pool_uninit(&pool->pools[0]);
ret = av_samples_get_buffer_size(&pool->linesize[0], ch,
frame->nb_samples, frame->format, 0);
if (ret < 0)
@@ -1596,19 +1654,19 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
}
default: av_assert0(0);
}
+
+ av_buffer_unref(&avctx->internal->pool);
+ avctx->internal->pool = pool_buf;
+
return 0;
fail:
- for (i = 0; i < 4; i++)
- av_buffer_pool_uninit(&pool->pools[i]);
- pool->format = -1;
- pool->planes = pool->channels = pool->samples = 0;
- pool->width = pool->height = 0;
+ av_buffer_unref(&pool_buf);
return ret;
}
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{
- FramePool *pool = avctx->internal->pool;
+ FramePool *pool = (FramePool*)avctx->internal->pool->data;
int planes = pool->planes;
int i;
@@ -1653,7 +1711,7 @@ fail:
static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
{
- FramePool *pool = s->internal->pool;
+ FramePool *pool = (FramePool*)s->internal->pool->data;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
int i;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 700807cd75..721fd017d4 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -108,25 +108,6 @@
# define STRIDE_ALIGN 8
#endif
-typedef struct FramePool {
- /**
- * Pools for each data plane. For audio all the planes have the same size,
- * so only pools[0] is used.
- */
- AVBufferPool *pools[4];
-
- /*
- * Pool parameters
- */
- int format;
- int width, height;
- int stride_align[AV_NUM_DATA_POINTERS];
- int linesize[4];
- int planes;
- int channels;
- int samples;
-} FramePool;
-
typedef struct DecodeSimpleContext {
AVPacket *in_pkt;
AVFrame *out_frame;
@@ -154,7 +135,7 @@ typedef struct AVCodecInternal {
AVFrame *to_free;
- FramePool *pool;
+ AVBufferRef *pool;
void *thread_ctx;
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index f0a162bc92..4cd890b295 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -296,6 +296,17 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src,
}
dst->hwaccel_flags = src->hwaccel_flags;
+
+ if (!!dst->internal->pool != !!src->internal->pool ||
+ (dst->internal->pool && dst->internal->pool->data != src->internal->pool->data)) {
+ av_buffer_unref(&dst->internal->pool);
+
+ if (src->internal->pool) {
+ dst->internal->pool = av_buffer_ref(src->internal->pool);
+ if (!dst->internal->pool)
+ return AVERROR(ENOMEM);
+ }
+ }
}
if (for_user) {
@@ -714,6 +725,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
}
if (p->avctx) {
+ av_buffer_unref(&p->avctx->internal->pool);
av_freep(&p->avctx->internal);
av_buffer_unref(&p->avctx->hw_frames_ctx);
}
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 4ab8cff4f5..26c038dfd9 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -583,12 +583,6 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
}
avctx->internal = avci;
- avci->pool = av_mallocz(sizeof(*avci->pool));
- if (!avci->pool) {
- ret = AVERROR(ENOMEM);
- goto free_and_end;
- }
-
avci->to_free = av_frame_alloc();
if (!avci->to_free) {
ret = AVERROR(ENOMEM);
@@ -1076,7 +1070,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
av_packet_free(&avci->ds.in_pkt);
ff_decode_bsfs_uninit(avctx);
- av_freep(&avci->pool);
+ av_buffer_unref(&avci->pool);
}
av_freep(&avci);
avctx->internal = NULL;
@@ -1111,7 +1105,6 @@ av_cold int avcodec_close(AVCodecContext *avctx)
return 0;
if (avcodec_is_open(avctx)) {
- FramePool *pool = avctx->internal->pool;
if (CONFIG_FRAME_THREAD_ENCODER &&
avctx->internal->frame_thread_encoder && avctx->thread_count > 1) {
ff_frame_thread_encoder_free(avctx);
@@ -1130,9 +1123,7 @@ av_cold int avcodec_close(AVCodecContext *avctx)
av_packet_free(&avctx->internal->ds.in_pkt);
- for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
- av_buffer_pool_uninit(&pool->pools[i]);
- av_freep(&avctx->internal->pool);
+ av_buffer_unref(&avctx->internal->pool);
if (avctx->hwaccel && avctx->hwaccel->uninit)
avctx->hwaccel->uninit(avctx);