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++
|
# error va_intel.hpp header must be compiled as C++
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "opencv2/core.hpp"
|
|
||||||
#include "ocl.hpp"
|
#include "ocl.hpp"
|
||||||
|
|
||||||
#if defined(HAVE_VA)
|
#if defined(HAVE_VA)
|
||||||
@ -45,10 +44,9 @@ using namespace cv::ocl;
|
|||||||
// TODO static functions in the Context class
|
// TODO static functions in the Context class
|
||||||
/** @brief Creates OpenCL context from VA.
|
/** @brief Creates OpenCL context from VA.
|
||||||
@param display - VADisplay for which CL interop should be established.
|
@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
|
@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
|
} // namespace cv::va_intel::ocl
|
||||||
|
|
||||||
|
@ -19,22 +19,16 @@ using namespace cv;
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// CL-VA Interoperability
|
// CL-VA Interoperability
|
||||||
|
|
||||||
#ifdef HAVE_OPENCL
|
#ifdef HAVE_OPENCL
|
||||||
# include "opencv2/core/opencl/runtime/opencl_core.hpp"
|
# include "opencv2/core/opencl/runtime/opencl_core.hpp"
|
||||||
# include "opencv2/core.hpp"
|
# include "opencv2/core.hpp"
|
||||||
# include "opencv2/core/ocl.hpp"
|
# include "opencv2/core/ocl.hpp"
|
||||||
# include "opencl_kernels_core.hpp"
|
# include "opencl_kernels_core.hpp"
|
||||||
|
# ifdef HAVE_VA_INTEL
|
||||||
|
# include "opencv2/core/detail/va_intel_interop.hpp"
|
||||||
|
# endif
|
||||||
#endif // HAVE_OPENCL
|
#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
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_VA
|
#ifdef HAVE_VA
|
||||||
#ifndef OPENCV_LIBVA_LINK
|
#ifndef OPENCV_LIBVA_LINK
|
||||||
#include "va_wrapper.impl.hpp"
|
#include "va_wrapper.impl.hpp"
|
||||||
@ -46,141 +40,109 @@ static void init_libva() { /* nothing */ }
|
|||||||
using namespace cv::detail;
|
using namespace cv::detail;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace cv { namespace va_intel {
|
namespace cv { namespace va_intel { namespace ocl {
|
||||||
|
|
||||||
#ifdef HAVE_VA_INTEL
|
Context& initializeContextFromVA(VADisplay display)
|
||||||
|
|
||||||
class VAAPIInterop : public ocl::Context::UserContext
|
|
||||||
{
|
{
|
||||||
public:
|
CV_UNUSED(display);
|
||||||
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);
|
|
||||||
#if !defined(HAVE_VA)
|
#if !defined(HAVE_VA)
|
||||||
NO_VA_SUPPORT_ERROR;
|
NO_VA_SUPPORT_ERROR;
|
||||||
#else // !HAVE_VA
|
#else // !HAVE_VA
|
||||||
|
|
||||||
# ifdef HAVE_VA_INTEL
|
# ifdef HAVE_VA_INTEL
|
||||||
if (tryInterop)
|
cl_uint numPlatforms;
|
||||||
|
cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
|
||||||
|
if (status != CL_SUCCESS)
|
||||||
|
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
|
||||||
|
if (numPlatforms == 0)
|
||||||
|
CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
|
||||||
|
|
||||||
|
std::vector<cl_platform_id> platforms(numPlatforms);
|
||||||
|
status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
|
||||||
|
if (status != CL_SUCCESS)
|
||||||
|
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list");
|
||||||
|
|
||||||
|
// For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension.
|
||||||
|
// With standard initialization procedure, we should examine platform extension string for that.
|
||||||
|
// But in practice, the platform ext string doesn't contain it, while device ext string does.
|
||||||
|
// Follow Intel procedure (see tutorial), we should obtain device IDs by extension call.
|
||||||
|
// Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance.
|
||||||
|
// So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context.
|
||||||
|
|
||||||
|
int found = -1;
|
||||||
|
cl_context context = 0;
|
||||||
|
cl_device_id device = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)numPlatforms; ++i)
|
||||||
{
|
{
|
||||||
cl_uint numPlatforms;
|
// Get extension function pointers
|
||||||
cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
|
clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn clGetDeviceIDsFromVA_APIMediaAdapterINTEL;
|
||||||
if (status != CL_SUCCESS)
|
clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn)
|
||||||
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
|
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL");
|
||||||
if (numPlatforms == 0)
|
if ((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL)
|
||||||
CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
|
|
||||||
|
|
||||||
std::vector<cl_platform_id> platforms(numPlatforms);
|
|
||||||
status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
|
|
||||||
if (status != CL_SUCCESS)
|
|
||||||
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list");
|
|
||||||
|
|
||||||
// For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension.
|
|
||||||
// With standard initialization procedure, we should examine platform extension string for that.
|
|
||||||
// But in practice, the platform ext string doesn't contain it, while device ext string does.
|
|
||||||
// Follow Intel procedure (see tutorial), we should obtain device IDs by extension call.
|
|
||||||
// Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance.
|
|
||||||
// So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context.
|
|
||||||
|
|
||||||
int found = -1;
|
|
||||||
cl_context context = 0;
|
|
||||||
cl_device_id device = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)numPlatforms; ++i)
|
|
||||||
{
|
{
|
||||||
// Get extension function pointers
|
continue;
|
||||||
clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn clGetDeviceIDsFromVA_APIMediaAdapterINTEL;
|
|
||||||
clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn)
|
|
||||||
clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL");
|
|
||||||
if ((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query device list
|
|
||||||
|
|
||||||
cl_uint numDevices = 0;
|
|
||||||
|
|
||||||
status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display,
|
|
||||||
CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices);
|
|
||||||
if ((status != CL_SUCCESS) || !(numDevices > 0))
|
|
||||||
continue;
|
|
||||||
numDevices = 1; // OpenCV expects only 1 device
|
|
||||||
status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display,
|
|
||||||
CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL);
|
|
||||||
if (status != CL_SUCCESS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Creating CL-VA media sharing OpenCL context
|
|
||||||
|
|
||||||
cl_context_properties props[] = {
|
|
||||||
CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display,
|
|
||||||
CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
context = clCreateContext(props, numDevices, &device, NULL, NULL, &status);
|
|
||||||
if (status != CL_SUCCESS)
|
|
||||||
{
|
|
||||||
clReleaseDevice(device);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
found = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found >= 0)
|
// Query device list
|
||||||
{
|
|
||||||
cl_platform_id platform = platforms[found];
|
|
||||||
std::string platformName = PlatformInfo(&platform).name();
|
|
||||||
|
|
||||||
OpenCLExecutionContext clExecCtx;
|
cl_uint numDevices = 0;
|
||||||
try
|
|
||||||
{
|
status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display,
|
||||||
clExecCtx = OpenCLExecutionContext::create(platformName, platform, context, device);
|
CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices);
|
||||||
clExecCtx.getContext().setUserContext(std::make_shared<VAAPIInterop>(platform));
|
if ((status != CL_SUCCESS) || !(numDevices > 0))
|
||||||
}
|
continue;
|
||||||
catch (...)
|
numDevices = 1; // OpenCV expects only 1 device
|
||||||
{
|
status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display,
|
||||||
clReleaseDevice(device);
|
CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL);
|
||||||
clReleaseContext(context);
|
if (status != CL_SUCCESS)
|
||||||
throw;
|
continue;
|
||||||
}
|
|
||||||
clExecCtx.bind();
|
// Creating CL-VA media sharing OpenCL context
|
||||||
return const_cast<Context&>(clExecCtx.getContext());
|
|
||||||
|
cl_context_properties props[] = {
|
||||||
|
CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display,
|
||||||
|
CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
context = clCreateContext(props, numDevices, &device, NULL, NULL, &status);
|
||||||
|
if (status != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
clReleaseDevice(device);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found >= 0)
|
||||||
|
{
|
||||||
|
cl_platform_id platform = platforms[found];
|
||||||
|
std::string platformName = PlatformInfo(&platform).name();
|
||||||
|
|
||||||
|
OpenCLExecutionContext clExecCtx;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clExecCtx = OpenCLExecutionContext::create(platformName, platform, context, device);
|
||||||
|
clExecCtx.getContext().setUserContext(std::make_shared<VAAPIInterop>(platform));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
clReleaseDevice(device);
|
||||||
|
clReleaseContext(context);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
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
|
# endif // HAVE_VA_INTEL
|
||||||
{
|
Context& ctx = Context::getDefault(true);
|
||||||
Context& ctx = Context::getDefault(true);
|
return ctx;
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
#endif // !HAVE_VA
|
#endif // !HAVE_VA
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,18 +498,16 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface,
|
|||||||
|
|
||||||
#ifdef HAVE_VA_INTEL
|
#ifdef HAVE_VA_INTEL
|
||||||
ocl::OpenCLExecutionContext& ocl_context = ocl::OpenCLExecutionContext::getCurrent();
|
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);
|
void* context_display = ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_VA_API_DISPLAY_INTEL);
|
||||||
CV_LOG_IF_INFO(NULL, interop && !context_display,
|
VAAPIInterop* interop = ocl_context.getContext().getUserContext<VAAPIInterop>().get();
|
||||||
"OpenCL/VA_INTEL: Can't interop with current OpenCL context - missing VA display, context re-creation is required");
|
if(!context_display || context_display != display)
|
||||||
bool isValidContextDisplay = (display == context_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));
|
||||||
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(!display)
|
||||||
if (isValidContextDisplay && interop)
|
CV_Error(cv::Error::StsBadArg,
|
||||||
{
|
"Invalid VADisplay passed to convertFromVASurface");
|
||||||
|
|
||||||
|
if(interop) {
|
||||||
UMat u = src.getUMat();
|
UMat u = src.getUMat();
|
||||||
|
|
||||||
// TODO Add support for roi
|
// TODO Add support for roi
|
||||||
@ -589,10 +549,14 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface,
|
|||||||
status = clReleaseMemObject(clImageUV);
|
status = clReleaseMemObject(clImageUV);
|
||||||
if (status != CL_SUCCESS)
|
if (status != CL_SUCCESS)
|
||||||
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)");
|
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)");
|
||||||
}
|
return;
|
||||||
else
|
} else
|
||||||
# endif // HAVE_VA_INTEL
|
# 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();
|
init_libva();
|
||||||
Mat m = src.getMat();
|
Mat m = src.getMat();
|
||||||
|
|
||||||
@ -682,9 +646,16 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out
|
|||||||
|
|
||||||
#ifdef HAVE_VA_INTEL
|
#ifdef HAVE_VA_INTEL
|
||||||
ocl::OpenCLExecutionContext& ocl_context = ocl::OpenCLExecutionContext::getCurrent();
|
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();
|
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();
|
UMat u = dst.getUMat();
|
||||||
|
|
||||||
// TODO Add support for roi
|
// TODO Add support for roi
|
||||||
@ -726,10 +697,14 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out
|
|||||||
status = clReleaseMemObject(clImageUV);
|
status = clReleaseMemObject(clImageUV);
|
||||||
if (status != CL_SUCCESS)
|
if (status != CL_SUCCESS)
|
||||||
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)");
|
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)");
|
||||||
}
|
return;
|
||||||
else
|
} else
|
||||||
# endif // HAVE_VA_INTEL
|
# 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();
|
init_libva();
|
||||||
Mat m = dst.getMat();
|
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>
|
#include <va/va_backend.h>
|
||||||
#ifdef HAVE_VA_INTEL
|
#ifdef HAVE_VA_INTEL
|
||||||
#include "opencv2/core/va_intel.hpp"
|
#include "opencv2/core/va_intel.hpp"
|
||||||
|
#include "opencv2/core/detail/va_intel_interop.hpp"
|
||||||
#ifndef CL_TARGET_OPENCL_VERSION
|
#ifndef CL_TARGET_OPENCL_VERSION
|
||||||
#define CL_TARGET_OPENCL_VERSION 120
|
#define CL_TARGET_OPENCL_VERSION 120
|
||||||
#endif
|
#endif
|
||||||
@ -455,6 +456,8 @@ AVHWDeviceType hw_check_opencl_context(AVHWDeviceContext* ctx) {
|
|||||||
VADisplay vadisplay_ctx = hw_get_va_display(ctx);
|
VADisplay vadisplay_ctx = hw_get_va_display(ctx);
|
||||||
if (vadisplay_ocl && vadisplay_ocl == vadisplay_ctx)
|
if (vadisplay_ocl && vadisplay_ocl == vadisplay_ctx)
|
||||||
return AV_HWDEVICE_TYPE_VAAPI;
|
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
|
#endif
|
||||||
#ifdef HAVE_D3D11
|
#ifdef HAVE_D3D11
|
||||||
ID3D11Device* d3d11device_ocl = (ID3D11Device*)ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_D3D11_DEVICE_KHR);
|
ID3D11Device* d3d11device_ocl = (ID3D11Device*)ocl_context.getContext().getOpenCLContextProperty(CL_CONTEXT_D3D11_DEVICE_KHR);
|
||||||
@ -472,10 +475,17 @@ void hw_init_opencl(AVBufferRef* ctx) {
|
|||||||
AVHWDeviceContext* hw_device_ctx = (AVHWDeviceContext*)ctx->data;
|
AVHWDeviceContext* hw_device_ctx = (AVHWDeviceContext*)ctx->data;
|
||||||
if (!hw_device_ctx)
|
if (!hw_device_ctx)
|
||||||
return;
|
return;
|
||||||
|
ocl::OpenCLExecutionContext& ocl_context = ocl::OpenCLExecutionContext::getCurrent();
|
||||||
#ifdef HAVE_VA_INTEL
|
#ifdef HAVE_VA_INTEL
|
||||||
VADisplay va_display = hw_get_va_display(hw_device_ctx);
|
cv::va_intel::VAAPIInterop* interop = ocl_context.getContext().getUserContext<cv::va_intel::VAAPIInterop>().get();
|
||||||
if (va_display) {
|
//only initialize the context automatically if it isn't already
|
||||||
va_intel::ocl::initializeContextFromVA(va_display);
|
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
|
#endif
|
||||||
#ifdef HAVE_D3D11
|
#ifdef HAVE_D3D11
|
||||||
@ -486,8 +496,7 @@ void hw_init_opencl(AVBufferRef* ctx) {
|
|||||||
#endif
|
#endif
|
||||||
if (hw_check_opencl_context(hw_device_ctx) != AV_HWDEVICE_TYPE_NONE) {
|
if (hw_check_opencl_context(hw_device_ctx) != AV_HWDEVICE_TYPE_NONE) {
|
||||||
// Attach AVHWDeviceContext to OpenCL context
|
// Attach AVHWDeviceContext to OpenCL context
|
||||||
ocl::Context &ocl_context = ocl::OpenCLExecutionContext::getCurrent().getContext();
|
ocl_context.getContext().setUserContext(std::make_shared<OpenCL_FFMPEG_Context>(ctx));
|
||||||
ocl_context.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;
|
VASurfaceID surface;
|
||||||
VAStatus status;
|
VAStatus status;
|
||||||
Timer t;
|
Timer t;
|
||||||
|
if(doInterop) {
|
||||||
// initialize CL context for CL/VA interop
|
// 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
|
// load input image
|
||||||
cv::UMat u1 = readImage(infile);
|
cv::UMat u1 = readImage(infile);
|
||||||
cv::Size size2 = u1.size();
|
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::va_intel::convertFromVASurface(va::display, surface, size2, u1);
|
||||||
cv::UMat u2;
|
cv::UMat u2;
|
||||||
cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3));
|
cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3));
|
||||||
|
|
||||||
// measure performance on some image processing
|
// measure performance on some image processing
|
||||||
writeImage(u1, outfile1, doInterop);
|
writeImage(u1, outfile1, doInterop);
|
||||||
t.start();
|
t.start();
|
||||||
|
Loading…
Reference in New Issue
Block a user