Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 50 additions & 27 deletions c2_components/src/mfx_c2_decoder_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<native_handle_t, decltype(hndl_deleter)> 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,
Expand Down Expand Up @@ -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<C2GraphicBlock> block_pool;
std::shared_ptr<C2GraphicBlock> 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<native_handle_t, decltype(hndl_deleter)> 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 {
Expand Down
85 changes: 6 additions & 79 deletions c2_utils/src/mfx_va_frame_pool_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<C2GraphicBlock> 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<C2GraphicBlock> unique_block = std::make_unique<C2GraphicBlock>(*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<MfxPool<C2GraphicBlock>>(); //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<MfxPool<C2GraphicBlock>>();
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);
Expand Down