Merge pull request #17228 from mshabunin:mfx-surface-pool-34

pull/17273/head^2
Alexander Alekhin 5 years ago
commit 6856cc7253
  1. 43
      modules/videoio/src/cap_mfx_common.cpp
  2. 32
      modules/videoio/src/cap_mfx_common.hpp
  3. 2
      modules/videoio/src/cap_mfx_reader.cpp
  4. 18
      modules/videoio/src/cap_mfx_writer.cpp

@ -14,10 +14,30 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
static mfxIMPL getImpl()
{
static const size_t res = utils::getConfigurationParameterSizeT("OPENCV_VIDEOIO_MFX_IMPL", MFX_IMPL_AUTO_ANY);
return (mfxIMPL)res;
}
static size_t getExtraSurfaceNum()
{
static const size_t res = cv::utils::getConfigurationParameterSizeT("OPENCV_VIDEOIO_MFX_EXTRA_SURFACE_NUM", 1);
return res;
}
static size_t getPoolTimeoutSec()
{
static const size_t res = utils::getConfigurationParameterSizeT("OPENCV_VIDEOIO_MFX_POOL_TIMEOUT", 1);
return res;
}
//==================================================================================================
bool DeviceHandler::init(MFXVideoSession &session) bool DeviceHandler::init(MFXVideoSession &session)
{ {
mfxStatus res = MFX_ERR_NONE; mfxStatus res = MFX_ERR_NONE;
mfxIMPL impl = MFX_IMPL_AUTO_ANY; mfxIMPL impl = getImpl();
mfxVersion ver = { {19, 1} }; mfxVersion ver = { {19, 1} };
res = session.Init(impl, &ver); res = session.Init(impl, &ver);
@ -114,11 +134,26 @@ SurfacePool::~SurfacePool()
{ {
} }
SurfacePool * SurfacePool::_create(const mfxFrameAllocRequest &request, const mfxVideoParam &params)
{
return new SurfacePool(request.Info.Width,
request.Info.Height,
saturate_cast<ushort>((size_t)request.NumFrameSuggested + getExtraSurfaceNum()),
params.mfx.FrameInfo);
}
mfxFrameSurface1 *SurfacePool::getFreeSurface() mfxFrameSurface1 *SurfacePool::getFreeSurface()
{ {
for(std::vector<mfxFrameSurface1>::iterator i = surfaces.begin(); i != surfaces.end(); ++i) const int64 start = cv::getTickCount();
if (!i->Data.Locked) do
return &(*i); {
for(std::vector<mfxFrameSurface1>::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
if (!i->Data.Locked)
return &(*i);
sleep_ms(10);
}
while((cv::getTickCount() - start) / cv::getTickFrequency() < getPoolTimeoutSec()); // seconds
DBG(cout << "No free surface!" << std::endl);
return 0; return 0;
} }

@ -6,6 +6,7 @@
#define MFXHELPER_H #define MFXHELPER_H
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include "opencv2/core/utils/configuration.private.hpp"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -259,11 +260,10 @@ public:
DBG(std::cout << "MFX QueryIOSurf: " << res << std::endl); DBG(std::cout << "MFX QueryIOSurf: " << res << std::endl);
if (res < MFX_ERR_NONE) if (res < MFX_ERR_NONE)
return 0; return 0;
return new SurfacePool(request.Info.Width, return _create(request, params);
request.Info.Height,
request.NumFrameSuggested,
params.mfx.FrameInfo);
} }
private:
static SurfacePool* _create(const mfxFrameAllocRequest& request, const mfxVideoParam& params);
private: private:
SurfacePool(const SurfacePool &); SurfacePool(const SurfacePool &);
SurfacePool &operator=(const SurfacePool &); SurfacePool &operator=(const SurfacePool &);
@ -285,6 +285,29 @@ protected:
}; };
// TODO: move to core::util?
#ifdef CV_CXX11
#include <thread>
static void sleep_ms(int64 ms)
{
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
#elif defined(__linux__)
#include <time.h>
static void sleep_ms(int64 ms)
{
nanosleep(ms * 1000 * 1000);
}
#elif defined _WIN32
static void sleep_ms(int64 ms)
{
Sleep(ms);
}
#else
#error "Can not detect sleep_ms() implementation"
#endif
// Linux specific // Linux specific
#ifdef __linux__ #ifdef __linux__
@ -310,7 +333,6 @@ private:
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
inline void sleep(unsigned long sec) { Sleep(1000 * sec); }
class DXHandle : public DeviceHandler { class DXHandle : public DeviceHandler {
public: public:

@ -214,7 +214,7 @@ bool VideoCapture_IntelMFX::grabFrame()
else if (res == MFX_WRN_DEVICE_BUSY) else if (res == MFX_WRN_DEVICE_BUSY)
{ {
DBG(cout << "Waiting for device" << endl); DBG(cout << "Waiting for device" << endl);
sleep(1); sleep_ms(1000);
continue; continue;
} }
else if (res == MFX_WRN_VIDEO_PARAM_CHANGED) else if (res == MFX_WRN_VIDEO_PARAM_CHANGED)

@ -10,6 +10,18 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
static size_t getBitrateDivisor()
{
static const size_t res = utils::getConfigurationParameterSizeT("OPENCV_VIDEOIO_MFX_BITRATE_DIVISOR", 300);
return res;
}
static mfxU32 getWriterTimeoutMS()
{
static const size_t res = utils::getConfigurationParameterSizeT("OPENCV_VIDEOIO_MFX_WRITER_TIMEOUT", 1);
return saturate_cast<mfxU32>(res * 1000); // convert from seconds
}
inline mfxU32 codecIdByFourCC(int fourcc) inline mfxU32 codecIdByFourCC(int fourcc)
{ {
const int CC_MPG2 = FourCC('M', 'P', 'G', '2').vali32; const int CC_MPG2 = FourCC('M', 'P', 'G', '2').vali32;
@ -77,7 +89,7 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.mfx.CodecId = codecId; params.mfx.CodecId = codecId;
params.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED; params.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED;
params.mfx.TargetKbps = (mfxU16)cvRound(frameSize.area() * fps / 500); // TODO: set in options params.mfx.TargetKbps = saturate_cast<mfxU16>((frameSize.area() * fps) / (42.6666 * getBitrateDivisor())); // TODO: set in options
params.mfx.RateControlMethod = MFX_RATECONTROL_VBR; params.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
params.mfx.FrameInfo.FrameRateExtN = cvRound(fps * 1000); params.mfx.FrameInfo.FrameRateExtN = cvRound(fps * 1000);
params.mfx.FrameInfo.FrameRateExtD = 1000; params.mfx.FrameInfo.FrameRateExtD = 1000;
@ -210,7 +222,7 @@ bool VideoWriter_IntelMFX::write_one(cv::InputArray bgr)
res = encoder->EncodeFrameAsync(NULL, workSurface, &bs->stream, &sync); res = encoder->EncodeFrameAsync(NULL, workSurface, &bs->stream, &sync);
if (res == MFX_ERR_NONE) if (res == MFX_ERR_NONE)
{ {
res = session->SyncOperation(sync, 1000); // 1 sec, TODO: provide interface to modify timeout res = session->SyncOperation(sync, getWriterTimeoutMS()); // TODO: provide interface to modify timeout
if (res == MFX_ERR_NONE) if (res == MFX_ERR_NONE)
{ {
// ready to write // ready to write
@ -239,7 +251,7 @@ bool VideoWriter_IntelMFX::write_one(cv::InputArray bgr)
else if (res == MFX_WRN_DEVICE_BUSY) else if (res == MFX_WRN_DEVICE_BUSY)
{ {
DBG(cout << "Waiting for device" << endl); DBG(cout << "Waiting for device" << endl);
sleep(1); sleep_ms(1000);
continue; continue;
} }
else else

Loading…
Cancel
Save