mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge 4192057728
into cd0699a338
This commit is contained in:
commit
aec6c706a8
@ -0,0 +1,36 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_CORE_VA_INTEL_INTEROP_HPP
|
||||
#define OPENCV_CORE_VA_INTEL_INTEROP_HPP
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error va_intel_interop.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)
|
||||
# include <CL/cl.h>
|
||||
# ifdef HAVE_VA_INTEL_OLD_HEADER
|
||||
# include <CL/va_ext.h>
|
||||
# else
|
||||
# include <CL/cl_va_api_media_sharing_intel.h>
|
||||
# endif
|
||||
# include "opencv2/core.hpp"
|
||||
# include "opencv2/core/ocl.hpp"
|
||||
|
||||
namespace cv { namespace va_intel {
|
||||
|
||||
class VAAPIInterop : public cv::ocl::Context::UserContext
|
||||
{
|
||||
public:
|
||||
VAAPIInterop(cl_platform_id platform);
|
||||
virtual ~VAAPIInterop() {};
|
||||
clCreateFromVA_APIMediaSurfaceINTEL_fn clCreateFromVA_APIMediaSurfaceINTEL;
|
||||
clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn clEnqueueAcquireVA_APIMediaSurfacesINTEL;
|
||||
clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL;
|
||||
};
|
||||
|
||||
}} // namespace cv::va_intel
|
||||
#endif /* defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) */
|
||||
#endif /* OPENCV_CORE_VA_INTEL_INTEROP_HPP */
|
@ -12,7 +12,6 @@
|
||||
# error va_intel.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "ocl.hpp"
|
||||
|
||||
#if defined(HAVE_VA)
|
||||
@ -45,10 +44,9 @@ using namespace cv::ocl;
|
||||
// TODO static functions in the Context class
|
||||
/** @brief Creates OpenCL context from VA.
|
||||
@param display - VADisplay for which CL interop should be established.
|
||||
@param tryInterop - try to set up for interoperability, if true; set up for use slow copy if false.
|
||||
@return Returns reference to OpenCL Context
|
||||
*/
|
||||
CV_EXPORTS Context& initializeContextFromVA(VADisplay display, bool tryInterop = true);
|
||||
CV_EXPORTS Context& initializeContextFromVA(VADisplay display);
|
||||
|
||||
} // namespace cv::va_intel::ocl
|
||||
|
||||
|
@ -19,21 +19,15 @@ using namespace cv;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// CL-VA Interoperability
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
# include "opencv2/core/opencl/runtime/opencl_core.hpp"
|
||||
# include "opencv2/core.hpp"
|
||||
# include "opencv2/core/ocl.hpp"
|
||||
# include "opencl_kernels_core.hpp"
|
||||
#endif // HAVE_OPENCL
|
||||
|
||||
# ifdef HAVE_VA_INTEL
|
||||
#ifdef HAVE_VA_INTEL_OLD_HEADER
|
||||
# include <CL/va_ext.h>
|
||||
#else
|
||||
# include <CL/cl_va_api_media_sharing_intel.h>
|
||||
#endif
|
||||
# include "opencv2/core/detail/va_intel_interop.hpp"
|
||||
# endif
|
||||
#endif // HAVE_OPENCL
|
||||
|
||||
#ifdef HAVE_VA
|
||||
#ifndef OPENCV_LIBVA_LINK
|
||||
@ -46,47 +40,16 @@ static void init_libva() { /* nothing */ }
|
||||
using namespace cv::detail;
|
||||
#endif
|
||||
|
||||
namespace cv { namespace va_intel {
|
||||
namespace cv { namespace va_intel { namespace ocl {
|
||||
|
||||
#ifdef HAVE_VA_INTEL
|
||||
|
||||
class VAAPIInterop : public ocl::Context::UserContext
|
||||
Context& initializeContextFromVA(VADisplay display)
|
||||
{
|
||||
public:
|
||||
VAAPIInterop(cl_platform_id platform) {
|
||||
clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromVA_APIMediaSurfaceINTEL");
|
||||
clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireVA_APIMediaSurfacesINTEL");
|
||||
clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseVA_APIMediaSurfacesINTEL");
|
||||
if (!clCreateFromVA_APIMediaSurfaceINTEL ||
|
||||
!clEnqueueAcquireVA_APIMediaSurfacesINTEL ||
|
||||
!clEnqueueReleaseVA_APIMediaSurfacesINTEL) {
|
||||
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get extension function for VA-API interop");
|
||||
}
|
||||
}
|
||||
virtual ~VAAPIInterop() {
|
||||
}
|
||||
clCreateFromVA_APIMediaSurfaceINTEL_fn clCreateFromVA_APIMediaSurfaceINTEL;
|
||||
clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn clEnqueueAcquireVA_APIMediaSurfacesINTEL;
|
||||
clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL;
|
||||
};
|
||||
|
||||
#endif // HAVE_VA_INTEL
|
||||
|
||||
namespace ocl {
|
||||
|
||||
Context& initializeContextFromVA(VADisplay display, bool tryInterop)
|
||||
{
|
||||
CV_UNUSED(display); CV_UNUSED(tryInterop);
|
||||
CV_UNUSED(display);
|
||||
#if !defined(HAVE_VA)
|
||||
NO_VA_SUPPORT_ERROR;
|
||||
#else // !HAVE_VA
|
||||
|
||||
# ifdef HAVE_VA_INTEL
|
||||
if (tryInterop)
|
||||
{
|
||||
cl_uint numPlatforms;
|
||||
cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
|
||||
if (status != CL_SUCCESS)
|
||||
@ -174,13 +137,12 @@ Context& initializeContextFromVA(VADisplay display, bool tryInterop)
|
||||
}
|
||||
clExecCtx.bind();
|
||||
return const_cast<Context&>(clExecCtx.getContext());
|
||||
}
|
||||
} else {
|
||||
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for VA-interop");
|
||||
}
|
||||
# endif // HAVE_VA_INTEL
|
||||
{
|
||||
Context& ctx = Context::getDefault(true);
|
||||
return ctx;
|
||||
}
|
||||
#endif // !HAVE_VA
|
||||
}
|
||||
|
||||
@ -536,18 +498,16 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface,
|
||||
|
||||
#ifdef HAVE_VA_INTEL
|
||||
ocl::OpenCLExecutionContext& ocl_context = ocl::OpenCLExecutionContext::getCurrent();
|
||||
VAAPIInterop* interop = ocl_context.getContext().getUserContext<VAAPIInterop>().get();
|
||||
CV_LOG_IF_DEBUG(NULL, !interop,
|
||||
"OpenCL/VA_INTEL: Can't interop with current OpenCL context - missing VAAPIInterop API. "
|
||||
"OpenCL context should be created through initializeContextFromVA()");
|
||||
void* context_display = ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_VA_API_DISPLAY_INTEL);
|
||||
CV_LOG_IF_INFO(NULL, interop && !context_display,
|
||||
"OpenCL/VA_INTEL: Can't interop with current OpenCL context - missing VA display, context re-creation is required");
|
||||
bool isValidContextDisplay = (display == context_display);
|
||||
CV_LOG_IF_INFO(NULL, interop && context_display && !isValidContextDisplay,
|
||||
"OpenCL/VA_INTEL: Can't interop with current OpenCL context - VA display mismatch: " << context_display << "(context) vs " << (void*)display << "(surface)");
|
||||
if (isValidContextDisplay && interop)
|
||||
{
|
||||
VAAPIInterop* interop = ocl_context.getContext().getUserContext<VAAPIInterop>().get();
|
||||
if(!context_display || context_display != display)
|
||||
CV_Error_(cv::Error::StsBadArg, ("Can't interop with current OpenCL context - VA display mismatch: %p (context) vs %p (surface).\ndid you call initializeContextFromVA before using VideoCapture/VideoWriter?", context_display, (void*)display));
|
||||
|
||||
if(!display)
|
||||
CV_Error(cv::Error::StsBadArg,
|
||||
"Invalid VADisplay passed to convertFromVASurface");
|
||||
|
||||
if(interop) {
|
||||
UMat u = src.getUMat();
|
||||
|
||||
// TODO Add support for roi
|
||||
@ -589,10 +549,14 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface,
|
||||
status = clReleaseMemObject(clImageUV);
|
||||
if (status != CL_SUCCESS)
|
||||
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)");
|
||||
}
|
||||
else
|
||||
return;
|
||||
} else
|
||||
# endif // HAVE_VA_INTEL
|
||||
{
|
||||
CV_LOG_DEBUG(NULL,
|
||||
"OpenCL/VA_INTEL: Can't interop with current OpenCL context - missing VAAPIInterop API. "
|
||||
"OpenCL context should be created through initializeContextFromVA()");
|
||||
|
||||
init_libva();
|
||||
Mat m = src.getMat();
|
||||
|
||||
@ -682,9 +646,16 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out
|
||||
|
||||
#ifdef HAVE_VA_INTEL
|
||||
ocl::OpenCLExecutionContext& ocl_context = ocl::OpenCLExecutionContext::getCurrent();
|
||||
void* context_display = ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_VA_API_DISPLAY_INTEL);
|
||||
VAAPIInterop* interop = ocl_context.getContext().getUserContext<VAAPIInterop>().get();
|
||||
if (display == ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_VA_API_DISPLAY_INTEL) && interop)
|
||||
{
|
||||
if(!context_display || context_display != display)
|
||||
CV_Error_(cv::Error::StsBadArg, ("Can't interop with current OpenCL context - VA display mismatch: %p (context) vs %p (surface).\ndid you call initializeContextFromVA before using VideoCapture/VideoWriter?", context_display, (void*)display));
|
||||
|
||||
if(!display)
|
||||
CV_Error(cv::Error::StsBadArg,
|
||||
"Invalid VADisplay passed to convertFromVASurface");
|
||||
|
||||
if(interop) {
|
||||
UMat u = dst.getUMat();
|
||||
|
||||
// TODO Add support for roi
|
||||
@ -726,10 +697,14 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out
|
||||
status = clReleaseMemObject(clImageUV);
|
||||
if (status != CL_SUCCESS)
|
||||
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)");
|
||||
}
|
||||
else
|
||||
return;
|
||||
} else
|
||||
# endif // HAVE_VA_INTEL
|
||||
{
|
||||
CV_LOG_DEBUG(NULL,
|
||||
"OpenCL/VA_INTEL: Can't interop with current OpenCL context - missing VAAPIInterop API. "
|
||||
"OpenCL context should be created through initializeContextFromVA()");
|
||||
|
||||
init_libva();
|
||||
Mat m = dst.getMat();
|
||||
|
||||
|
27
modules/core/src/va_intel_interop.cpp
Normal file
27
modules/core/src/va_intel_interop.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)
|
||||
# include "opencv2/core/opencl/runtime/opencl_core.hpp"
|
||||
# include "opencv2/core/detail/va_intel_interop.hpp"
|
||||
|
||||
namespace cv { namespace va_intel {
|
||||
|
||||
VAAPIInterop::VAAPIInterop(cl_platform_id platform) {
|
||||
clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromVA_APIMediaSurfaceINTEL");
|
||||
clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireVA_APIMediaSurfacesINTEL");
|
||||
clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseVA_APIMediaSurfacesINTEL");
|
||||
if (!clCreateFromVA_APIMediaSurfaceINTEL ||
|
||||
!clEnqueueAcquireVA_APIMediaSurfacesINTEL ||
|
||||
!clEnqueueReleaseVA_APIMediaSurfacesINTEL) {
|
||||
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get extension function for VA-API interop");
|
||||
}
|
||||
}
|
||||
}} // namespace cv::va_intel
|
||||
#endif /* defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) */
|
@ -32,6 +32,7 @@
|
||||
#include <va/va_backend.h>
|
||||
#ifdef HAVE_VA_INTEL
|
||||
#include "opencv2/core/va_intel.hpp"
|
||||
#include "opencv2/core/detail/va_intel_interop.hpp"
|
||||
#ifndef CL_TARGET_OPENCL_VERSION
|
||||
#define CL_TARGET_OPENCL_VERSION 120
|
||||
#endif
|
||||
@ -455,6 +456,8 @@ AVHWDeviceType hw_check_opencl_context(AVHWDeviceContext* ctx) {
|
||||
VADisplay vadisplay_ctx = hw_get_va_display(ctx);
|
||||
if (vadisplay_ocl && vadisplay_ocl == vadisplay_ctx)
|
||||
return AV_HWDEVICE_TYPE_VAAPI;
|
||||
else
|
||||
CV_Error_(cv::Error::StsBadArg, ("Can't interop with current OpenCL context - VA display mismatch: %p (hwcontext) vs %p (ocl_context).\ndid you call initializeContextFromVA before using VideoCapture/VideoWriter?", vadisplay_ctx, vadisplay_ocl));
|
||||
#endif
|
||||
#ifdef HAVE_D3D11
|
||||
ID3D11Device* d3d11device_ocl = (ID3D11Device*)ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_D3D11_DEVICE_KHR);
|
||||
@ -472,11 +475,18 @@ void hw_init_opencl(AVBufferRef* ctx) {
|
||||
AVHWDeviceContext* hw_device_ctx = (AVHWDeviceContext*)ctx->data;
|
||||
if (!hw_device_ctx)
|
||||
return;
|
||||
ocl::OpenCLExecutionContext& ocl_context = ocl::OpenCLExecutionContext::getCurrent();
|
||||
#ifdef HAVE_VA_INTEL
|
||||
cv::va_intel::VAAPIInterop* interop = ocl_context.getContext().getUserContext<cv::va_intel::VAAPIInterop>().get();
|
||||
//only initialize the context automatically if it isn't already
|
||||
if(!interop) {
|
||||
VADisplay va_display = hw_get_va_display(hw_device_ctx);
|
||||
if (va_display) {
|
||||
va_intel::ocl::initializeContextFromVA(va_display);
|
||||
}
|
||||
} else {
|
||||
CV_LOG_DEBUG(NULL, "OpenCL/VA_INTEL: CL/VA interop already initialized. ")
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_D3D11
|
||||
AVD3D11VADeviceContext* d3d11_device_ctx = hw_get_d3d11_device_ctx(hw_device_ctx);
|
||||
@ -486,8 +496,7 @@ void hw_init_opencl(AVBufferRef* ctx) {
|
||||
#endif
|
||||
if (hw_check_opencl_context(hw_device_ctx) != AV_HWDEVICE_TYPE_NONE) {
|
||||
// Attach AVHWDeviceContext to OpenCL context
|
||||
ocl::Context &ocl_context = ocl::OpenCLExecutionContext::getCurrent().getContext();
|
||||
ocl_context.setUserContext(std::make_shared<OpenCL_FFMPEG_Context>(ctx));
|
||||
ocl_context.getContext().setUserContext(std::make_shared<OpenCL_FFMPEG_Context>(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,10 +200,10 @@ static float run(const char* infile, const char* outfile1, const char* outfile2,
|
||||
VASurfaceID surface;
|
||||
VAStatus status;
|
||||
Timer t;
|
||||
|
||||
if(doInterop) {
|
||||
// initialize CL context for CL/VA interop
|
||||
cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop);
|
||||
|
||||
cv::va_intel::ocl::initializeContextFromVA(va::display);
|
||||
}
|
||||
// load input image
|
||||
cv::UMat u1 = readImage(infile);
|
||||
cv::Size size2 = u1.size();
|
||||
@ -215,7 +215,6 @@ static float run(const char* infile, const char* outfile1, const char* outfile2,
|
||||
cv::va_intel::convertFromVASurface(va::display, surface, size2, u1);
|
||||
cv::UMat u2;
|
||||
cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3));
|
||||
|
||||
// measure performance on some image processing
|
||||
writeImage(u1, outfile1, doInterop);
|
||||
t.start();
|
||||
|
Loading…
Reference in New Issue
Block a user