summaryrefslogtreecommitdiffstats
path: root/video/mp_image_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/mp_image_pool.c')
-rw-r--r--video/mp_image_pool.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/video/mp_image_pool.c b/video/mp_image_pool.c
index 8aa584b33e..922854a7d1 100644
--- a/video/mp_image_pool.c
+++ b/video/mp_image_pool.c
@@ -19,24 +19,28 @@
#include <stddef.h>
#include <stdbool.h>
-#include <pthread.h>
#include <assert.h>
#include <libavutil/buffer.h>
#include <libavutil/hwcontext.h>
+#if HAVE_VULKAN_INTEROP
+#include <libavutil/hwcontext_vulkan.h>
+#endif
#include <libavutil/mem.h>
+#include <libavutil/pixdesc.h>
#include "mpv_talloc.h"
#include "common/common.h"
#include "fmt-conversion.h"
-#include "mp_image.h"
#include "mp_image_pool.h"
+#include "mp_image.h"
+#include "osdep/threads.h"
-static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
-#define pool_lock() pthread_mutex_lock(&pool_mutex)
-#define pool_unlock() pthread_mutex_unlock(&pool_mutex)
+static mp_static_mutex pool_mutex = MP_STATIC_MUTEX_INITIALIZER;
+#define pool_lock() mp_mutex_lock(&pool_mutex)
+#define pool_unlock() mp_mutex_unlock(&pool_mutex)
// Thread-safety: the pool itself is not thread-safe, but pool-allocated images
// can be referenced and unreferenced from other threads. (As long as the image
@@ -276,7 +280,7 @@ int mp_image_hw_download_get_sw_format(struct mp_image *src)
return imgfmt;
}
-// Copies the contents of the HW surface src to system memory and retuns it.
+// Copies the contents of the HW surface src to system memory and returns it.
// If swpool is not NULL, it's used to allocate the target image.
// src must be a hw surface with a AVHWFramesContext attached.
// The returned image is cropped as needed.
@@ -325,7 +329,7 @@ bool mp_image_hw_upload(struct mp_image *hw_img, struct mp_image *src)
if (hw_img->w != src->w || hw_img->h != src->h)
return false;
- if (!hw_img->hwctx || src->hwctx)
+ if (!hw_img->hwctx)
return false;
bool ok = false;
@@ -333,7 +337,7 @@ bool mp_image_hw_upload(struct mp_image *hw_img, struct mp_image *src)
AVFrame *srcav = NULL;
// This means the destination image will not be "writable", which would be
- // a pain if Libav enforced this - fortunately it doesn't care. We can
+ // a pain if FFmpeg enforced this - fortunately it doesn't care. We can
// transfer data to it even if there are multiple refs.
dstav = mp_image_to_av_frame(hw_img);
if (!dstav)
@@ -346,8 +350,8 @@ bool mp_image_hw_upload(struct mp_image *hw_img, struct mp_image *src)
ok = av_hwframe_transfer_data(dstav, srcav, 0) >= 0;
done:
- av_frame_unref(srcav);
- av_frame_unref(dstav);
+ av_frame_free(&srcav);
+ av_frame_free(&dstav);
if (ok)
mp_image_copy_attributes(hw_img, src);
@@ -356,7 +360,8 @@ done:
bool mp_update_av_hw_frames_pool(struct AVBufferRef **hw_frames_ctx,
struct AVBufferRef *hw_device_ctx,
- int imgfmt, int sw_imgfmt, int w, int h)
+ int imgfmt, int sw_imgfmt, int w, int h,
+ bool disable_multiplane)
{
enum AVPixelFormat format = imgfmt2pixfmt(imgfmt);
enum AVPixelFormat sw_format = imgfmt2pixfmt(sw_imgfmt);
@@ -387,6 +392,18 @@ bool mp_update_av_hw_frames_pool(struct AVBufferRef **hw_frames_ctx,
hw_frames->sw_format = sw_format;
hw_frames->width = w;
hw_frames->height = h;
+
+#if HAVE_VULKAN_INTEROP
+ if (format == AV_PIX_FMT_VULKAN && disable_multiplane) {
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(sw_format);
+ if ((desc->flags & AV_PIX_FMT_FLAG_PLANAR) &&
+ !(desc->flags & AV_PIX_FMT_FLAG_RGB)) {
+ AVVulkanFramesContext *vk_frames = hw_frames->hwctx;
+ vk_frames->flags = AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE;
+ }
+ }
+#endif
+
if (av_hwframe_ctx_init(*hw_frames_ctx) < 0) {
av_buffer_unref(hw_frames_ctx);
return false;
@@ -426,3 +443,30 @@ struct mp_image *mp_av_pool_image_hw_upload(struct AVBufferRef *hw_frames_ctx,
mp_image_copy_attributes(dst, src);
return dst;
}
+
+struct mp_image *mp_av_pool_image_hw_map(struct AVBufferRef *hw_frames_ctx,
+ struct mp_image *src)
+{
+ AVFrame *dst_frame = av_frame_alloc();
+ if (!dst_frame)
+ return NULL;
+
+ dst_frame->format = ((AVHWFramesContext*)hw_frames_ctx->data)->format;
+ dst_frame->hw_frames_ctx = av_buffer_ref(hw_frames_ctx);
+
+ AVFrame *src_frame = mp_image_to_av_frame(src);
+ if (av_hwframe_map(dst_frame, src_frame, 0) < 0) {
+ av_frame_free(&src_frame);
+ av_frame_free(&dst_frame);
+ return NULL;
+ }
+ av_frame_free(&src_frame);
+
+ struct mp_image *dst = mp_image_from_av_frame(dst_frame);
+ av_frame_free(&dst_frame);
+ if (!dst)
+ return NULL;
+
+ mp_image_copy_attributes(dst, src);
+ return dst;
+}