diff --git a/modules/gapi/perf/streaming/gapi_streaming_source_perf_tests.cpp b/modules/gapi/perf/streaming/gapi_streaming_source_perf_tests.cpp new file mode 100644 index 000000000000..b4b141523306 --- /dev/null +++ b/modules/gapi/perf/streaming/gapi_streaming_source_perf_tests.cpp @@ -0,0 +1,79 @@ +// 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. +// +// Copyright (C) 2021 Intel Corporation + + +#include "../perf_precomp.hpp" +#include "../../test/common/gapi_tests_common.hpp" +#include +#include + +namespace opencv_test +{ +using namespace perf; + +const std::string files[] = { + "highgui/video/big_buck_bunny.h265", + "highgui/video/big_buck_bunny.h264", +}; + +const std::string codec[] = { + "MFX_CODEC_HEVC", + "MFX_CODEC_AVC" +}; + +using source_t = std::string; +using codec_t = std::string; +using source_description_t = std::tuple; + +class OneVPLSourcePerfTest : public TestPerfParams {}; +class VideoCapSourcePerfTest : public TestPerfParams {}; + +PERF_TEST_P_(OneVPLSourcePerfTest, TestPerformance) +{ + using namespace cv::gapi::wip; + + const auto params = GetParam(); + source_t src = findDataFile(get<0>(params)); + codec_t type = get<1>(params); + + std::vector cfg_params { + oneVPL_cfg_param::create("mfxImplDescription.Impl", "MFX_IMPL_TYPE_HARDWARE"), + oneVPL_cfg_param::create("mfxImplDescription.mfxDecoderDescription.decoder.CodecID", type), + }; + + auto source_ptr = make_vpl_src(src, cfg_params); + Data out; + TEST_CYCLE() + { + source_ptr->pull(out); + } + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(VideoCapSourcePerfTest, TestPerformance) +{ + using namespace cv::gapi::wip; + + source_t src = findDataFile(GetParam()); + auto source_ptr = make_src(src); + Data out; + TEST_CYCLE() + { + source_ptr->pull(out); + } + + SANITY_CHECK_NOTHING(); +} + +INSTANTIATE_TEST_CASE_P(Streaming, OneVPLSourcePerfTest, + Values(source_description_t(files[0], codec[0]), + source_description_t(files[1], codec[1]))); + +INSTANTIATE_TEST_CASE_P(Streaming, VideoCapSourcePerfTest, + Values(files[0], + files[1])); +} // namespace opencv_test diff --git a/modules/gapi/samples/infer_single_roi.cpp b/modules/gapi/samples/infer_single_roi.cpp index 6054a3f4a629..fcef19db49f8 100644 --- a/modules/gapi/samples/infer_single_roi.cpp +++ b/modules/gapi/samples/infer_single_roi.cpp @@ -256,9 +256,17 @@ int main(int argc, char *argv[]) pipeline.start(); cv::Mat out; + int framesCount = 0; + cv::TickMeter t; + t.start(); while (pipeline.pull(cv::gout(out))) { cv::imshow("Out", out); cv::waitKey(1); + framesCount++; } + t.stop(); + std::cout << "Elapsed time: " << t.getTimeSec() << std::endl; + std::cout << "FPS: " << framesCount / t.getTimeSec() << std::endl; + std::cout << "framesCount: " << framesCount << std::endl; return 0; } diff --git a/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.cpp b/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.cpp index c352c509c2f4..6a9a16862db0 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.cpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.cpp @@ -107,7 +107,7 @@ VPLCPUAccelerationPolicy::create_surface_pool(size_t pool_size, size_t surface_s // remember pool by key GAPI_LOG_INFO(nullptr, "New pool allocated, key: " << preallocated_pool_memory_ptr << - ", surface count: " << pool.size() << + ", surface count: " << pool.total_size() << ", surface size bytes: " << surface_size_bytes); try { if (!pool_table.emplace(preallocated_pool_memory_ptr, std::move(pool)).second) { @@ -132,27 +132,7 @@ VPLCPUAccelerationPolicy::surface_weak_ptr_t VPLCPUAccelerationPolicy::get_free_ } pool_t& requested_pool = pool_it->second; -#ifdef TEST_PERF return requested_pool.find_free(); -#else // TEST_PERF - auto it = - std::find_if(requested_pool.begin(), requested_pool.end(), - [](const surface_ptr_t& val) { - GAPI_DbgAssert(val && "Pool contains empty surface"); - return !val->get_locks_count(); - }); - - // Limitation realloc pool might be a future extension - if (it == requested_pool.end()) { - std::stringstream ss; - ss << "cannot get free surface from pool, key: " << key << ", size: " << requested_pool.size(); - const std::string& str = ss.str(); - GAPI_LOG_WARNING(nullptr, str); - throw std::runtime_error(std::string(__FUNCTION__) + " - " + str); - } - - return *it; -#endif // TEST_PERF } size_t VPLCPUAccelerationPolicy::get_free_surface_count(pool_key_t key) const { @@ -162,18 +142,8 @@ size_t VPLCPUAccelerationPolicy::get_free_surface_count(pool_key_t key) const { ", table size: " << pool_table.size()); return 0; } -#ifdef TEST_PERF - return 0; -#else // TEST_PERF const pool_t& requested_pool = pool_it->second; - size_t free_surf_count = - std::count_if(requested_pool.begin(), requested_pool.end(), - [](const surface_ptr_t& val) { - GAPI_Assert(val && "Pool contains empty surface"); - return !val->get_locks_count(); - }); - return free_surf_count; -#endif // TEST_PERF + return requested_pool.available_size(); } size_t VPLCPUAccelerationPolicy::get_surface_count(pool_key_t key) const { @@ -183,11 +153,8 @@ size_t VPLCPUAccelerationPolicy::get_surface_count(pool_key_t key) const { ", table size: " << pool_table.size()); return 0; } -#ifdef TEST_PERF - return 0; -#else // TEST_PERF - return pool_it->second.size(); -#endif // TEST_PERF + + return pool_it->second.total_size(); } cv::MediaFrame::AdapterPtr VPLCPUAccelerationPolicy::create_frame_adapter(pool_key_t key, @@ -202,28 +169,7 @@ cv::MediaFrame::AdapterPtr VPLCPUAccelerationPolicy::create_frame_adapter(pool_k } pool_t& requested_pool = pool_it->second; -#ifdef TEST_PERF return cv::MediaFrame::AdapterPtr{new VPLMediaFrameCPUAdapter(requested_pool.find_by_handle(surface))}; -#else // TEST_PERF - auto it = - std::find_if(requested_pool.begin(), requested_pool.end(), - [surface](const surface_ptr_t& val) { - GAPI_DbgAssert(val && "Pool contains empty surface"); - return val->get_handle() == surface; - }); - - // Limitation realloc pool might be a future extension - if (it == requested_pool.end()) { - std::stringstream ss; - ss << "cannot get requested surface from pool, key: " << key << ", surf: " - << surface << ", pool size: " << requested_pool.size(); - const std::string& str = ss.str(); - GAPI_LOG_WARNING(nullptr, str); - throw std::runtime_error(std::string(__FUNCTION__) + " - " + str); - } - - return cv::MediaFrame::AdapterPtr{new VPLMediaFrameCPUAdapter(*it)}; -#endif // TEST_PERF } } // namespace wip } // namespace gapi diff --git a/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.hpp b/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.hpp index ea326d234e92..2cfefafde7fd 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.hpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.hpp @@ -15,9 +15,7 @@ #ifdef HAVE_ONEVPL #include #include "streaming/onevpl/accelerators/accel_policy_interface.hpp" -#ifdef TEST_PERF #include "streaming/onevpl/accelerators/surface/surface_pool.hpp" -#endif // TEST_PERF namespace cv { namespace gapi { @@ -28,11 +26,8 @@ struct VPLCPUAccelerationPolicy final : public VPLAccelerationPolicy // GAPI_EXPORTS for tests GAPI_EXPORTS VPLCPUAccelerationPolicy(); GAPI_EXPORTS ~VPLCPUAccelerationPolicy(); -#ifdef TEST_PERF + using pool_t = CachedPool; -#else // TEST_PERF - using pool_t = std::vector; -#endif // TEST_PERF GAPI_EXPORTS void init(session_t session) override; GAPI_EXPORTS void deinit(session_t session) override; diff --git a/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.cpp b/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.cpp index 10e145c9a9d9..1e6b06b5048d 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.cpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.cpp @@ -10,7 +10,7 @@ void CachedPool::reserve(size_t size) { surfaces.reserve(size); } -size_t CachedPool::size() const { +size_t CachedPool::total_size() const { return surfaces.size(); } @@ -26,6 +26,17 @@ void CachedPool::push_back(surface_ptr_t &&surf) { next_free_it = surfaces.begin(); } +size_t CachedPool::available_size() const { + + size_t free_surf_count = + std::count_if(surfaces.begin(), surfaces.end(), + [](const surface_ptr_t& val) { + GAPI_DbgAssert(val && "Pool contains empty surface"); + return !val->get_locks_count(); + }); + return free_surf_count; +} + CachedPool::surface_ptr_t CachedPool::find_free() { auto it = diff --git a/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.hpp b/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.hpp index a1eba15616b6..09779a1dc1ac 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.hpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.hpp @@ -29,8 +29,10 @@ class CachedPool { // GAPI_EXPORTS for tests GAPI_EXPORTS void push_back(surface_ptr_t &&surf); GAPI_EXPORTS void reserve(size_t size); - GAPI_EXPORTS size_t size() const; + GAPI_EXPORTS size_t total_size() const; + GAPI_EXPORTS size_t available_size() const; GAPI_EXPORTS void clear(); + GAPI_EXPORTS surface_ptr_t find_free(); GAPI_EXPORTS surface_ptr_t find_by_handle(mfxFrameSurface1* handle); private: diff --git a/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp b/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp index 2b8e33cf76b7..e5fbe928bd87 100644 --- a/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp +++ b/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp @@ -20,7 +20,7 @@ namespace cv { namespace gapi { namespace wip { /* UTILS */ -mfxU32 GetSurfaceSize(mfxU32 FourCC, mfxU32 width, mfxU32 height) { +mfxU32 GetSurfaceSize_(mfxU32 FourCC, mfxU32 width, mfxU32 height) { mfxU32 nbytes = 0; mfxU32 half_width = width / 2; @@ -45,7 +45,7 @@ mfxU32 GetSurfaceSize(mfxU32 FourCC, mfxU32 width, mfxU32 height) { return nbytes; } -surface_ptr_t create_surface_RGB4(mfxFrameInfo frameInfo, +surface_ptr_t create_surface_RGB4_(mfxFrameInfo frameInfo, std::shared_ptr out_buf_ptr, size_t out_buf_ptr_offset, size_t out_buf_size) @@ -78,7 +78,7 @@ surface_ptr_t create_surface_RGB4(mfxFrameInfo frameInfo, return Surface::create_surface(std::move(handle), out_buf_ptr); } -surface_ptr_t create_surface_other(mfxFrameInfo frameInfo, +surface_ptr_t create_surface_other_(mfxFrameInfo frameInfo, std::shared_ptr out_buf_ptr, size_t out_buf_ptr_offset, size_t out_buf_size) @@ -110,62 +110,95 @@ surface_ptr_t create_surface_other(mfxFrameInfo frameInfo, return Surface::create_surface(std::move(handle), out_buf_ptr); } -VPLLegacyDecodeEngine::VPLLegacyDecodeEngine(std::unique_ptr&& accel) +VPLLegacyDecodeEngineAsync::VPLLegacyDecodeEngineAsync(std::unique_ptr&& accel) : ProcessingEngineBase(std::move(accel)) { GAPI_LOG_INFO(nullptr, "Create Legacy Decode Engine"); create_pipeline( - // 1) Reade File + // 1) Read File [this] (EngineSession& sess) -> ExecutionStatus { - LegacyDecodeSession &my_sess = static_cast(sess); + LegacyDecodeSessionAsync &my_sess = static_cast(sess); my_sess.last_status = ReadEncodedStream(my_sess.stream, my_sess.data_provider); if (my_sess.last_status != MFX_ERR_NONE) { my_sess.data_provider.reset(); //close source } return ExecutionStatus::Continue; }, - // 2) enqueue ASYNC decode + // 2) enqueue ASYNC decode operation [this] (EngineSession& sess) -> ExecutionStatus { - LegacyDecodeSession &my_sess = static_cast(sess); + LegacyDecodeSessionAsync &my_sess = static_cast(sess); + // prepare sync object for new surface + LegacyDecodeSessionAsync::op_handle_t sync_pair{}; + + // queue qecode operation my_sess.last_status = MFXVideoDECODE_DecodeFrameAsync(my_sess.session, my_sess.last_status == MFX_ERR_NONE ? &my_sess.stream : nullptr, /* No more data to read, start decode draining mode*/ my_sess.procesing_surface_ptr.lock()->get_handle(), - &my_sess.output_surface_ptr, - &my_sess.sync); + &sync_pair.second, + &sync_pair.first); + + // process wait-like statuses in-place + while (my_sess.last_status == MFX_ERR_MORE_SURFACE || + my_sess.last_status == MFX_WRN_DEVICE_BUSY) { + try { + if (my_sess.last_status == MFX_ERR_MORE_SURFACE) { + my_sess.swap_surface(*this); + } + my_sess.last_status = + MFXVideoDECODE_DecodeFrameAsync(my_sess.session, + &my_sess.stream, + my_sess.procesing_surface_ptr.lock()->get_handle(), + &sync_pair.second, + &sync_pair.first); + + } catch (const std::exception& ex) { + GAPI_LOG_WARNING(nullptr, "[" << my_sess.session << "] error: " << ex.what() << + "Abort"); + } + } + + if (my_sess.last_status == MFX_ERR_NONE) { + my_sess.sync_queue.emplace(sync_pair); + } else if (MFX_ERR_MORE_DATA != my_sess.last_status) /* suppress MFX_ERR_MORE_DATA warning */ { + GAPI_LOG_WARNING(nullptr, "pending ops count: " << my_sess.sync_queue.size() << + ", sync id: " << sync_pair.first << + ", status: " << mfxstatus_to_string(my_sess.last_status)); + } return ExecutionStatus::Continue; }, // 3) Wait for ASYNC decode result [this] (EngineSession& sess) -> ExecutionStatus { - if (sess.last_status == MFX_ERR_NONE) // Got 1 decoded frame + LegacyDecodeSessionAsync& my_sess = static_cast(sess); + if (!my_sess.sync_queue.empty()) // FIFO: check the oldest async operation complete { - do { - //TODO try to extract TIMESTAMP - sess.last_status = MFXVideoCORE_SyncOperation(sess.session, sess.sync, 100); - if (MFX_ERR_NONE == sess.last_status) { - - LegacyDecodeSession& my_sess = static_cast(sess); - on_frame_ready(my_sess); - } - } while (sess.last_status == MFX_WRN_IN_EXECUTION); + LegacyDecodeSessionAsync::op_handle_t& pending_op = my_sess.sync_queue.front(); + sess.last_status = MFXVideoCORE_SyncOperation(sess.session, pending_op.first, 0); + + GAPI_LOG_DEBUG(nullptr, "pending ops count: " << my_sess.sync_queue.size() << + ", sync id: " << pending_op.first << + ", status: " << mfxstatus_to_string(my_sess.last_status)); + if (MFX_ERR_NONE == sess.last_status) { + on_frame_ready(my_sess, pending_op.second); + } } return ExecutionStatus::Continue; }, // 4) Falls back on generic status procesing [this] (EngineSession& sess) -> ExecutionStatus { - return this->process_error(sess.last_status, static_cast(sess)); + return this->process_error(sess.last_status, static_cast(sess)); } ); } -void VPLLegacyDecodeEngine::initialize_session(mfxSession mfx_session, +void VPLLegacyDecodeEngineAsync::initialize_session(mfxSession mfx_session, DecoderParams&& decoder_param, std::shared_ptr provider) { @@ -178,7 +211,7 @@ void VPLLegacyDecodeEngine::initialize_session(mfxSession mfx_session, ", mfxFrameAllocRequest.NumFrameSuggested: " << decRequest.NumFrameSuggested << ", mfxFrameAllocRequest.Type: " << decRequest.Type); - mfxU32 singleSurfaceSize = GetSurfaceSize(decoder_param.param.mfx.FrameInfo.FourCC, + mfxU32 singleSurfaceSize = GetSurfaceSize_(decoder_param.param.mfx.FrameInfo.FourCC, decoder_param.param.mfx.FrameInfo.Width, decoder_param.param.mfx.FrameInfo.Height); if (!singleSurfaceSize) { @@ -193,9 +226,9 @@ void VPLLegacyDecodeEngine::initialize_session(mfxSession mfx_session, [&frameInfo] (std::shared_ptr out_buf_ptr, size_t out_buf_ptr_offset, size_t out_buf_size) -> surface_ptr_t { return (frameInfo.FourCC == MFX_FOURCC_RGB4) ? - create_surface_RGB4(frameInfo, out_buf_ptr, out_buf_ptr_offset, + create_surface_RGB4_(frameInfo, out_buf_ptr, out_buf_ptr_offset, out_buf_size) : - create_surface_other(frameInfo, out_buf_ptr, out_buf_ptr_offset, + create_surface_other_(frameInfo, out_buf_ptr, out_buf_ptr_offset, out_buf_size);}; //TODO Configure preallocation size (how many frames we can hold) @@ -206,8 +239,8 @@ void VPLLegacyDecodeEngine::initialize_session(mfxSession mfx_session, surface_creator); // create session - std::shared_ptr sess_ptr = - register_session(mfx_session, + std::shared_ptr sess_ptr = + register_session(mfx_session, std::move(decoder_param), provider); @@ -216,27 +249,39 @@ void VPLLegacyDecodeEngine::initialize_session(mfxSession mfx_session, sess_ptr->swap_surface(*this); } -ProcessingEngineBase::ExecutionStatus VPLLegacyDecodeEngine::execute_op(operation_t& op, EngineSession& sess) { +ProcessingEngineBase::ExecutionStatus VPLLegacyDecodeEngineAsync::execute_op(operation_t& op, EngineSession& sess) { return op(sess); } -void VPLLegacyDecodeEngine::on_frame_ready(LegacyDecodeSession& sess) +void VPLLegacyDecodeEngineAsync::on_frame_ready(LegacyDecodeSessionAsync& sess, mfxFrameSurface1* ready_surface) { GAPI_LOG_DEBUG(nullptr, "[" << sess.session << "], frame ready"); // manage memory ownership rely on acceleration policy auto frame_adapter = acceleration_policy->create_frame_adapter(sess.decoder_pool_id, - sess.output_surface_ptr); + ready_surface); ready_frames.emplace(cv::MediaFrame(std::move(frame_adapter)), sess.generate_frame_meta()); + + // pop ready sync onject + sess.sync_queue.pop(); } -ProcessingEngineBase::ExecutionStatus VPLLegacyDecodeEngine::process_error(mfxStatus status, LegacyDecodeSession& sess) +ProcessingEngineBase::ExecutionStatus VPLLegacyDecodeEngineAsync::process_error(mfxStatus status, LegacyDecodeSessionAsync& sess) { GAPI_LOG_DEBUG(nullptr, "status: " << mfxstatus_to_string(status)); switch (status) { case MFX_ERR_NONE: - return ExecutionStatus::Continue; + { + // prepare sync object for new surface + try { + sess.swap_surface(*this); + return ExecutionStatus::Continue; + } catch (const std::exception& ex) { + GAPI_LOG_WARNING(nullptr, "[" << sess.session << "] error: " << ex.what() << + "Abort"); + } + } case MFX_ERR_MORE_DATA: // The function requires more bitstream at input before decoding can proceed if (!sess.data_provider || sess.data_provider->empty()) { // No more data to drain from decoder, start encode draining mode @@ -262,27 +307,27 @@ ProcessingEngineBase::ExecutionStatus VPLLegacyDecodeEngine::process_error(mfxSt case MFX_ERR_DEVICE_LOST: // For non-CPU implementations, // Cleanup if device is lost - GAPI_DbgAssert(false && "VPLLegacyDecodeEngine::process_error - " + GAPI_DbgAssert(false && "VPLLegacyDecodeEngineAsync::process_error - " "MFX_ERR_DEVICE_LOST is not processed"); break; case MFX_WRN_DEVICE_BUSY: // For non-CPU implementations, // Wait a few milliseconds then try again - GAPI_DbgAssert(false && "VPLLegacyDecodeEngine::process_error - " + GAPI_DbgAssert(false && "VPLLegacyDecodeEngineAsync::process_error - " "MFX_WRN_DEVICE_BUSY is not processed"); break; case MFX_WRN_VIDEO_PARAM_CHANGED: // The decoder detected a new sequence header in the bitstream. // Video parameters may have changed. // In external memory allocation case, might need to reallocate the output surface - GAPI_DbgAssert(false && "VPLLegacyDecodeEngine::process_error - " + GAPI_DbgAssert(false && "VPLLegacyDecodeEngineAsync::process_error - " "MFX_WRN_VIDEO_PARAM_CHANGED is not processed"); break; case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM: // The function detected that video parameters provided by the application // are incompatible with initialization parameters. // The application should close the component and then reinitialize it - GAPI_DbgAssert(false && "VPLLegacyDecodeEngine::process_error - " + GAPI_DbgAssert(false && "VPLLegacyDecodeEngineAsync::process_error - " "MFX_ERR_INCOMPATIBLE_VIDEO_PARAM is not processed"); break; case MFX_ERR_REALLOC_SURFACE: @@ -290,11 +335,20 @@ ProcessingEngineBase::ExecutionStatus VPLLegacyDecodeEngine::process_error(mfxSt // mfxInfoMFX::EnableReallocRequest was set to ON during initialization. // This applies to external memory allocations and should not be expected for // a simple internal allocation case like this - GAPI_DbgAssert(false && "VPLLegacyDecodeEngine::process_error - " + GAPI_DbgAssert(false && "VPLLegacyDecodeEngineAsync::process_error - " "MFX_ERR_REALLOC_SURFACE is not processed"); break; + case MFX_WRN_IN_EXECUTION: + try { + sess.swap_surface(*this); + return ExecutionStatus::Continue; + } catch (const std::exception& ex) { + GAPI_LOG_WARNING(nullptr, "[" << sess.session << "] error: " << ex.what() << + "Abort"); + } default: - GAPI_LOG_WARNING(nullptr, "Unknown status code: " << mfxstatus_to_string(status)); + GAPI_LOG_WARNING(nullptr, "Unknown status code: " << mfxstatus_to_string(status) << + ", decoded frames: " << sess.decoded_frames_count); break; } diff --git a/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.hpp b/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.hpp index db4a2519ff41..db6ac8e53636 100644 --- a/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.hpp +++ b/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.hpp @@ -4,8 +4,8 @@ // // Copyright (C) 2021 Intel Corporation -#ifndef GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_ENGINE_LEGACY_HPP -#define GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_ENGINE_LEGACY_HPP +#ifndef GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_ENGINE_ASYNC_HPP +#define GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_ENGINE_ASYNC_HPP #include #include @@ -22,26 +22,26 @@ namespace gapi { namespace wip { -class LegacyDecodeSession; +class LegacyDecodeSessionAsync; struct DecoderParams; struct IDataProvider; struct VPLAccelerationPolicy; -class VPLLegacyDecodeEngine : public ProcessingEngineBase { +class VPLLegacyDecodeEngineAsync : public ProcessingEngineBase { public: - VPLLegacyDecodeEngine(std::unique_ptr&& accel); + VPLLegacyDecodeEngineAsync(std::unique_ptr&& accel); void initialize_session(mfxSession mfx_session, DecoderParams&& decoder_param, std::shared_ptr provider) override; private: ExecutionStatus execute_op(operation_t& op, EngineSession& sess) override; - ExecutionStatus process_error(mfxStatus status, LegacyDecodeSession& sess); + ExecutionStatus process_error(mfxStatus status, LegacyDecodeSessionAsync& sess); - void on_frame_ready(LegacyDecodeSession& sess); + void on_frame_ready(LegacyDecodeSessionAsync& sess, mfxFrameSurface1* ready_surface); }; } // namespace wip } // namespace gapi } // namespace cv #endif // HAVE_ONEVPL -#endif // GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_ENGINE_LEGACY_HPP +#endif // GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_ENGINE_ASYNC_HPP diff --git a/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.cpp b/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.cpp index 5653bb499491..7cb145d83df9 100644 --- a/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.cpp +++ b/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.cpp @@ -17,33 +17,34 @@ namespace cv { namespace gapi { namespace wip { -LegacyDecodeSession::LegacyDecodeSession(mfxSession sess, +LegacyDecodeSessionAsync::LegacyDecodeSessionAsync(mfxSession sess, DecoderParams&& decoder_param, std::shared_ptr provider) : EngineSession(sess, std::move(decoder_param.stream)), mfx_decoder_param(std::move(decoder_param.param)), data_provider(std::move(provider)), procesing_surface_ptr(), - output_surface_ptr(), + sync_queue(), decoded_frames_count() { } -LegacyDecodeSession::~LegacyDecodeSession() +LegacyDecodeSessionAsync::~LegacyDecodeSessionAsync() { GAPI_LOG_INFO(nullptr, "Close Decode for session: " << session); MFXVideoDECODE_Close(session); } -void LegacyDecodeSession::swap_surface(VPLLegacyDecodeEngine& engine) { +void LegacyDecodeSessionAsync::swap_surface(VPLLegacyDecodeEngineAsync& engine) { VPLAccelerationPolicy* acceleration_policy = engine.get_accel(); GAPI_Assert(acceleration_policy && "Empty acceleration_policy"); - auto old_locked = procesing_surface_ptr.lock(); try { auto cand = acceleration_policy->get_free_surface(decoder_pool_id).lock(); GAPI_LOG_DEBUG(nullptr, "[" << session << "] swap surface" - ", old: " << (old_locked ? old_locked->get_handle() : nullptr) << + ", old: " << (!procesing_surface_ptr.expired() + ? procesing_surface_ptr.lock()->get_handle() + : nullptr) << ", new: "<< cand->get_handle()); procesing_surface_ptr = cand; @@ -53,12 +54,12 @@ void LegacyDecodeSession::swap_surface(VPLLegacyDecodeEngine& engine) { } } -void LegacyDecodeSession::init_surface_pool(VPLAccelerationPolicy::pool_key_t key) { +void LegacyDecodeSessionAsync::init_surface_pool(VPLAccelerationPolicy::pool_key_t key) { GAPI_Assert(key && "Init decode pull with empty key"); decoder_pool_id = key; } -Data::Meta LegacyDecodeSession::generate_frame_meta() { +Data::Meta LegacyDecodeSessionAsync::generate_frame_meta() { const auto now = std::chrono::system_clock::now(); const auto dur = std::chrono::duration_cast (now.time_since_epoch()); diff --git a/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.hpp b/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.hpp index bc6d7a479026..6dc7752a7199 100644 --- a/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.hpp +++ b/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.hpp @@ -4,10 +4,11 @@ // // Copyright (C) 2021 Intel Corporation -#ifndef GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_SESSION_HPP -#define GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_SESSION_HPP +#ifndef GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_SESSION_ASYNC_HPP +#define GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_SESSION_ASYNC_HPP #include #include +#include #include "streaming/onevpl/engine/engine_session.hpp" #include "streaming/onevpl/accelerators/accel_policy_interface.hpp" @@ -25,15 +26,15 @@ struct IDataProvider; class Surface; struct VPLAccelerationPolicy; -class LegacyDecodeSession : public EngineSession { +class LegacyDecodeSessionAsync : public EngineSession { public: - friend class VPLLegacyDecodeEngine; + friend class VPLLegacyDecodeEngineAsync; - LegacyDecodeSession(mfxSession sess, DecoderParams&& decoder_param, std::shared_ptr provider); - ~LegacyDecodeSession(); + LegacyDecodeSessionAsync(mfxSession sess, DecoderParams&& decoder_param, std::shared_ptr provider); + ~LegacyDecodeSessionAsync(); using EngineSession::EngineSession; - void swap_surface(VPLLegacyDecodeEngine& engine); + void swap_surface(VPLLegacyDecodeEngineAsync& engine); void init_surface_pool(VPLAccelerationPolicy::pool_key_t key); mfxVideoParam mfx_decoder_param; @@ -45,12 +46,13 @@ class LegacyDecodeSession : public EngineSession { mfxFrameAllocRequest request; std::weak_ptr procesing_surface_ptr; - mfxFrameSurface1* output_surface_ptr; + using op_handle_t = std::pair; + std::queue sync_queue; int64_t decoded_frames_count; }; } // namespace wip } // namespace gapi } // namespace cv #endif // HAVE_ONEVPL -#endif // GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_SESSION_HPP +#endif // GAPI_STREAMING_ONVPL_ENGINE_DECODE_DECODE_SESSION_ASYNC_HPP diff --git a/modules/gapi/src/streaming/onevpl/onevpl_source_priv.cpp b/modules/gapi/src/streaming/onevpl/onevpl_source_priv.cpp index 4163c6a8a402..85c3c8077941 100644 --- a/modules/gapi/src/streaming/onevpl/onevpl_source_priv.cpp +++ b/modules/gapi/src/streaming/onevpl/onevpl_source_priv.cpp @@ -205,7 +205,7 @@ OneVPLSource::Priv::Priv(std::shared_ptr provider, const std::vec } else { - engine.reset(new VPLLegacyDecodeEngine(std::move(acceleration))); + engine.reset(new VPLLegacyDecodeEngineAsync(std::move(acceleration))); } } diff --git a/modules/gapi/src/streaming/onevpl/onevpl_utils.cpp b/modules/gapi/src/streaming/onevpl/onevpl_utils.cpp index 9a7212a3a80d..7ecc3f5abb84 100644 --- a/modules/gapi/src/streaming/onevpl/onevpl_utils.cpp +++ b/modules/gapi/src/streaming/onevpl/onevpl_utils.cpp @@ -386,6 +386,8 @@ std::string mfxstatus_to_string(mfxStatus err) { return "MFX_WRN_DEVICE_BUSY"; case MFX_WRN_VIDEO_PARAM_CHANGED: return "MFX_WRN_VIDEO_PARAM_CHANGED"; + case MFX_WRN_IN_EXECUTION: + return "MFX_WRN_IN_EXECUTION"; default: