From: Maksim Shabunin Date: Tue, 17 Dec 2019 12:55:45 +0000 (+0300) Subject: CAP_MFX: surface pool with timeout, more parameters X-Git-Tag: submit/tizen/20210224.033012~2^2~198^2^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f30931848eb7cbb526e9dac7cdf7d91070e1ec25;p=platform%2Fupstream%2Fopencv.git CAP_MFX: surface pool with timeout, more parameters --- diff --git a/modules/videoio/src/cap_mfx_common.cpp b/modules/videoio/src/cap_mfx_common.cpp index 55c2450..268d8c6 100644 --- a/modules/videoio/src/cap_mfx_common.cpp +++ b/modules/videoio/src/cap_mfx_common.cpp @@ -14,10 +14,30 @@ using namespace std; 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) { mfxStatus res = MFX_ERR_NONE; - mfxIMPL impl = MFX_IMPL_AUTO_ANY; + mfxIMPL impl = getImpl(); mfxVersion ver = { {19, 1} }; res = session.Init(impl, &ver); @@ -114,11 +134,26 @@ SurfacePool::~SurfacePool() { } +SurfacePool * SurfacePool::_create(const mfxFrameAllocRequest &request, const mfxVideoParam ¶ms) +{ + return new SurfacePool(request.Info.Width, + request.Info.Height, + saturate_cast((size_t)request.NumFrameSuggested + getExtraSurfaceNum()), + params.mfx.FrameInfo); +} + mfxFrameSurface1 *SurfacePool::getFreeSurface() { - for(std::vector::iterator i = surfaces.begin(); i != surfaces.end(); ++i) - if (!i->Data.Locked) - return &(*i); + const int64 start = cv::getTickCount(); + do + { + for(std::vector::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; } diff --git a/modules/videoio/src/cap_mfx_common.hpp b/modules/videoio/src/cap_mfx_common.hpp index b4d2d9a..bef6d34 100644 --- a/modules/videoio/src/cap_mfx_common.hpp +++ b/modules/videoio/src/cap_mfx_common.hpp @@ -6,6 +6,7 @@ #define MFXHELPER_H #include "opencv2/core.hpp" +#include "opencv2/core/utils/configuration.private.hpp" #include #include @@ -259,12 +260,11 @@ public: DBG(std::cout << "MFX QueryIOSurf: " << res << std::endl); if (res < MFX_ERR_NONE) return 0; - return new SurfacePool(request.Info.Width, - request.Info.Height, - request.NumFrameSuggested, - params.mfx.FrameInfo); + return _create(request, params); } private: + static SurfacePool* _create(const mfxFrameAllocRequest& request, const mfxVideoParam& params); +private: SurfacePool(const SurfacePool &); SurfacePool &operator=(const SurfacePool &); public: @@ -285,6 +285,29 @@ protected: }; +// TODO: move to core::util? +#ifdef CV_CXX11 +#include +static void sleep_ms(int64 ms) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +} +#elif defined(__linux__) +#include +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 #ifdef __linux__ @@ -310,7 +333,6 @@ private: #ifdef _WIN32 #include -inline void sleep(unsigned long sec) { Sleep(1000 * sec); } class DXHandle : public DeviceHandler { public: diff --git a/modules/videoio/src/cap_mfx_reader.cpp b/modules/videoio/src/cap_mfx_reader.cpp index f2ec1c4..7df2cf5 100644 --- a/modules/videoio/src/cap_mfx_reader.cpp +++ b/modules/videoio/src/cap_mfx_reader.cpp @@ -214,7 +214,7 @@ bool VideoCapture_IntelMFX::grabFrame() else if (res == MFX_WRN_DEVICE_BUSY) { DBG(cout << "Waiting for device" << endl); - sleep(1); + sleep_ms(1000); continue; } else if (res == MFX_WRN_VIDEO_PARAM_CHANGED) diff --git a/modules/videoio/src/cap_mfx_writer.cpp b/modules/videoio/src/cap_mfx_writer.cpp index 8a93fc7..1279141 100644 --- a/modules/videoio/src/cap_mfx_writer.cpp +++ b/modules/videoio/src/cap_mfx_writer.cpp @@ -10,6 +10,18 @@ using namespace std; 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(res * 1000); // convert from seconds +} + inline mfxU32 codecIdByFourCC(int fourcc) { const int CC_MPG2 = FourCC('M', 'P', 'G', '2').vali32; @@ -77,7 +89,7 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc, memset(¶ms, 0, sizeof(params)); params.mfx.CodecId = codecId; params.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED; - params.mfx.TargetKbps = (mfxU16)cvRound(frameSize.area() * fps / 500); // TODO: set in options + params.mfx.TargetKbps = saturate_cast((frameSize.area() * fps) / (42.6666 * getBitrateDivisor())); // TODO: set in options params.mfx.RateControlMethod = MFX_RATECONTROL_VBR; params.mfx.FrameInfo.FrameRateExtN = cvRound(fps * 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); 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) { // ready to write @@ -239,7 +251,7 @@ bool VideoWriter_IntelMFX::write_one(cv::InputArray bgr) else if (res == MFX_WRN_DEVICE_BUSY) { DBG(cout << "Waiting for device" << endl); - sleep(1); + sleep_ms(1000); continue; } else