diff options
Diffstat (limited to 'video/mp_image_pool.c')
-rw-r--r-- | video/mp_image_pool.c | 66 |
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; +} |