summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/avcodec.h23
-rw-r--r--libavcodec/internal.h5
-rw-r--r--libavcodec/pthread_frame.c1
-rw-r--r--libavcodec/utils.c34
4 files changed, 59 insertions, 4 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 65c7da4ec9..c76ee04cf5 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2999,6 +2999,29 @@ typedef struct AVHWAccel {
* AVCodecContext.release_buffer().
*/
int frame_priv_data_size;
+
+ /**
+ * Initialize the hwaccel private data.
+ *
+ * This will be called from ff_get_format(), after hwaccel and
+ * hwaccel_context are set and the hwaccel private data in AVCodecInternal
+ * is allocated.
+ */
+ int (*init)(AVCodecContext *avctx);
+
+ /**
+ * Uninitialize the hwaccel private data.
+ *
+ * This will be called from get_format() or avcodec_close(), after hwaccel
+ * and hwaccel_context are already uninitialized.
+ */
+ int (*uninit)(AVCodecContext *avctx);
+
+ /**
+ * Size of the private data to allocate in
+ * AVCodecInternal.hwaccel_priv_data.
+ */
+ int priv_data_size;
} AVHWAccel;
/**
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 78af94ecc4..6aaaf4c2cb 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -95,6 +95,11 @@ typedef struct AVCodecInternal {
* packet into every function.
*/
AVPacket *pkt;
+
+ /**
+ * hwaccel-specific private data
+ */
+ void *hwaccel_priv_data;
} AVCodecInternal;
struct AVCodecDefault {
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index ca36be2958..34ca9a6fb7 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -206,6 +206,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src,
dst->hwaccel = src->hwaccel;
dst->hwaccel_context = src->hwaccel_context;
+ dst->internal->hwaccel_priv_data = src->internal->hwaccel_priv_data;
}
if (for_user) {
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index c002c9c4e8..d5c307042e 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -893,16 +893,37 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
if (!desc)
return AV_PIX_FMT_NONE;
+ if (avctx->hwaccel && avctx->hwaccel->uninit)
+ avctx->hwaccel->uninit(avctx);
+ av_freep(&avctx->internal->hwaccel_priv_data);
+ avctx->hwaccel = NULL;
+
if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
- avctx->hwaccel = find_hwaccel(avctx->codec_id, ret);
- if (!avctx->hwaccel) {
+ AVHWAccel *hwaccel;
+ int err;
+
+ hwaccel = find_hwaccel(avctx->codec_id, ret);
+ if (!hwaccel) {
av_log(avctx, AV_LOG_ERROR,
"Could not find an AVHWAccel for the pixel format: %s",
desc->name);
return AV_PIX_FMT_NONE;
}
- } else {
- avctx->hwaccel = NULL;
+
+ if (hwaccel->priv_data_size) {
+ avctx->internal->hwaccel_priv_data = av_mallocz(hwaccel->priv_data_size);
+ if (!avctx->internal->hwaccel_priv_data)
+ return AV_PIX_FMT_NONE;
+ }
+
+ if (hwaccel->init) {
+ err = hwaccel->init(avctx);
+ if (err < 0) {
+ av_freep(&avctx->internal->hwaccel_priv_data);
+ return AV_PIX_FMT_NONE;
+ }
+ }
+ avctx->hwaccel = hwaccel;
}
return ret;
@@ -1688,6 +1709,11 @@ av_cold int avcodec_close(AVCodecContext *avctx)
for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
av_buffer_pool_uninit(&pool->pools[i]);
av_freep(&avctx->internal->pool);
+
+ if (avctx->hwaccel && avctx->hwaccel->uninit)
+ avctx->hwaccel->uninit(avctx);
+ av_freep(&avctx->internal->hwaccel_priv_data);
+
av_freep(&avctx->internal);
}