MediaSDK video backend: Windows support
authorMaksim Shabunin <maksim.shabunin@gmail.com>
Tue, 10 Oct 2017 14:21:27 +0000 (17:21 +0300)
committerMaksim Shabunin <maksim.shabunin@gmail.com>
Wed, 11 Oct 2017 13:33:37 +0000 (16:33 +0300)
CMakeLists.txt
cmake/OpenCVDetectMediaSDK.cmake
modules/videoio/src/cap_mfx_common.cpp
modules/videoio/src/cap_mfx_common.hpp
modules/videoio/src/cap_mfx_reader.cpp
modules/videoio/src/cap_mfx_writer.cpp

index 8e9bd0b..47de63f 100644 (file)
@@ -245,7 +245,7 @@ OCV_OPTION(WITH_INTELPERC      "Include Intel Perceptual Computing support"  OFF
 OCV_OPTION(WITH_MATLAB         "Include Matlab support"                      ON   IF (NOT ANDROID AND NOT IOS AND NOT WINRT))
 OCV_OPTION(WITH_VA             "Include VA support"                          OFF  IF (UNIX AND NOT ANDROID) )
 OCV_OPTION(WITH_VA_INTEL       "Include Intel VA-API/OpenCL support"         OFF  IF (UNIX AND NOT ANDROID) )
-OCV_OPTION(WITH_MFX            "Include Intel Media SDK support"             OFF   IF (UNIX AND NOT ANDROID) )
+OCV_OPTION(WITH_MFX            "Include Intel Media SDK support"             OFF   IF ((UNIX AND NOT ANDROID) OR (WIN32 AND NOT WINRT AND NOT MINGW)) )
 OCV_OPTION(WITH_GDAL           "Include GDAL Support"                        OFF  IF (NOT ANDROID AND NOT IOS AND NOT WINRT) )
 OCV_OPTION(WITH_GPHOTO2        "Include gPhoto2 library support"             ON   IF (UNIX AND NOT ANDROID) )
 OCV_OPTION(WITH_LAPACK         "Include Lapack library support"              ON   IF (NOT ANDROID AND NOT IOS) )
index bc0b2ed..97f898c 100644 (file)
@@ -1,6 +1,10 @@
-set(root "$ENV{MFX_HOME}")
+set(HAVE_MFX 0)
 
-find_path(MFX_INCLUDE mfxdefs.h PATHS "${root}/include" NO_DEFAULT_PATH)
+if (UNIX)
+    set(root "$ENV{MFX_HOME}")
+elseif(WIN32)
+    set(root "$ENV{INTELMEDIASDKROOT}")
+endif()
 
 # TODO: ICC? MINGW? ARM? IOS?
 if(WIN32)
@@ -15,24 +19,41 @@ else()
     # ???
 endif()
 
-find_library(MFX_LIBRARY mfx PATHS "${root}/lib/${arch}" NO_DEFAULT_PATH)
-find_library(MFX_VA_LIBRARY va)
-find_library(MFX_VA_DRM_LIBRARY va-drm)
+find_path(MFX_INCLUDE mfxdefs.h PATHS "${root}/include" NO_DEFAULT_PATH)
+message(STATUS "MFX_INCLUDE: ${MFX_INCLUDE} (${root}/include)")
+find_library(MFX_LIBRARY NAMES mfx PATHS "${root}/lib/${arch}" NO_DEFAULT_PATH)
+if(MSVC)
+    if(MSVC14)
+        find_library(MFX_LIBRARY NAMES libmfx_vs2015.lib PATHS "${root}/lib/${arch}" NO_DEFAULT_PATH)
+    else()
+        find_library(MFX_LIBRARY NAMES libmfx.lib PATHS "${root}/lib/${arch}" NO_DEFAULT_PATH)
+    endif()
+endif()
+
+if(NOT MFX_INCLUDE OR NOT MFX_LIBRARY)
+    return()
+endif()
 
-if(MFX_INCLUDE AND MFX_LIBRARY AND MFX_VA_LIBRARY AND MFX_VA_DRM_LIBRARY)
+set(deps)
+
+if (UNIX)
+    find_library(MFX_VA_LIBRARY va)
+    find_library(MFX_VA_DRM_LIBRARY va-drm)
+    if (NOT MFX_VA_LIBRARY OR NOT MFX_VA_DRM_LIBRARY)
+        return()
+    endif()
     add_library(mfx-va UNKNOWN IMPORTED)
     set_target_properties(mfx-va PROPERTIES IMPORTED_LOCATION "${MFX_VA_LIBRARY}")
-
     add_library(mfx-va-drm UNKNOWN IMPORTED)
     set_target_properties(mfx-va-drm PROPERTIES IMPORTED_LOCATION "${MFX_VA_DRM_LIBRARY}")
-
-    add_library(mfx UNKNOWN IMPORTED)
-    set_target_properties(mfx PROPERTIES
-      IMPORTED_LOCATION "${MFX_LIBRARY}"
-      INTERFACE_INCLUDE_DIRECTORIES "${MFX_INCLUDE}"
-      INTERFACE_LINK_LIBRARIES "mfx-va;mfx-va-drm;-Wl,--exclude-libs=libmfx"
-    )
-    set(HAVE_MFX 1)
-else()
-    set(HAVE_MFX 0)
+    list(APPEND deps mfx-va mfx-va-drm "-Wl,--exclude-libs=libmfx")
 endif()
+
+add_library(mfx UNKNOWN IMPORTED)
+set_target_properties(mfx PROPERTIES
+  IMPORTED_LOCATION "${MFX_LIBRARY}"
+  INTERFACE_INCLUDE_DIRECTORIES "${MFX_INCLUDE}"
+  INTERFACE_LINK_LIBRARIES "${deps}"
+)
+
+set(HAVE_MFX 1)
index dda0cc2..49fb847 100644 (file)
@@ -5,10 +5,12 @@
 #include "cap_mfx_common.hpp"
 
 // Linux specific
+#ifdef __linux__
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#endif
 
 using namespace std;
 using namespace cv;
@@ -36,6 +38,8 @@ bool DeviceHandler::init(MFXVideoSession &session)
 
 //==================================================================================================
 
+#ifdef __linux__
+
 VAHandle::VAHandle() {
     // TODO: provide a way of modifying this path
     const string filename = "/dev/dri/card0";
@@ -68,6 +72,19 @@ bool VAHandle::initDeviceSession(MFXVideoSession &session) {
     return false;
 }
 
+#endif // __linux__
+
+DeviceHandler * createDeviceHandler()
+{
+#if defined __linux__
+    return new VAHandle();
+#elif defined _WIN32
+    return new DXHandle();
+#else
+    return 0;
+#endif
+}
+
 //==================================================================================================
 
 SurfacePool::SurfacePool(ushort width_, ushort height_, ushort count, const mfxFrameInfo &frameInfo, uchar bpp)
@@ -85,7 +102,8 @@ SurfacePool::SurfacePool(ushort width_, ushort height_, ushort count, const mfxF
         surface.Info = frameInfo;
         surface.Data.Y = dataPtr;
         surface.Data.UV = dataPtr + width * height;
-        surface.Data.Pitch = width;
+        surface.Data.PitchLow = width & 0xFFFF;
+        surface.Data.PitchHigh = (width >> 16) & 0xFFFF;
         DBG(cout << "allocate surface " << (void*)&surface << ", Y = " << (void*)dataPtr << " (" << width << "x" << height << ")" << endl);
     }
     DBG(cout << "Allocated: " << endl
@@ -112,7 +130,7 @@ ReadBitstream::ReadBitstream(const char *filename, size_t maxSize) : drain(false
     input.open(filename, std::ios::in | std::ios::binary);
     DBG(cout << "Open " << filename << " -> " << input.is_open() << std::endl);
     memset(&stream, 0, sizeof(stream));
-    stream.MaxLength = maxSize;
+    stream.MaxLength = (mfxU32)maxSize;
     stream.Data = new mfxU8[stream.MaxLength];
     CV_Assert(stream.Data);
 }
@@ -139,7 +157,7 @@ bool ReadBitstream::read()
     input.read((char*)(stream.Data + stream.DataLength), stream.MaxLength - stream.DataLength);
     if (input.eof() || input.good())
     {
-        mfxU32 bytesRead = input.gcount();
+        mfxU32 bytesRead = (mfxU32)input.gcount();
         if (bytesRead > 0)
         {
             stream.DataLength += bytesRead;
@@ -157,7 +175,7 @@ WriteBitstream::WriteBitstream(const char * filename, size_t maxSize)
     output.open(filename, std::ios::out | std::ios::binary);
     DBG(cout << "BS Open " << filename << " -> " << output.is_open() << std::endl);
     memset(&stream, 0, sizeof(stream));
-    stream.MaxLength = maxSize;
+    stream.MaxLength = (mfxU32)maxSize;
     stream.Data = new mfxU8[stream.MaxLength];
     DBG(cout << "BS Allocate " << maxSize << " bytes (" << ((float)maxSize / (1 << 20)) << " Mb)" << endl);
     CV_Assert(stream.Data);
index 1e97849..f18eafe 100644 (file)
@@ -168,7 +168,7 @@ inline void cleanup(T * &ptr)
 
 //==================================================================================================
 
-struct Plugin
+class Plugin
 {
 public:
     static Plugin * loadEncoderPlugin(MFXVideoSession &session, mfxU32 codecId)
@@ -206,7 +206,7 @@ private:
 
 //==================================================================================================
 
-struct ReadBitstream
+class ReadBitstream
 {
 public:
     ReadBitstream(const char * filename, size_t maxSize = 10 * 1024 * 1024);
@@ -225,7 +225,7 @@ public:
 
 //==================================================================================================
 
-struct WriteBitstream
+class WriteBitstream
 {
 public:
     WriteBitstream(const char * filename, size_t maxSize);
@@ -268,7 +268,7 @@ private:
     SurfacePool(const SurfacePool &);
     SurfacePool &operator=(const SurfacePool &);
 public:
-    ushort width, height;
+    size_t width, height;
     size_t oneSize;
     cv::AutoBuffer<uchar, 0> buffers;
     std::vector<mfxFrameSurface1> surfaces;
@@ -286,6 +286,7 @@ protected:
 
 
 // Linux specific
+#ifdef __linux__
 
 #include <va/va_drm.h>
 
@@ -302,7 +303,26 @@ private:
     int file;
 };
 
-// TODO: Windows specific
+#endif // __linux__
 
+// Windows specific
+#ifdef _WIN32
+
+#include <Windows.h>
+inline void sleep(unsigned long sec) { Sleep(1000 * sec); }
+
+class DXHandle : public DeviceHandler {
+public:
+    DXHandle() {}
+    ~DXHandle() {}
+private:
+    DXHandle(const DXHandle &);
+    DXHandle &operator=(const DXHandle &);
+    virtual bool initDeviceSession(MFXVideoSession &) { return true; }
+};
+
+#endif // _WIN32
+
+DeviceHandler * createDeviceHandler();
 
 #endif // MFXHELPER_H
index b5c39ca..c926611 100644 (file)
@@ -38,8 +38,7 @@ VideoCapture_IntelMFX::VideoCapture_IntelMFX(const cv::String &filename)
     mfxStatus res = MFX_ERR_NONE;
 
     // Init device and session
-
-    deviceHandler = new VAHandle();
+    deviceHandler = createDeviceHandler();
     session = new MFXVideoSession();
     if (!deviceHandler->init(*session))
     {
@@ -227,7 +226,6 @@ bool VideoCapture_IntelMFX::grabFrame()
             MSG(cerr << "MFX: Bad status: " << res << endl);
             return false;
         }
-        return false;
     }
 }
 
index 6f8700a..ccbf8e4 100644 (file)
@@ -40,8 +40,7 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc,
     }
 
     // Init device and session
-
-    deviceHandler = new VAHandle();
+    deviceHandler = createDeviceHandler();
     session = new MFXVideoSession();
     if (!deviceHandler->init(*session))
     {
@@ -71,7 +70,7 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc,
     memset(&params, 0, sizeof(params));
     params.mfx.CodecId = codecId;
     params.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED;
-    params.mfx.TargetKbps = frameSize.area() * fps / 500; // TODO: set in options
+    params.mfx.TargetKbps = (mfxU16)cvRound(frameSize.area() * fps / 500); // TODO: set in options
     params.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
     params.mfx.FrameInfo.FrameRateExtN = cvRound(fps * 1000);
     params.mfx.FrameInfo.FrameRateExtD = 1000;
@@ -80,10 +79,10 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc,
     params.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
     params.mfx.FrameInfo.CropX = 0;
     params.mfx.FrameInfo.CropY = 0;
-    params.mfx.FrameInfo.CropW = frameSize.width;
-    params.mfx.FrameInfo.CropH = frameSize.height;
-    params.mfx.FrameInfo.Width = alignSize(frameSize.width, 32);
-    params.mfx.FrameInfo.Height = alignSize(frameSize.height, 32);
+    params.mfx.FrameInfo.CropW = (mfxU16)frameSize.width;
+    params.mfx.FrameInfo.CropH = (mfxU16)frameSize.height;
+    params.mfx.FrameInfo.Width = (mfxU16)alignSize(frameSize.width, 32);
+    params.mfx.FrameInfo.Height = (mfxU16)alignSize(frameSize.height, 32);
     params.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
     res = encoder->Query(&params, &params);
     DBG(cout << "MFX Query: " << res << endl << params.mfx << params.mfx.FrameInfo);
@@ -263,7 +262,6 @@ bool VideoWriter_IntelMFX::write_one(cv::InputArray bgr)
             MSG(cerr << "MFX: Bad status: " << res << endl);
             return false;
         }
-        return true;
     }
 }