From 5bff7b02e98facc5427a2f6f763b0199a8cf6e44 Mon Sep 17 00:00:00 2001 From: zhangyichix Date: Mon, 21 Apr 2025 10:13:30 +0800 Subject: [PATCH 1/2] Fix detach surface cts test run timeout issue The issue is detach surface cts test run timeout, cause is it keeps reallocating surface when the allocated surface is not in cached buffer pool. After removing the InCache() limitation, sometimes we get a locked block which is still used by onevpl and will cause random fail. Solution is 1) Remove code to check if allocated surfce is in cache. 2) For detached surface situation, when get locked surface we keep fetching new surface from framework until we get an unlocked one. Tracked-On: OAM-132019 Signed-off-by: Lina Sun Signed-off-by: zhangyichix --- .../src/mfx_c2_decoder_component.cpp | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index ecc57a5c..880c5866 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -1831,28 +1831,6 @@ c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t heig C2MemoryUsage mem_usage = {m_consumerUsage, C2AndroidMemoryUsage::HW_CODEC_WRITE}; res = m_c2Allocator->fetchGraphicBlock(width, height, MfxFourCCToGralloc(fourcc), mem_usage, out_block); - if (res == C2_OK) { - auto hndl_deleter = [](native_handle_t *hndl) { - native_handle_delete(hndl); - hndl = nullptr; - }; - - std::unique_ptr hndl( - android::UnwrapNativeCodec2GrallocHandle((*out_block)->handle()), hndl_deleter); - - uint64_t id; - if (C2_OK != MfxGrallocInstance::getInstance()->GetBackingStore(hndl.get(), &id)) - return C2_CORRUPTED; - if(!m_vppConversion) { - if (m_allocator && !m_allocator->InCache(id)) { - res = C2_BLOCKING; - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - // If always fetch a nocached block, check if width or height have changed - // compare to when it was initialized. - MFX_DEBUG_TRACE_STREAM("fetchGraphicBlock a nocached block, please retune output blocks. id = " << id); - } - } - } } else if (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY) { C2MemoryUsage mem_usage = {m_consumerUsage, C2MemoryUsage::CPU_WRITE}; res = m_c2Allocator->fetchGraphicBlock(width, height, @@ -1934,12 +1912,57 @@ c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out, bool } m_surfaces.emplace(id, frame_out->GetMfxFrameSurface()); } else { - if (it->second->Data.Locked) { - /* Buffer locked, try next block. */ - MFX_DEBUG_TRACE_PRINTF("Buffer still locked, try next block"); - res = C2_TIMED_OUT; - } else { + if(!it->second->Data.Locked) { *frame_out = MfxC2FrameOut(std::move(out_block), it->second); + } else { + // when surface detached in framework, keep AllocateC2Block until we get an unlocked surface. + std::list block_pool; + std::shared_ptr new_block; + bool found_surface = false; + + while (it != m_surfaces.end() && !found_surface) { + // Buffer locked, try next block. + res = AllocateC2Block(MFXGetSurfaceWidth(m_mfxVideoParams.mfx.FrameInfo, m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY), + MFXGetSurfaceHeight(m_mfxVideoParams.mfx.FrameInfo, m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY), + m_mfxVideoParams.mfx.FrameInfo.FourCC, &new_block); + + if (C2_TIMED_OUT == res) continue; + + if (C2_OK != res) break; + + block_pool.push_back(*new_block); + + std::unique_ptr new_hndl( + android::UnwrapNativeCodec2GrallocHandle(new_block->handle()), hndl_deleter); + + if(new_hndl == nullptr) + { + return C2_NO_MEMORY; + } + + it = m_surfaces.end(); + + if (C2_OK != MfxGrallocInstance::getInstance()->GetBackingStore(new_hndl.get(), &id)) + { + return C2_CORRUPTED; + } + + it = m_surfaces.find(id); + + if(C2_OK == res && (it == m_surfaces.end() || (it != m_surfaces.end() && !it->second->Data.Locked))) { + block_pool.clear(); + found_surface = true; + if(it == m_surfaces.end()) { + res = MfxC2FrameOut::Create(converter, std::move(new_block), m_mfxVideoParams.mfx.FrameInfo, frame_out, new_hndl.get()); + if (C2_OK != res) { + break; + } + m_surfaces.emplace(id, frame_out->GetMfxFrameSurface()); + } else { + *frame_out = MfxC2FrameOut(std::move(new_block), it->second); + } + } + } } } } else { From a4f3a93aee21da1d77969d572b546e31293c3592 Mon Sep 17 00:00:00 2001 From: zhangyichix Date: Thu, 20 Mar 2025 10:52:09 +0800 Subject: [PATCH 2/2] Remove InCache logic during initialization of decoder InCache logic will consume all buffers in buffer pool at same time, Sometimes encounters stuck issue. Tracked-On: OAM-132019 Signed-off-by: zhangyichix --- c2_utils/src/mfx_va_frame_pool_allocator.cpp | 85 ++------------------ 1 file changed, 6 insertions(+), 79 deletions(-) diff --git a/c2_utils/src/mfx_va_frame_pool_allocator.cpp b/c2_utils/src/mfx_va_frame_pool_allocator.cpp index d8aae064..6d7c761d 100755 --- a/c2_utils/src/mfx_va_frame_pool_allocator.cpp +++ b/c2_utils/src/mfx_va_frame_pool_allocator.cpp @@ -88,87 +88,14 @@ mfxStatus MfxVaFramePoolAllocator::AllocFrames(mfxFrameAllocRequest *request, } response->NumFrameActual = 0; -#define RETRY_TIMES 5 - for (int i = 0; i < opt_buffers; ++i) { - - std::shared_ptr new_block; - int retry_time_left = RETRY_TIMES; - do { - res = m_c2Allocator->fetchGraphicBlock( - MFXGetSurfaceWidth(request->Info), MFXGetSurfaceHeight(request->Info), - MfxFourCCToGralloc(request->Info.FourCC), - { m_consumerUsage, C2AndroidMemoryUsage::HW_CODEC_WRITE }, - &new_block); - if (!retry_time_left--) { - if (request->NumFrameMin <= i) { - // Ignore the error here in case system cannot allocate - // the maximum buffers. The minimum buffer is OK. - res = C2_TIMED_OUT; - break; - } else { - // Retry to get minimum request buffers. - retry_time_left = RETRY_TIMES; - } - } - } while(res == C2_BLOCKING); - if (res != C2_OK || !new_block) break; - - uint64_t id; - native_handle_t *hndl = android::UnwrapNativeCodec2GrallocHandle(new_block->handle()); - if (C2_OK != MfxGrallocInstance::getInstance()->GetBackingStore(hndl, &id)) { - mfx_res = MFX_ERR_INVALID_HANDLE; - break; - } - - m_cachedBufferId.emplace(id, i); - // if (C2_OK != res) { //TODO dead code not need. - // native_handle_delete(hndl); - // mfx_res = MFX_ERR_MEMORY_ALLOC; - // break; - // } - - // deep copy to have unique_ptr as m_pool required unique_ptr - std::unique_ptr unique_block = std::make_unique(*new_block); - - bool decode_target = true; - mfx_res = ConvertGrallocToVa(hndl, decode_target, &mids[i]); - if (MFX_ERR_NONE != mfx_res) { - native_handle_delete(hndl); - break; - } - - MFX_DEBUG_TRACE_STREAM(NAMED(unique_block->handle()) << NAMED(mids[i])); - - m_pool->Append(std::move(unique_block));//tmp cache it, in case return it to system and alloc again at once. - - native_handle_delete(hndl); - - ++response->NumFrameActual; - } - MFX_DEBUG_TRACE_I32(response->NumFrameActual); - - if (MFX_ERR_NONE != mfx_res) { - MFX_DEBUG_TRACE_MSG("Fatal error occurred while allocating memory"); - - MFX_DEBUG_TRACE__mfxStatus(mfx_res); - return mfx_res; - } - if (response->NumFrameActual >= request->NumFrameMin) { - response->mids = mids.release(); - m_pool = std::make_unique>(); //release graphic buffer - mfx_res = MFX_ERR_NONE; // suppress the error if allocated enough - } else { - response->NumFrameActual = 0; - response->mids = nullptr; - // recreate m_pool to clean it - FreeAllMappings(); - m_pool = std::make_unique>(); - mfx_res = MFX_ERR_MEMORY_ALLOC; - } - } while(false); + response->NumFrameActual = opt_buffers; + response->mids = mids.release(); + } while (false); } else { - mfx_res = AllocFrames(request, response); + response->NumFrameActual = 0; + response->mids = nullptr; + mfx_res = MFX_ERR_INCOMPATIBLE_VIDEO_PARAM; } MFX_DEBUG_TRACE__mfxStatus(mfx_res);