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 { 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);