Skip to content

Commit 8b664d6

Browse files
committed
Merge pull request opencv#8825 from mshabunin:media-sdk-support
2 parents 43b03b6 + c06f3d6 commit 8b664d6

14 files changed

+1381
-1
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ OCV_OPTION(WITH_IPP_A "Include Intel IPP_A support" OFF
252252
OCV_OPTION(WITH_MATLAB "Include Matlab support" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT))
253253
OCV_OPTION(WITH_VA "Include VA support" OFF IF (UNIX AND NOT ANDROID) )
254254
OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" OFF IF (UNIX AND NOT ANDROID) )
255+
OCV_OPTION(WITH_MFX "Include Intel Media SDK support" OFF IF (UNIX AND NOT ANDROID) )
255256
OCV_OPTION(WITH_GDAL "Include GDAL Support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) )
256257
OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" ON IF (UNIX AND NOT ANDROID) )
257258
OCV_OPTION(WITH_LAPACK "Include Lapack library support" ON IF (NOT ANDROID AND NOT IOS) )
@@ -1228,6 +1229,10 @@ if(DEFINED WITH_INTELPERC)
12281229
status(" Intel PerC:" HAVE_INTELPERC THEN "YES" ELSE NO)
12291230
endif(DEFINED WITH_INTELPERC)
12301231

1232+
if(DEFINED WITH_MFX)
1233+
status(" Intel Media SDK:" HAVE_MFX THEN "YES (${MFX_LIBRARY})" ELSE NO)
1234+
endif()
1235+
12311236
if(DEFINED WITH_GPHOTO2)
12321237
status(" gPhoto2:" HAVE_GPHOTO2 THEN "YES" ELSE NO)
12331238
endif(DEFINED WITH_GPHOTO2)

cmake/OpenCVDetectMediaSDK.cmake

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
set(root "$ENV{MFX_HOME}")
2+
3+
find_path(MFX_INCLUDE mfxdefs.h PATHS "${root}/include" NO_DEFAULT_PATH)
4+
5+
# TODO: ICC? MINGW? ARM? IOS?
6+
if(WIN32)
7+
if(X86_64)
8+
set(arch "x64")
9+
else()
10+
set(arch "win32")
11+
endif()
12+
elseif(UNIX)
13+
set(arch "lin_x64")
14+
else()
15+
# ???
16+
endif()
17+
18+
find_library(MFX_LIBRARY mfx PATHS "${root}/lib/${arch}" NO_DEFAULT_PATH)
19+
find_library(MFX_VA_LIBRARY va)
20+
find_library(MFX_VA_DRM_LIBRARY va-drm)
21+
22+
if(MFX_INCLUDE AND MFX_LIBRARY AND MFX_VA_LIBRARY AND MFX_VA_DRM_LIBRARY)
23+
add_library(mfx-va UNKNOWN IMPORTED)
24+
set_target_properties(mfx-va PROPERTIES IMPORTED_LOCATION "${MFX_VA_LIBRARY}")
25+
26+
add_library(mfx-va-drm UNKNOWN IMPORTED)
27+
set_target_properties(mfx-va-drm PROPERTIES IMPORTED_LOCATION "${MFX_VA_DRM_LIBRARY}")
28+
29+
add_library(mfx UNKNOWN IMPORTED)
30+
set_target_properties(mfx PROPERTIES
31+
IMPORTED_LOCATION "${MFX_LIBRARY}"
32+
INTERFACE_INCLUDE_DIRECTORIES "${MFX_INCLUDE}"
33+
INTERFACE_LINK_LIBRARIES "mfx-va;mfx-va-drm;-Wl,--exclude-libs=libmfx"
34+
)
35+
set(HAVE_MFX 1)
36+
else()
37+
set(HAVE_MFX 0)
38+
endif()

cmake/OpenCVFindLibsVideo.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ if(WITH_INTELPERC)
294294
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindIntelPerCSDK.cmake")
295295
endif(WITH_INTELPERC)
296296

297+
if(WITH_MFX)
298+
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectMediaSDK.cmake")
299+
endif()
300+
297301
# --- gPhoto2 ---
298302
ocv_clear_vars(HAVE_GPHOTO2)
299303
if(WITH_GPHOTO2)

cmake/templates/cvconfig.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@
205205
/* Intel VA-API/OpenCL */
206206
#cmakedefine HAVE_VA_INTEL
207207

208+
/* Intel Media SDK */
209+
#cmakedefine HAVE_MFX
210+
208211
/* Lapack */
209212
#cmakedefine HAVE_LAPACK
210213

modules/videoio/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ if(DEFINED WINRT AND NOT DEFINED WINRT_8_0 AND NOT DEFINED ENABLE_WINRT_MODE_NAT
6161
${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/MediaStreamSink.hpp)
6262
endif()
6363

64+
if(HAVE_MFX)
65+
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_common.cpp)
66+
list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_common.hpp)
67+
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_reader.cpp)
68+
list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_reader.hpp)
69+
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_writer.cpp)
70+
list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_writer.hpp)
71+
list(APPEND VIDEOIO_LIBRARIES mfx)
72+
endif()
73+
6474
if(WIN32 AND NOT ARM)
6575
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_cmu.cpp)
6676
endif()

modules/videoio/include/opencv2/videoio.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ enum VideoCaptureAPIs {
115115
CAP_FFMPEG = 1900, //!< Open and record video file or stream using the FFMPEG library
116116
CAP_IMAGES = 2000, //!< OpenCV Image Sequence (e.g. img_%02d.jpg)
117117
CAP_ARAVIS = 2100, //!< Aravis SDK
118-
CAP_OCV_MJPEG = 2200 //!< Built-in MotionJPEG codec
118+
CAP_OCV_MJPEG = 2200, //!< Built-in MotionJPEG codec
119+
CAP_INTEL_MFX = 2300 //!< Intel MediaSDK
119120
};
120121

121122
/** @brief %VideoCapture generic properties identifier.

modules/videoio/src/cap.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
#include "cap_intelperc.hpp"
4444
#include "cap_dshow.hpp"
4545

46+
#ifdef HAVE_MFX
47+
#include "cap_mfx_reader.hpp"
48+
#include "cap_mfx_writer.hpp"
49+
#endif
50+
4651
// All WinRT versions older than 8.0 should provide classes used for video support
4752
#if defined(WINRT) && !defined(WINRT_8_0) && defined(__cplusplus_winrt)
4853
# include "cap_winrt_capture.hpp"
@@ -525,6 +530,9 @@ static Ptr<IVideoCapture> IVideoCapture_create(const String& filename)
525530
CV_CAP_ANY,
526531
#ifdef HAVE_GPHOTO2
527532
CV_CAP_GPHOTO2,
533+
#endif
534+
#ifdef HAVE_MFX
535+
CAP_INTEL_MFX,
528536
#endif
529537
-1, -1
530538
};
@@ -543,6 +551,11 @@ static Ptr<IVideoCapture> IVideoCapture_create(const String& filename)
543551
case CV_CAP_GPHOTO2:
544552
capture = createGPhoto2Capture(filename);
545553
break;
554+
#endif
555+
#ifdef HAVE_MFX
556+
case CAP_INTEL_MFX:
557+
capture = makePtr<VideoCapture_IntelMFX>(filename);
558+
break;
546559
#endif
547560
}
548561

@@ -558,9 +571,19 @@ static Ptr<IVideoCapture> IVideoCapture_create(const String& filename)
558571
static Ptr<IVideoWriter> IVideoWriter_create(int apiPreference, const String& filename, int _fourcc, double fps, Size frameSize, bool isColor)
559572
{
560573
Ptr<IVideoWriter> iwriter;
574+
#ifdef HAVE_MFX
575+
if (apiPreference == CAP_INTEL_MFX || apiPreference == CAP_ANY)
576+
{
577+
iwriter = VideoWriter_IntelMFX::create(filename, _fourcc, fps, frameSize, isColor);
578+
if (!iwriter.empty())
579+
return iwriter;
580+
}
581+
#endif
582+
561583
if( (apiPreference == CAP_OCV_MJPEG || apiPreference == CAP_ANY)
562584
&& _fourcc == CV_FOURCC('M', 'J', 'P', 'G') )
563585
iwriter = createMotionJpegWriter(filename, fps, frameSize, isColor);
586+
564587
return iwriter;
565588
}
566589

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html
4+
5+
#include "cap_mfx_common.hpp"
6+
7+
// Linux specific
8+
#include <unistd.h>
9+
#include <sys/types.h>
10+
#include <sys/stat.h>
11+
#include <fcntl.h>
12+
13+
using namespace std;
14+
using namespace cv;
15+
16+
bool DeviceHandler::init(MFXVideoSession &session)
17+
{
18+
mfxStatus res = MFX_ERR_NONE;
19+
mfxIMPL impl = MFX_IMPL_AUTO;
20+
mfxVersion ver = { {19, 1} };
21+
22+
res = session.Init(impl, &ver);
23+
DBG(cout << "MFX SessionInit: " << res << endl);
24+
25+
res = session.QueryIMPL(&impl);
26+
DBG(cout << "MFX QueryIMPL: " << res << " => " << asHex(impl) << endl);
27+
28+
res = session.QueryVersion(&ver);
29+
DBG(cout << "MFX QueryVersion: " << res << " => " << ver.Major << "." << ver.Minor << endl);
30+
31+
if (res != MFX_ERR_NONE)
32+
return false;
33+
34+
return initDeviceSession(session);
35+
}
36+
37+
//==================================================================================================
38+
39+
VAHandle::VAHandle() {
40+
// TODO: provide a way of modifying this path
41+
const string filename = "/dev/dri/card0";
42+
file = open(filename.c_str(), O_RDWR);
43+
if (file < 0)
44+
CV_Error(Error::StsError, "Can't open file: " + filename);
45+
display = vaGetDisplayDRM(file);
46+
}
47+
48+
VAHandle::~VAHandle() {
49+
if (display) {
50+
vaTerminate(display);
51+
}
52+
if (file >= 0) {
53+
close(file);
54+
}
55+
}
56+
57+
bool VAHandle::initDeviceSession(MFXVideoSession &session) {
58+
int majorVer = 0, minorVer = 0;
59+
VAStatus va_res = vaInitialize(display, &majorVer, &minorVer);
60+
DBG(cout << "vaInitialize: " << va_res << endl << majorVer << '.' << minorVer << endl);
61+
if (va_res == VA_STATUS_SUCCESS) {
62+
mfxStatus mfx_res = session.SetHandle(static_cast<mfxHandleType>(MFX_HANDLE_VA_DISPLAY), display);
63+
DBG(cout << "MFX SetHandle: " << mfx_res << endl);
64+
if (mfx_res == MFX_ERR_NONE) {
65+
return true;
66+
}
67+
}
68+
return false;
69+
}
70+
71+
//==================================================================================================
72+
73+
SurfacePool::SurfacePool(ushort width_, ushort height_, ushort count, const mfxFrameInfo &frameInfo, uchar bpp)
74+
: width(alignSize(width_, 32)),
75+
height(alignSize(height_, 32)),
76+
oneSize(width * height * bpp / 8),
77+
buffers(count * oneSize),
78+
surfaces(count)
79+
{
80+
for(int i = 0; i < count; ++i)
81+
{
82+
mfxFrameSurface1 &surface = surfaces[i];
83+
uint8_t * dataPtr = buffers + oneSize * i;
84+
memset(&surface, 0, sizeof(mfxFrameSurface1));
85+
surface.Info = frameInfo;
86+
surface.Data.Y = dataPtr;
87+
surface.Data.UV = dataPtr + width * height;
88+
surface.Data.Pitch = width;
89+
DBG(cout << "allocate surface " << (void*)&surface << ", Y = " << (void*)dataPtr << " (" << width << "x" << height << ")" << endl);
90+
}
91+
DBG(cout << "Allocated: " << endl
92+
<< "- surface data: " << buffers.size() << " bytes" << endl
93+
<< "- surface headers: " << surfaces.size() * sizeof(mfxFrameSurface1) << " bytes" << endl);
94+
}
95+
96+
SurfacePool::~SurfacePool()
97+
{
98+
}
99+
100+
mfxFrameSurface1 *SurfacePool::getFreeSurface()
101+
{
102+
for(std::vector<mfxFrameSurface1>::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
103+
if (!i->Data.Locked)
104+
return &(*i);
105+
return 0;
106+
}
107+
108+
//==================================================================================================
109+
110+
ReadBitstream::ReadBitstream(const char *filename, size_t maxSize) : drain(false)
111+
{
112+
input.open(filename, std::ios::in | std::ios::binary);
113+
DBG(cout << "Open " << filename << " -> " << input.is_open() << std::endl);
114+
memset(&stream, 0, sizeof(stream));
115+
stream.MaxLength = maxSize;
116+
stream.Data = new mfxU8[stream.MaxLength];
117+
CV_Assert(stream.Data);
118+
}
119+
120+
ReadBitstream::~ReadBitstream()
121+
{
122+
delete[] stream.Data;
123+
}
124+
125+
bool ReadBitstream::isOpened() const
126+
{
127+
return input.is_open();
128+
}
129+
130+
bool ReadBitstream::isDone() const
131+
{
132+
return input.eof();
133+
}
134+
135+
bool ReadBitstream::read()
136+
{
137+
memmove(stream.Data, stream.Data + stream.DataOffset, stream.DataLength);
138+
stream.DataOffset = 0;
139+
input.read((char*)(stream.Data + stream.DataLength), stream.MaxLength - stream.DataLength);
140+
if (input.eof() || input.good())
141+
{
142+
mfxU32 bytesRead = input.gcount();
143+
if (bytesRead > 0)
144+
{
145+
stream.DataLength += bytesRead;
146+
DBG(cout << "read " << bytesRead << " bytes" << endl);
147+
return true;
148+
}
149+
}
150+
return false;
151+
}
152+
153+
//==================================================================================================
154+
155+
WriteBitstream::WriteBitstream(const char * filename, size_t maxSize)
156+
{
157+
output.open(filename, std::ios::out | std::ios::binary);
158+
DBG(cout << "BS Open " << filename << " -> " << output.is_open() << std::endl);
159+
memset(&stream, 0, sizeof(stream));
160+
stream.MaxLength = maxSize;
161+
stream.Data = new mfxU8[stream.MaxLength];
162+
DBG(cout << "BS Allocate " << maxSize << " bytes (" << ((float)maxSize / (1 << 20)) << " Mb)" << endl);
163+
CV_Assert(stream.Data);
164+
}
165+
166+
WriteBitstream::~WriteBitstream()
167+
{
168+
delete[] stream.Data;
169+
}
170+
171+
bool WriteBitstream::write()
172+
{
173+
output.write((char*)(stream.Data + stream.DataOffset), stream.DataLength);
174+
stream.DataLength = 0;
175+
return output.good();
176+
}
177+
178+
bool WriteBitstream::isOpened() const
179+
{
180+
return output.is_open();
181+
}
182+
183+
//==================================================================================================

0 commit comments

Comments
 (0)