From e11b22d5a3928c181a77ea41a9841bad7bc1ff32 Mon Sep 17 00:00:00 2001 From: Nana Zhang Date: Thu, 29 Aug 2024 08:35:39 +0000 Subject: [PATCH 01/14] Improve performance when CPU need access decode surface 1. Send consumer usage from framework, allocate system/video memory according to consumer usage. 2. If cpu read often, use minigbm allocate linear NV12 buffer, and C2 send this "system buffer" to OneVPL, OneVPL internally allocate NV12 buffer for decoding using vaapi and copy this internal buffer to linear surface internally Tracked-On: OAM-124103 Signed-off-by: Nana Zhang (cherry picked from commit 7968852cfaa9b4b0be4d8f1834287194722cf5bf) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../include/mfx_c2_decoder_component.h | 2 + .../src/mfx_c2_decoder_component.cpp | 150 ++++++------------ 2 files changed, 47 insertions(+), 105 deletions(-) diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index 3f6fc2b8..bc895460 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -268,6 +268,7 @@ class MfxC2DecoderComponent : public MfxC2Component std::shared_ptr m_inputMediaType; std::shared_ptr m_inputFormat; std::shared_ptr m_outputFormat; + std::shared_ptr m_outputUsage; std::shared_ptr m_profileLevel; std::shared_ptr m_actualOutputDelay; std::shared_ptr m_requestedInputDelay; @@ -292,4 +293,5 @@ class MfxC2DecoderComponent : public MfxC2Component static C2R ColorAspectsSetter(bool mayBlock, C2P &me, const C2P &def, const C2P &coded); + static C2R OutputUsageSetter(bool mayBlock, C2P &me); }; diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index db7ccfea..f03c8f23 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -46,7 +46,6 @@ constexpr uint64_t kMinInputBufferSize = 1 * WIDTH_1K * HEIGHT_1K; constexpr uint64_t kDefaultConsumerUsage = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER); - // Android S declared VP8 profile #if PLATFORM_SDK_VERSION <= 30 // Android 11(R) enum VP8_PROFILE { @@ -108,6 +107,13 @@ C2R MfxC2DecoderComponent::ProfileLevelSetter(bool mayBlock, C2P &me) { + (void)mayBlock; + (void)me; + C2R res = C2R::Ok(); + return res; +} + C2R MfxC2DecoderComponent::DefaultColorAspectsSetter(bool mayBlock, C2P &me) { (void)mayBlock; @@ -221,6 +227,15 @@ MfxC2DecoderComponent::MfxC2DecoderComponent(const C2String name, const CreateCo .withConstValue(AllocSharedString("video/raw")) .build()); + m_consumerUsage = C2AndroidMemoryUsage::FromGrallocUsage(kDefaultConsumerUsage).expected; + addParameter( + DefineParam(m_outputUsage, C2_PARAMKEY_OUTPUT_STREAM_USAGE) + .withDefault(new C2StreamUsageTuning::output(SINGLE_STREAM_ID, m_consumerUsage)) + .withFields({ C2F(m_outputUsage, value).any(),}) + .withSetter(OutputUsageSetter) + .build() + ); + switch(m_decoderType) { case DECODER_H264: { m_uOutputDelay = /*max_dpb_size*/16 + /*for async depth*/1 + /*for msdk unref in sync part*/1; @@ -663,9 +678,6 @@ MfxC2DecoderComponent::MfxC2DecoderComponent(const C2String name, const CreateCo m_hdrStaticInfo->maxCll = 0; m_hdrStaticInfo->maxFall = 0; - // By default prepare buffer to be displayed on any of the common surfaces - m_consumerUsage = kDefaultConsumerUsage; - MFX_ZERO_MEMORY(m_signalInfo); //m_paramStorage.DumpParams(); } @@ -713,6 +725,7 @@ c2_status_t MfxC2DecoderComponent::Init() if(mfx_res == MFX_ERR_NONE) { mfx_res = InitSession(); } + if(MFX_ERR_NONE == mfx_res) { InitFrameConstructor(); } @@ -725,51 +738,23 @@ c2_status_t MfxC2DecoderComponent::DoStart() MFX_DEBUG_TRACE_FUNC; m_uSyncedPointsCount = 0; - mfxStatus mfx_res = MFX_ERR_NONE; m_bEosReceived = false; + m_bAllocatorSet = false; do { - bool allocator_required = (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY); - - if (allocator_required != m_bAllocatorSet) { - + // Must reserve MFXClose(), InitSession() logic here, if not some drm cts will not pass #ifdef USE_ONEVPL - mfx_res = MFXClose(m_mfxSession); + mfxStatus mfx_res = MFXClose(m_mfxSession); #else - mfx_res = m_mfxSession.Close(); + mfxStatus mfx_res = m_mfxSession.Close(); #endif - if (MFX_ERR_NONE != mfx_res) break; - - mfx_res = InitSession(); - if (MFX_ERR_NONE != mfx_res) break; - - // set frame allocator - if (allocator_required) { - m_allocator = m_device->GetFramePoolAllocator(); -#ifdef USE_ONEVPL - mfx_res = MFXVideoCORE_SetFrameAllocator(m_mfxSession, &(m_device->GetFrameAllocator()->GetMfxAllocator())); -#else - mfx_res = m_mfxSession.SetFrameAllocator(&(m_device->GetFrameAllocator()->GetMfxAllocator())); -#endif - } else { - m_allocator = nullptr; -#ifdef USE_ONEVPL - mfx_res = MFXVideoCORE_SetFrameAllocator(m_mfxSession, nullptr); -#else - mfx_res = m_mfxSession.SetFrameAllocator(nullptr); -#endif - } - if (MFX_ERR_NONE != mfx_res) break; - - m_bAllocatorSet = allocator_required; - } + if (MFX_ERR_NONE != mfx_res) break; - MFX_DEBUG_TRACE_STREAM(m_surfaces.size()); - MFX_DEBUG_TRACE_STREAM(m_surfacePool.size()); + mfx_res = InitSession(); + if (MFX_ERR_NONE != mfx_res) break; m_workingQueue.Start(); m_waitingQueue.Start(); - } while(false); m_OperationState = OperationState::RUNNING; @@ -829,7 +814,7 @@ c2_status_t MfxC2DecoderComponent::Release() #ifdef USE_ONEVPL if (m_mfxSession) { - MFXClose(m_mfxSession); + sts = MFXClose(m_mfxSession); m_mfxSession = nullptr; } #else @@ -1053,17 +1038,9 @@ mfxStatus MfxC2DecoderComponent::ResetSettings() m_signalInfo.VideoFullRange = 2; // UNSPECIFIED Range mfx_set_defaults_mfxVideoParam_dec(&m_mfxVideoParams); - if (m_device) - { - // default pattern: video memory if allocator available - m_mfxVideoParams.IOPattern = m_device->GetFrameAllocator() ? - MFX_IOPATTERN_OUT_VIDEO_MEMORY : MFX_IOPATTERN_OUT_SYSTEM_MEMORY; - - } - else - { - res = MFX_ERR_NULL_PTR; - } + m_mfxVideoParams.IOPattern = (m_consumerUsage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)) ? + MFX_IOPATTERN_OUT_SYSTEM_MEMORY : MFX_IOPATTERN_OUT_VIDEO_MEMORY; + MFX_DEBUG_TRACE_U32(m_mfxVideoParams.IOPattern); return res; } @@ -1145,9 +1122,6 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all } if (MFX_ERR_NONE == mfx_res) { - // set memory type according to consumer usage sent from framework - m_mfxVideoParams.IOPattern = (C2MemoryUsage::CPU_READ == m_consumerUsage) ? - MFX_IOPATTERN_OUT_SYSTEM_MEMORY : MFX_IOPATTERN_OUT_VIDEO_MEMORY; MFX_DEBUG_TRACE_I32(m_mfxVideoParams.IOPattern); MFX_DEBUG_TRACE_I32(m_mfxVideoParams.mfx.FrameInfo.Width); MFX_DEBUG_TRACE_I32(m_mfxVideoParams.mfx.FrameInfo.Height); @@ -1206,41 +1180,16 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all m_mfxVideoParams.AsyncDepth = GetAsyncDepth(); } - // We need check whether the BQ allocator has a surface, if No we cannot use MFX_IOPATTERN_OUT_VIDEO_MEMORY mode. - if (MFX_ERR_NONE == mfx_res && m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY) { - std::shared_ptr out_block; - c2_status_t res = C2_OK; - C2MemoryUsage mem_usage = {C2AndroidMemoryUsage::CPU_READ | C2AndroidMemoryUsage::HW_COMPOSER_READ, - C2AndroidMemoryUsage::HW_CODEC_WRITE}; - - res = m_c2Allocator->fetchGraphicBlock(m_mfxVideoParams.mfx.FrameInfo.Width, - m_mfxVideoParams.mfx.FrameInfo.Height, - MfxFourCCToGralloc(m_mfxVideoParams.mfx.FrameInfo.FourCC), - mem_usage, &out_block); - - if (res == C2_OK) - { - uint32_t width, height, format, stride, igbp_slot, generation; - uint64_t usage, igbp_id; - android::_UnwrapNativeCodec2GrallocMetadata(out_block->handle(), &width, &height, &format, &usage, - &stride, &generation, &igbp_id, &igbp_slot); - if ((!igbp_id && !igbp_slot) || (!igbp_id && igbp_slot == 0xffffffff)) - { - // No surface & BQ - m_mfxVideoParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; - m_allocator = nullptr; - } - } - } - - if (MFX_ERR_NONE == mfx_res && m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY) { + bool allocator_required = (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY); + if (MFX_ERR_NONE == mfx_res && allocator_required && m_bAllocatorSet == false) { + // set frame allocator + m_allocator = m_device->GetFramePoolAllocator(); #ifdef USE_ONEVPL - mfx_res = MFXVideoCORE_SetFrameAllocator(m_mfxSession, nullptr); + mfx_res = MFXVideoCORE_SetFrameAllocator(m_mfxSession, &(m_device->GetFrameAllocator()->GetMfxAllocator())); #else - mfx_res = m_mfxSession.SetFrameAllocator(nullptr); + mfx_res = m_mfxSession.SetFrameAllocator(&(m_device->GetFrameAllocator()->GetMfxAllocator())); #endif - m_bAllocatorSet = false; - if (MFX_ERR_NONE != mfx_res) MFX_DEBUG_TRACE_MSG("SetFrameAllocator failed"); + if (MFX_ERR_NONE == mfx_res) m_bAllocatorSet = true; } if (MFX_ERR_NONE == mfx_res) { @@ -1497,6 +1446,16 @@ void MfxC2DecoderComponent::DoUpdateMfxParam(const std::vector ¶ms } break; } + case kParamIndexUsage: { + if (C2StreamUsageTuning::output::PARAM_TYPE == param->index()) { + m_consumerUsage = m_outputUsage->value; + // Set memory type according to consumer usage sent from framework + m_mfxVideoParams.IOPattern = (m_consumerUsage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)) ? + MFX_IOPATTERN_OUT_SYSTEM_MEMORY : MFX_IOPATTERN_OUT_VIDEO_MEMORY; + MFX_DEBUG_TRACE_STREAM("config kParamIndexUsage to 0x" << std::hex << m_consumerUsage); + } + break; + } default: MFX_DEBUG_TRACE_STREAM("attempt to configure " << C2Param::Type(param->type()).typeIndex() << " type, but not found"); @@ -1726,7 +1685,6 @@ c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t heig } if (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY) { - C2MemoryUsage mem_usage = {m_consumerUsage, C2AndroidMemoryUsage::HW_CODEC_WRITE}; res = m_c2Allocator->fetchGraphicBlock(width, height, MfxFourCCToGralloc(fourcc), mem_usage, out_block); @@ -1751,7 +1709,6 @@ c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t heig } } } else if (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY) { - C2MemoryUsage mem_usage = {m_consumerUsage, C2MemoryUsage::CPU_WRITE}; res = m_c2Allocator->fetchGraphicBlock(width, height, MfxFourCCToGralloc(fourcc, false), mem_usage, out_block); @@ -2018,24 +1975,7 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) res = GetCodec2BlockPool(m_outputPoolId, shared_from_this(), &m_c2Allocator); if (res != C2_OK) break; -#ifdef MFX_BUFFER_QUEUE - bool hasSurface = std::static_pointer_cast(m_c2Allocator)->outputSurfaceSet(); - m_mfxVideoParams.IOPattern = hasSurface ? MFX_IOPATTERN_OUT_VIDEO_MEMORY : MFX_IOPATTERN_OUT_SYSTEM_MEMORY; -#endif - if (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY) { - m_allocator = nullptr; -#ifdef USE_ONEVPL - mfx_sts = MFXVideoCORE_SetFrameAllocator(m_mfxSession, nullptr); -#else - mfx_sts = m_mfxSession.SetFrameAllocator(nullptr); -#endif - m_bAllocatorSet = false; - ALOGI("System memory is being used for decoding!"); - - if (MFX_ERR_NONE != mfx_sts) break; - } } - // loop repeats DecodeFrame on the same frame // if DecodeFrame returns error which is repairable, like resolution change bool resolution_change = false; From cc478105b2bfd074b2f4619d7eb118a1bf01f6bf Mon Sep 17 00:00:00 2001 From: Nana Zhang Date: Tue, 10 Sep 2024 14:24:41 +0000 Subject: [PATCH 02/14] Fix vts regression Tracked-On: OAM-124578 Signed-off-by: Nana Zhang (cherry picked from commit a071ad91d96f1819de932a0eb836a77e85379cf4) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../src/mfx_c2_decoder_component.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index f03c8f23..c19dcefa 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -1180,6 +1180,33 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all m_mfxVideoParams.AsyncDepth = GetAsyncDepth(); } + // We need check whether the BQ allocator has a surface, if No we cannot use MFX_IOPATTERN_OUT_VIDEO_MEMORY mode. + if (MFX_ERR_NONE == mfx_res && m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY) { + std::shared_ptr out_block; + c2_status_t res = C2_OK; + C2MemoryUsage mem_usage = {C2AndroidMemoryUsage::CPU_READ | C2AndroidMemoryUsage::HW_COMPOSER_READ, + C2AndroidMemoryUsage::HW_CODEC_WRITE}; + + res = m_c2Allocator->fetchGraphicBlock(m_mfxVideoParams.mfx.FrameInfo.Width, + m_mfxVideoParams.mfx.FrameInfo.Height, + MfxFourCCToGralloc(m_mfxVideoParams.mfx.FrameInfo.FourCC), + mem_usage, &out_block); + + if (res == C2_OK) + { + uint32_t width, height, format, stride, igbp_slot, generation; + uint64_t usage, igbp_id; + android::_UnwrapNativeCodec2GrallocMetadata(out_block->handle(), &width, &height, &format, &usage, + &stride, &generation, &igbp_id, &igbp_slot); + if ((!igbp_id && !igbp_slot) || (!igbp_id && igbp_slot == 0xffffffff)) + { + // No surface & BQ + m_mfxVideoParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; + m_allocator = nullptr; + } + } + } + bool allocator_required = (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY); if (MFX_ERR_NONE == mfx_res && allocator_required && m_bAllocatorSet == false) { // set frame allocator From cf212e0c4ad3eccd096d122b94465e35f012f9ed Mon Sep 17 00:00:00 2001 From: "Wan, Hao" Date: Tue, 10 Sep 2024 09:21:57 +0000 Subject: [PATCH 03/14] Resolve Widevine L3 cencSchemeTypeV18 failed run ats -a x86_6 -m GtsExoPlayerTestCases -t com.google.android.exoplayer.gts.CommonEncryptionDrmTest#cencSchemeTypeV184 The root cause is that the resolution changed processing flow was triggered when decoding the last input bitstream with the same timestamp but different frame index. At this point, the input must be processed as an independent frame. Tracked-On: OAM-118988 Signed-off-by: Wan, Hao (cherry picked from commit 769bcd1883b40133ae547fcaf287ac83239de95e) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../include/mfx_c2_decoder_component.h | 2 +- .../src/mfx_c2_decoder_component.cpp | 29 +++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index bc895460..61ac356d 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -219,7 +219,7 @@ class MfxC2DecoderComponent : public MfxC2Component std::list m_lockedSurfaces; // allocated, but cannot be re-used as Locked by Decoder std::mutex m_pendingWorksMutex; - std::map> m_pendingWorks; + std::map> m_pendingWorks; std::shared_ptr m_allocator; // used when Video memory output // for pre-allocation when Video memory is chosen and always when System memory output diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index c19dcefa..6d6c3e23 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -1867,6 +1867,7 @@ c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out) bool MfxC2DecoderComponent::IsDuplicatedTimeStamp(uint64_t timestamp) { MFX_DEBUG_TRACE_FUNC; + MFX_DEBUG_TRACE_I64(timestamp); bool bDuplicated = false; @@ -1887,6 +1888,7 @@ bool MfxC2DecoderComponent::IsDuplicatedTimeStamp(uint64_t timestamp) bool MfxC2DecoderComponent::IsPartialFrame(uint64_t frame_index) { MFX_DEBUG_TRACE_FUNC; + MFX_DEBUG_TRACE_I64(frame_index); bool bDuplicated = false; @@ -1936,6 +1938,8 @@ void MfxC2DecoderComponent::ReleaseReadViews(uint64_t incoming_frame_index) read_view = std::move(it->second); read_view.reset(); m_readViews.erase(it); + MFX_DEBUG_TRACE_STREAM("release read_view with " << + NAMED(incoming_frame_index)); } } @@ -1952,9 +1956,11 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) mfxStatus mfx_sts = MFX_ERR_NONE; const auto incoming_frame_index = work->input.ordinal.frameIndex; + const auto incoming_timestamp = work->input.ordinal.timestamp; const auto incoming_flags = work->input.flags; MFX_DEBUG_TRACE_STREAM("work: " << work.get() << "; index: " << incoming_frame_index.peeku() << + "; timestamp: " << incoming_timestamp.peeku() << " flags: " << std::hex << incoming_flags); bool expect_output = false; @@ -1983,6 +1989,7 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) } } + bool encounterResolutionChanged = false; do { std::unique_ptr read_view; res = m_c2Bitstream->AppendFrame(work->input, TIMEOUT_NS, &read_view); @@ -1991,6 +1998,8 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) { std::lock_guard lock(m_readViewMutex); m_readViews.emplace(incoming_frame_index.peeku(), std::move(read_view)); + MFX_DEBUG_TRACE_STREAM("emplace readview with " << NAMED(incoming_frame_index.peeku()) + << NAMED(incoming_timestamp.peeku())); MFX_DEBUG_TRACE_I32(m_readViews.size()); } @@ -2047,6 +2056,8 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) resolution_change = (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == mfx_sts); if (resolution_change) { + encounterResolutionChanged = true; + frame_out = MfxC2FrameOut(); // release the frame to be used in Drain Drain(nullptr); @@ -2093,8 +2104,13 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) bool incomplete_frame = (incoming_flags & (C2FrameData::FLAG_INCOMPLETE | C2FrameData::FLAG_CODEC_CONFIG)) != 0; - // sometimes the frame is split to several buffers with the same timestamp. - incomplete_frame |= IsPartialFrame(incoming_frame_index.peeku()); + // Sometimes the frame is split to several buffers with the same timestamp. + // If the current input bitstream causes a change in resolution, + // the corresponding decoded frame must be returned to the framework in the 'WaitWork' thread, + // rather than returning an empty output in the 'DoWork' thread. + if (!encounterResolutionChanged) { + incomplete_frame |= IsPartialFrame(incoming_frame_index.peeku()); + } // notify listener in case of failure or empty output if (C2_OK != res || !expect_output || incomplete_frame || flushing) { @@ -2149,7 +2165,6 @@ void MfxC2DecoderComponent::Drain(std::unique_ptr&& work) if (m_bInitialized) { do { - if (m_bFlushing) { if (work) { m_flushedWorks.push_back(std::move(work)); @@ -2176,7 +2191,6 @@ void MfxC2DecoderComponent::Drain(std::unique_ptr&& work) // eos work, should be sent after last work returned if (work) { m_waitingQueue.Push([work = std::move(work), this]() mutable { - FillEmptyWork(std::move(work), C2_OK); }); } @@ -2429,16 +2443,21 @@ void MfxC2DecoderComponent::PushPending(std::unique_ptr&& work) if (!IsDuplicatedTimeStamp(duplicated_timestamp)) { m_duplicatedTimeStamp.push_back(std::make_pair(duplicate->second->input.ordinal.timestamp.peeku(), duplicate->second->input.ordinal.frameIndex.peeku())); + MFX_DEBUG_TRACE_STREAM("record work with duplicated timestamp: " << duplicate->second->input.ordinal.timestamp.peeku() << + "; index: " << duplicate->second->input.ordinal.frameIndex.peeku()); } m_duplicatedTimeStamp.push_back(std::make_pair(work->input.ordinal.timestamp.peeku(), work->input.ordinal.frameIndex.peeku())); + MFX_DEBUG_TRACE_STREAM("record incoming work with duplicated timestamp: " << work->input.ordinal.timestamp.peeku() << + "; index: " << work->input.ordinal.frameIndex.peeku()); } const auto incoming_frame_index = work->input.ordinal.frameIndex; auto it = m_pendingWorks.find(incoming_frame_index); if (it != m_pendingWorks.end()) { // Shouldn't be the same index there NotifyWorkDone(std::move(it->second), C2_CORRUPTED); - MFX_DEBUG_TRACE_STREAM("Work removed: " << NAMED(it->second->input.ordinal.frameIndex.peeku())); + MFX_DEBUG_TRACE_STREAM("Work removed: " << NAMED(it->second->input.ordinal.frameIndex.peeku()) << + NAMED(it->second->input.ordinal.timestamp.peeku())); m_pendingWorks.erase(it); } m_pendingWorks.emplace(incoming_frame_index, std::move(work)); From 51a62d7a4ef260bf6b92821f75d49e93f3007bcb Mon Sep 17 00:00:00 2001 From: Lina Sun Date: Fri, 6 Sep 2024 01:20:30 +0000 Subject: [PATCH 04/14] Revert "[c2][decoder] Set default output to 8-bit pixel format" This reverts commit 3542c39b539c97c0840d2f962ec0012b3d9f02a4. As driver doesn't support decode 10bit bitsteam to 8 bit frames directly. Previous solution of changing frame info to 8-bit does not work. Revert the commit and use VPP to convert 10 bit frames to 8 bit. Tracked-On: OAM-122766 Signed-off-by: Lina Sun (cherry picked from commit 9451408d20edc94c0debe34b9466d15b9865456a) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../src/mfx_c2_decoder_component.cpp | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index 6d6c3e23..a9168ae5 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -651,7 +651,6 @@ MfxC2DecoderComponent::MfxC2DecoderComponent(const C2String name, const CreateCo // But the format we actually allocated buffer is HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL for 8-bit, // HAL_PIXEL_FORMAT_P010_INTEL for 10-bit. via function MfxFourCCToGralloc in mfx_c2_utils.cpp std::vector supportedPixelFormats = { - HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, HAL_PIXEL_FORMAT_YCBCR_420_888, HAL_PIXEL_FORMAT_YV12, HAL_PIXEL_FORMAT_YCBCR_P010 @@ -1148,25 +1147,6 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all m_mfxVideoParams.mfx.FrameInfo.Width = MFX_MEM_ALIGN(m_mfxVideoParams.mfx.FrameInfo.Width, 16); m_mfxVideoParams.mfx.FrameInfo.Height = MFX_MEM_ALIGN(m_mfxVideoParams.mfx.FrameInfo.Height, 16); - // Google requires the component to decode to 8-bit color format by default. - // Reference CTS cases testDefaultOutputColorFormat. - MFX_DEBUG_TRACE_I32(m_pixelFormat->value); - if (HAL_PIXEL_FORMAT_YCBCR_420_888 == m_pixelFormat->value && MFX_FOURCC_P010 == m_mfxVideoParams.mfx.FrameInfo.FourCC) { - MFX_DEBUG_TRACE_MSG("force change from 10-bit to 8-bit"); - m_mfxVideoParams.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; - m_mfxVideoParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; - m_mfxVideoParams.mfx.FrameInfo.BitDepthLuma = 8; - m_mfxVideoParams.mfx.FrameInfo.BitDepthChroma = 8; - m_mfxVideoParams.mfx.FrameInfo.Shift = 0; - if (m_decoderType == DECODER_H265) { - m_mfxVideoParams.mfx.CodecProfile = MFX_PROFILE_HEVC_MAIN; - } - if (m_decoderType == DECODER_VP9) { - m_mfxVideoParams.mfx.CodecProfile = MFX_PROFILE_VP9_0; - } - } - - MFX_DEBUG_TRACE_I32(m_mfxVideoParams.mfx.FrameInfo.FourCC); if (MFX_ERR_NONE == mfx_res) { mfx_res = m_c2Bitstream->GetFrameConstructor()->Init(m_mfxVideoParams.mfx.CodecProfile, m_mfxVideoParams.mfx.FrameInfo); } @@ -2366,6 +2346,11 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn C2StreamPictureSizeInfo::output new_size(0u, m_size->width, m_size->height); m_updatingC2Configures.push_back(C2Param::Copy(new_size)); } + // Update pixel format to framework if it different from what we actually allocted. + if (MFX_FOURCC_P010 == m_mfxVideoParams.mfx.FrameInfo.FourCC && m_pixelFormat->value != HAL_PIXEL_FORMAT_YCBCR_P010) { + C2StreamPixelFormatInfo::output new_pixel_format(0u, HAL_PIXEL_FORMAT_YCBCR_P010); + m_updatingC2Configures.push_back(C2Param::Copy(new_pixel_format)); + } // Update codec's configure for (int i = 0; i < m_updatingC2Configures.size(); i++) { From 735dc21d92d60961c5e3a48ad7e5e434d99efb1d Mon Sep 17 00:00:00 2001 From: Lina Sun Date: Fri, 6 Sep 2024 01:26:16 +0000 Subject: [PATCH 05/14] [c2][decoder] Use VPP for 10 bit to 8 bit frames conversion For 10 bit bitstream decoder, if decode format is not specified, VPP convert 10 bit frames to 8 bit frames as output. Tracked-On: OAM-122766 Signed-off-by: Lina Sun (cherry picked from commit 656fff27e6939b1d9b29560ad2aa6ae410ff0668) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../include/mfx_c2_decoder_component.h | 10 +- .../src/mfx_c2_decoder_component.cpp | 154 +++++++++++++++--- 2 files changed, 138 insertions(+), 26 deletions(-) diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index 61ac356d..f9d6fdbf 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -131,9 +131,10 @@ class MfxC2DecoderComponent : public MfxC2Component mfxStatus DecodeFrame(mfxBitstream *bs, MfxC2FrameOut&& frame_out, bool* flushing, bool* expect_output); - c2_status_t AllocateC2Block(uint32_t width, uint32_t height, uint32_t fourcc, std::shared_ptr* out_block); + c2_status_t AllocateC2Block(uint32_t width, uint32_t height, uint32_t fourcc, + std::shared_ptr* out_block, bool vpp_conversion = false); - c2_status_t AllocateFrame(MfxC2FrameOut* frame_out); + c2_status_t AllocateFrame(MfxC2FrameOut* frame_out, bool vpp_conversion = false); mfxU16 GetAsyncDepth(); @@ -162,6 +163,8 @@ class MfxC2DecoderComponent : public MfxC2Component void UpdateColorAspectsFromBitstream(const mfxExtVideoSignalInfo &signalInfo); + mfxStatus InitVPP(); + private: DecoderType m_decoderType; @@ -246,6 +249,9 @@ class MfxC2DecoderComponent : public MfxC2Component unsigned int m_uOutputDelay = 8u; unsigned int m_uInputDelay = 0u; + MFXVideoVPP* m_vpp; + bool m_vppConversion = false; + #if MFX_DEBUG_DUMP_FRAME == MFX_DEBUG_YES int m_count = 0; std::mutex m_count_lock; diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index a9168ae5..11df780d 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -651,6 +651,7 @@ MfxC2DecoderComponent::MfxC2DecoderComponent(const C2String name, const CreateCo // But the format we actually allocated buffer is HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL for 8-bit, // HAL_PIXEL_FORMAT_P010_INTEL for 10-bit. via function MfxFourCCToGralloc in mfx_c2_utils.cpp std::vector supportedPixelFormats = { + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, HAL_PIXEL_FORMAT_YCBCR_420_888, HAL_PIXEL_FORMAT_YV12, HAL_PIXEL_FORMAT_YCBCR_P010 @@ -1248,6 +1249,15 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all m_mfxVideoParams.mfx.FrameInfo.CropH = cropH; } } + + // Google requires the component to decode to 8-bit color format by default. + // Reference CTS cases testDefaultOutputColorFormat. + if (MFX_ERR_NONE == mfx_res && HAL_PIXEL_FORMAT_YCBCR_420_888 == m_pixelFormat->value && + MFX_FOURCC_P010 == m_mfxVideoParams.mfx.FrameInfo.FourCC) { + m_vppConversion = true; + mfx_res = InitVPP(); + } + if (MFX_ERR_NONE != mfx_res) { FreeDecoder(); } @@ -1256,6 +1266,49 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all return mfx_res; } +mfxStatus MfxC2DecoderComponent::InitVPP() +{ + MFX_DEBUG_TRACE_FUNC; + mfxStatus sts = MFX_ERR_NONE; + mfxVideoParam vppParam; + +#ifdef USE_ONEVPL + MFX_NEW(m_vpp, MFXVideoVPP(m_mfxSession)); +#else + MFX_NEW(m_vpp, MFXVideoVPP(*m_pSession)); +#endif + + if(!m_vpp) { + sts = MFX_ERR_UNKNOWN; + return sts; + } + + mfxFrameInfo frame_info; + frame_info = m_mfxVideoParams.mfx.FrameInfo; + MFX_ZERO_MEMORY(vppParam); + + if(m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY) { + vppParam.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY; + } else { + vppParam.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; + } + + vppParam.vpp.In = frame_info; + vppParam.vpp.Out = frame_info; + + vppParam.vpp.Out.FourCC = MFX_FOURCC_NV12; + vppParam.vpp.Out.Shift = 0; + + vppParam.AsyncDepth = m_mfxVideoParams.AsyncDepth; + + MFX_DEBUG_TRACE__mfxFrameInfo(vppParam.vpp.In); + MFX_DEBUG_TRACE__mfxFrameInfo(vppParam.vpp.Out); + + if (MFX_ERR_NONE == sts) sts = m_vpp->Init(&vppParam); + + return sts; +} + void MfxC2DecoderComponent::FreeDecoder() { MFX_DEBUG_TRACE_FUNC; @@ -1264,6 +1317,11 @@ void MfxC2DecoderComponent::FreeDecoder() m_lockedSurfaces.clear(); + if(m_vppConversion && m_vpp != NULL) { + m_vpp->Close(); + MFX_DELETE(m_vpp); + } + if(nullptr != m_mfxDecoder) { m_mfxDecoder->Close(); m_mfxDecoder = nullptr; @@ -1670,7 +1728,7 @@ mfxStatus MfxC2DecoderComponent::DecodeFrame(mfxBitstream *bs, MfxC2FrameOut&& f return mfx_sts; } -c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t height, uint32_t fourcc, std::shared_ptr* out_block) +c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t height, uint32_t fourcc, std::shared_ptr* out_block, bool vpp_conversion) { MFX_DEBUG_TRACE_FUNC; @@ -1707,12 +1765,14 @@ c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t heig uint64_t id; if (C2_OK != MfxGrallocInstance::getInstance()->GetBackingStore(hndl.get(), &id)) return C2_CORRUPTED; - 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); + 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) { @@ -1726,7 +1786,7 @@ c2_status_t MfxC2DecoderComponent::AllocateC2Block(uint32_t width, uint32_t heig return res; } -c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out) +c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out, bool vpp_conversion) { MFX_DEBUG_TRACE_FUNC; @@ -1749,9 +1809,15 @@ c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out) } std::shared_ptr out_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, &out_block); + if(!vpp_conversion) { + 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, &out_block); + } else { + 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), + MFX_FOURCC_NV12, &out_block, vpp_conversion); + } if (C2_TIMED_OUT == res) continue; if (C2_OK != res) break; @@ -1778,11 +1844,16 @@ c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out) it = m_surfaces.find(id); if (it == m_surfaces.end()){ // haven't been used for decoding yet - res = MfxC2FrameOut::Create(converter, std::move(out_block), m_mfxVideoParams.mfx.FrameInfo, frame_out, hndl.get()); + if(!vpp_conversion) { + res = MfxC2FrameOut::Create(converter, std::move(out_block), m_mfxVideoParams.mfx.FrameInfo, frame_out, hndl.get()); + } else { + mfxFrameInfo frame_info = m_mfxVideoParams.mfx.FrameInfo; + frame_info.FourCC = MFX_FOURCC_NV12; + res = MfxC2FrameOut::Create(converter, std::move(out_block), frame_info, frame_out, hndl.get()); + } if (C2_OK != res) { break; } - m_surfaces.emplace(id, frame_out->GetMfxFrameSurface()); } else { if (it->second->Data.Locked) { @@ -1830,7 +1901,13 @@ c2_status_t MfxC2DecoderComponent::AllocateFrame(MfxC2FrameOut* frame_out) } } else { // small resolution video playback with system memory - res = MfxC2FrameOut::Create(std::move(out_block), m_mfxVideoParams.mfx.FrameInfo, TIMEOUT_NS, frame_out); + if(!vpp_conversion) { + res = MfxC2FrameOut::Create(std::move(out_block), m_mfxVideoParams.mfx.FrameInfo, TIMEOUT_NS, frame_out); + } else { + mfxFrameInfo frame_info = m_mfxVideoParams.mfx.FrameInfo; + frame_info.FourCC = MFX_FOURCC_NV12; + res = MfxC2FrameOut::Create(std::move(out_block), frame_info, TIMEOUT_NS, frame_out); + } } if (C2_OK != res) { @@ -2230,12 +2307,13 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn MFX_DEBUG_TRACE_FUNC; c2_status_t res = C2_OK; + mfxStatus mfx_res = MFX_ERR_NONE; { #ifdef USE_ONEVPL - mfxStatus mfx_res = MFXVideoCORE_SyncOperation(m_mfxSession, sync_point, MFX_TIMEOUT_INFINITE); + mfx_res = MFXVideoCORE_SyncOperation(m_mfxSession, sync_point, MFX_TIMEOUT_INFINITE); #else - mfxStatus mfx_res = m_mfxSession.SyncOperation(sync_point, MFX_TIMEOUT_INFINITE); + mfx_res = m_mfxSession.SyncOperation(sync_point, MFX_TIMEOUT_INFINITE); #endif if (MFX_ERR_NONE != mfx_res) { MFX_DEBUG_TRACE_MSG("SyncOperation failed"); @@ -2254,6 +2332,24 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn MFX_DEBUG_TRACE_I32(m_mfxVideoParams.mfx.FrameInfo.CropW); MFX_DEBUG_TRACE_I32(m_mfxVideoParams.mfx.FrameInfo.CropH); + MfxC2FrameOut frameOutVpp; + std::shared_ptr mfx_surface_vpp; + if(m_vppConversion) { + AllocateFrame(&frameOutVpp, true); + mfx_surface_vpp = frameOutVpp.GetMfxFrameSurface(); + + if (mfx_surface_vpp) { + mfxSyncPoint syncp; + mfx_res = m_vpp->RunFrameVPPAsync(mfx_surface.get(), mfx_surface_vpp.get(), NULL, &syncp); + if (MFX_ERR_NONE == mfx_res) +#ifdef USE_ONEVPL + mfx_res = MFXVideoCORE_SyncOperation(m_mfxSession, syncp, MFX_TIMEOUT_INFINITE); +#else + mfx_res = m_pSession->SyncOperation(syncp, MFX_TIMEOUT_INFINITE); +#endif + } + } + decltype(C2WorkOrdinalStruct::timestamp) ready_timestamp{mfx_surface->Data.TimeStamp}; std::unique_ptr work; @@ -2286,8 +2382,14 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn //C2Event event; // not supported yet, left for future use //event.fire(); // pre-fire event as output buffer is ready to use - const C2Rect rect = C2Rect(mfx_surface->Info.CropW, mfx_surface->Info.CropH) - .at(mfx_surface->Info.CropX, mfx_surface->Info.CropY); + C2Rect rect; + if(!m_vppConversion) { + rect = C2Rect(mfx_surface->Info.CropW, mfx_surface->Info.CropH) + .at(mfx_surface->Info.CropX, mfx_surface->Info.CropY); + } else { + rect = C2Rect(mfx_surface_vpp->Info.CropW, mfx_surface_vpp->Info.CropH) + .at(mfx_surface_vpp->Info.CropX, mfx_surface_vpp->Info.CropY); + } { // Update frame format description to be returned by Query method @@ -2304,7 +2406,12 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn m_mfxVideoParams.mfx.FrameInfo = mfx_surface->Info; } - std::shared_ptr block = frame_out.GetC2GraphicBlock(); + std::shared_ptr block; + if(!m_vppConversion) { + block = frame_out.GetC2GraphicBlock(); + } else { + block = frameOutVpp.GetC2GraphicBlock(); + } if (!block) { res = C2_CORRUPTED; break; @@ -2346,11 +2453,6 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn C2StreamPictureSizeInfo::output new_size(0u, m_size->width, m_size->height); m_updatingC2Configures.push_back(C2Param::Copy(new_size)); } - // Update pixel format to framework if it different from what we actually allocted. - if (MFX_FOURCC_P010 == m_mfxVideoParams.mfx.FrameInfo.FourCC && m_pixelFormat->value != HAL_PIXEL_FORMAT_YCBCR_P010) { - C2StreamPixelFormatInfo::output new_pixel_format(0u, HAL_PIXEL_FORMAT_YCBCR_P010); - m_updatingC2Configures.push_back(C2Param::Copy(new_pixel_format)); - } // Update codec's configure for (int i = 0; i < m_updatingC2Configures.size(); i++) { @@ -2397,6 +2499,10 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn } while (false); // Release output frame before onWorkDone is called, release causes unmap for system memory. frame_out = MfxC2FrameOut(); + if(m_vppConversion) { + frameOutVpp = MfxC2FrameOut(); + } + if (work) { NotifyWorkDone(std::move(work), res); } From e21faffa3302487c5af3d87529472eea6cb33c42 Mon Sep 17 00:00:00 2001 From: "Wan, Hao" Date: Wed, 25 Sep 2024 15:38:50 +0000 Subject: [PATCH 06/14] [c2][coverity] Fix coverity issue CID 349680 std::make_shared will throw the std::bad_alloc exception rather than return nullptr. Here just remove the logically dead code for the coverity issue. Tracked-On: OAM-123225 Signed-off-by: Wan, Hao (cherry picked from commit a2321dbc061bc293a34a82710f027f056a7da6fb) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_utils/src/mfx_frame_constructor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/c2_utils/src/mfx_frame_constructor.cpp b/c2_utils/src/mfx_frame_constructor.cpp index 20595eb9..2a874ba9 100755 --- a/c2_utils/src/mfx_frame_constructor.cpp +++ b/c2_utils/src/mfx_frame_constructor.cpp @@ -417,7 +417,6 @@ mfxStatus MfxC2AVCFrameConstructor::FindHeaders(const mfxU8* data, mfxU32 size, start_code = ReadStartCode(&data, &size); if (isSPS(start_code.type)) { std::shared_ptr sps = std::make_shared(); - if (!sps) return MFX_ERR_MEMORY_ALLOC; MFX_ZERO_MEMORY((*sps)); sps->Data = (mfxU8*)data - start_code.size; From dce20b446a2bf15a8eac97466a4cc45c8ec054cc Mon Sep 17 00:00:00 2001 From: "Wan, Hao" Date: Wed, 9 Oct 2024 14:32:31 +0000 Subject: [PATCH 07/14] Fix Coverity issues CID/Type: 187157 Explicit null dereferenced 656172 Dereference after null check 602228 Dereference before null check Tracked-On: OAM-126078 Signed-off-by: Wan, Hao (cherry picked from commit 1c6ccea5fe902fc46deffc5c509e81d02d549ea3) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../src/mfx_c2_decoder_component.cpp | 33 +++++++++++-------- c2_utils/src/mfx_gralloc1.cpp | 7 ++-- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index 11df780d..68f4d0ec 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -2004,6 +2004,8 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) { MFX_DEBUG_TRACE_FUNC; + if (!work) return; + if (m_bFlushing) { m_flushedWorks.push_back(std::move(work)); return; @@ -2334,19 +2336,20 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn MfxC2FrameOut frameOutVpp; std::shared_ptr mfx_surface_vpp; - if(m_vppConversion) { - AllocateFrame(&frameOutVpp, true); - mfx_surface_vpp = frameOutVpp.GetMfxFrameSurface(); - - if (mfx_surface_vpp) { - mfxSyncPoint syncp; - mfx_res = m_vpp->RunFrameVPPAsync(mfx_surface.get(), mfx_surface_vpp.get(), NULL, &syncp); - if (MFX_ERR_NONE == mfx_res) -#ifdef USE_ONEVPL - mfx_res = MFXVideoCORE_SyncOperation(m_mfxSession, syncp, MFX_TIMEOUT_INFINITE); -#else - mfx_res = m_pSession->SyncOperation(syncp, MFX_TIMEOUT_INFINITE); -#endif + if (m_vppConversion) { + res = AllocateFrame(&frameOutVpp, true); + if (res == C2_OK) { + mfx_surface_vpp = frameOutVpp.GetMfxFrameSurface(); + if (mfx_surface_vpp.get()) { + mfxSyncPoint syncp; + mfx_res = m_vpp->RunFrameVPPAsync(mfx_surface.get(), mfx_surface_vpp.get(), NULL, &syncp); + if (MFX_ERR_NONE == mfx_res) + #ifdef USE_ONEVPL + mfx_res = MFXVideoCORE_SyncOperation(m_mfxSession, syncp, MFX_TIMEOUT_INFINITE); + #else + mfx_res = m_pSession->SyncOperation(syncp, MFX_TIMEOUT_INFINITE); + #endif + } } } @@ -2387,6 +2390,10 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn rect = C2Rect(mfx_surface->Info.CropW, mfx_surface->Info.CropH) .at(mfx_surface->Info.CropX, mfx_surface->Info.CropY); } else { + if (mfx_surface_vpp.get() == nullptr) { + res = C2_CORRUPTED; + break; + } rect = C2Rect(mfx_surface_vpp->Info.CropW, mfx_surface_vpp->Info.CropH) .at(mfx_surface_vpp->Info.CropX, mfx_surface_vpp->Info.CropY); } diff --git a/c2_utils/src/mfx_gralloc1.cpp b/c2_utils/src/mfx_gralloc1.cpp index 96addbfb..038260c9 100755 --- a/c2_utils/src/mfx_gralloc1.cpp +++ b/c2_utils/src/mfx_gralloc1.cpp @@ -278,13 +278,16 @@ buffer_handle_t MfxGralloc1Module::ImportBuffer(const buffer_handle_t rawHandle) MFX_DEBUG_TRACE_FUNC; c2_status_t res = C2_OK; buffer_handle_t *outBuffer = nullptr; - int32_t gr1_res = (*m_grImportBufferFunc)(m_gralloc1_dev, rawHandle, outBuffer); + buffer_handle_t out = nullptr; + int32_t gr1_res = (*m_grImportBufferFunc)(m_gralloc1_dev, rawHandle, outBuffer); if (GRALLOC1_ERROR_NONE != gr1_res || nullptr == outBuffer) { MFX_DEBUG_TRACE_I32(gr1_res); res = C2_BAD_STATE; } - buffer_handle_t out = const_cast(*outBuffer); + + if (outBuffer) + out = const_cast(*outBuffer); MFX_DEBUG_TRACE__android_c2_status_t(res); return out; From 1ae1fb8a8cd9e4221392855d1eeed59e3a625185 Mon Sep 17 00:00:00 2001 From: Nana Zhang Date: Tue, 3 Sep 2024 01:12:22 +0000 Subject: [PATCH 08/14] Clean code for MFX_BUFFER_QUEUE When `MFX_BUFFER_QUEUE` is enabled, `mediaskd_c2` will use a buffer queue implemented in `mediasdk_c2`(maybe framework doesn't support before). Now, we will use the buffer queue in Android media framework. Therefore, this part of the code is deprecated. Signed-off-by: Nana Zhang Tracked-On: OAM-124733 (cherry picked from commit 5d67a8829c23e2324785e2de4abdec3defdcabb1) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_components/Android.bp | 1 - .../include/mfx_c2_decoder_component.h | 4 +- .../src/mfx_c2_decoder_component.cpp | 16 +- c2_utils/Android.bp | 5 - c2_utils/src/mfx_va_frame_pool_allocator.cpp | 9 - plugin_store/Android.bp | 49 -- plugin_store/include/mfx_c2_allocator_id.h | 27 - plugin_store/include/mfx_c2_buffer_queue.h | 86 -- plugin_store/src/mfx_c2_buffer_queue.cpp | 780 ------------------ plugin_store/src/mfx_c2_plugin_store.cpp | 99 --- 10 files changed, 3 insertions(+), 1073 deletions(-) delete mode 100644 plugin_store/Android.bp delete mode 100755 plugin_store/include/mfx_c2_allocator_id.h delete mode 100755 plugin_store/include/mfx_c2_buffer_queue.h delete mode 100755 plugin_store/src/mfx_c2_buffer_queue.cpp delete mode 100755 plugin_store/src/mfx_c2_plugin_store.cpp diff --git a/c2_components/Android.bp b/c2_components/Android.bp index fa14524c..b74e24a6 100644 --- a/c2_components/Android.bp +++ b/c2_components/Android.bp @@ -71,7 +71,6 @@ cc_library_shared { include_dirs: [ "vendor/intel/mediasdk_c2/c2_utils/include", "vendor/intel/mediasdk_c2/c2_buffers/include", - "vendor/intel/mediasdk_c2/plugin_store/include", "frameworks/native/libs/ui/include", "frameworks/av/media/codec2/sfplugin/utils", ], diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index f9d6fdbf..b6f0c28e 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -264,7 +264,6 @@ class MfxC2DecoderComponent : public MfxC2Component std::shared_ptr m_domain; std::shared_ptr m_size; std::shared_ptr m_surfaceAllocator; - std::shared_ptr m_inputAllocators; std::shared_ptr m_outputAllocators; std::shared_ptr m_maxSize; std::shared_ptr m_maxInputSize; @@ -277,13 +276,12 @@ class MfxC2DecoderComponent : public MfxC2Component std::shared_ptr m_outputUsage; std::shared_ptr m_profileLevel; std::shared_ptr m_actualOutputDelay; - std::shared_ptr m_requestedInputDelay; - std::shared_ptr m_actualInputDelay; std::shared_ptr m_inputDelay; std::shared_ptr m_defaultColorAspects; std::shared_ptr m_inColorAspects; std::shared_ptr m_outColorAspects; std::shared_ptr m_pixelFormat; + /* ----------------------------------------Setters------------------------------------------- */ static C2R OutputSurfaceAllocatorSetter(bool mayBlock, C2P &me); static C2R SizeSetter(bool mayBlock, const C2P &oldMe, diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index 68f4d0ec..c66d3d4c 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -26,8 +26,6 @@ #include "mfx_c2_components_registry.h" #include "mfx_c2_utils.h" #include "mfx_defaults.h" -#include "mfx_c2_allocator_id.h" -#include "mfx_c2_buffer_queue.h" #include "C2PlatformSupport.h" #include "mfx_c2_color_aspects_utils.h" @@ -1038,9 +1036,7 @@ mfxStatus MfxC2DecoderComponent::ResetSettings() m_signalInfo.VideoFullRange = 2; // UNSPECIFIED Range mfx_set_defaults_mfxVideoParam_dec(&m_mfxVideoParams); - m_mfxVideoParams.IOPattern = (m_consumerUsage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)) ? - MFX_IOPATTERN_OUT_SYSTEM_MEMORY : MFX_IOPATTERN_OUT_VIDEO_MEMORY; - MFX_DEBUG_TRACE_U32(m_mfxVideoParams.IOPattern); + m_mfxVideoParams.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; return res; } @@ -1183,7 +1179,6 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all { // No surface & BQ m_mfxVideoParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; - m_allocator = nullptr; } } } @@ -1403,14 +1398,7 @@ c2_status_t MfxC2DecoderComponent::UpdateC2Param(const mfxVideoParam* src, C2Par } case kParamIndexAllocators: { if (C2PortAllocatorsTuning::output::PARAM_TYPE == index) { - if (m_mfxVideoParams.IOPattern == MFX_IOPATTERN_OUT_VIDEO_MEMORY) -#ifdef MFX_BUFFER_QUEUE - m_outputAllocators->m.values[0] = MFX_BUFFERQUEUE; -#else - m_outputAllocators->m.values[0] = C2PlatformAllocatorStore::GRALLOC; -#endif - else - m_outputAllocators->m.values[0] = C2PlatformAllocatorStore::GRALLOC; + m_outputAllocators->m.values[0] = C2PlatformAllocatorStore::GRALLOC; MFX_DEBUG_TRACE_PRINTF("Set output port alloctor to: %d", m_outputAllocators->m.values[0]); } break; diff --git a/c2_utils/Android.bp b/c2_utils/Android.bp index a88f9522..ac1a17ca 100644 --- a/c2_utils/Android.bp +++ b/c2_utils/Android.bp @@ -47,16 +47,11 @@ cc_library_static { "src/*.cpp", ], - cflags: [ - //"-DMFX_BUFFER_QUEUE" - ], - local_include_dirs: [ "include", ], include_dirs: [ - "vendor/intel/mediasdk_c2/plugin_store/include", "hardware/intel/external/minigbm-intel", "frameworks/native/include", "frameworks/native/libs/ui/include", diff --git a/c2_utils/src/mfx_va_frame_pool_allocator.cpp b/c2_utils/src/mfx_va_frame_pool_allocator.cpp index a2e0a124..d8aae064 100755 --- a/c2_utils/src/mfx_va_frame_pool_allocator.cpp +++ b/c2_utils/src/mfx_va_frame_pool_allocator.cpp @@ -21,8 +21,6 @@ #if defined(LIBVA_SUPPORT) #include "mfx_va_frame_pool_allocator.h" -#include "mfx_c2_buffer_queue.h" - #include "mfx_c2_utils.h" #include "mfx_debug.h" #include "mfx_msdk_debug.h" @@ -89,13 +87,6 @@ mfxStatus MfxVaFramePoolAllocator::AllocFrames(mfxFrameAllocRequest *request, break; } -#ifdef MFX_BUFFER_QUEUE - res = std::static_pointer_cast(m_c2Allocator)->requestNewBufferSet(max_buffers); - if(res != C2_OK) { - mfx_res = MFX_ERR_MEMORY_ALLOC; - break; - } -#endif response->NumFrameActual = 0; #define RETRY_TIMES 5 for (int i = 0; i < opt_buffers; ++i) { diff --git a/plugin_store/Android.bp b/plugin_store/Android.bp deleted file mode 100644 index 55da2fcb..00000000 --- a/plugin_store/Android.bp +++ /dev/null @@ -1,49 +0,0 @@ -cc_library_shared { - name: "libc2plugin_store_celadon", - vendor: true, - - defaults: [ - "mfx_c2_defaults", - ], - - srcs: ["src/*.cpp"], - - export_include_dirs: [ - "include", - ], - - include_dirs: [ - "frameworks/av/media/codec2/vndk/include", - "frameworks/av/media/codec2/components/base/include", - "frameworks/av/media/codec2/core/include", - "frameworks/av/media/codec2/vndk/include", - "frameworks/av/media/libstagefright/include", - "frameworks/av/media/libstagefright/include", - "vendor/intel/mediasdk_c2/c2_utils/include", - ], - - header_libs: [ - "libcodec2_internal", - ], - - static_libs: [ - "libmfx_c2_utils_va" - ], - - shared_libs: [ - "android.hardware.graphics.bufferqueue@2.0", - "libcutils", - "libhardware", - "libhidlbase", - "libnativewindow", - "libstagefright_bufferqueue_helper", - "libstagefright_foundation", - "libui", - "libutilscallstack", - ], - - cflags: [ - "-Werror", - "-Wall", - ], -} diff --git a/plugin_store/include/mfx_c2_allocator_id.h b/plugin_store/include/mfx_c2_allocator_id.h deleted file mode 100755 index ff2a755e..00000000 --- a/plugin_store/include/mfx_c2_allocator_id.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2021 Intel Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#pragma once - -#include - -enum : C2AllocatorStore::id_t { - MFX_BUFFERQUEUE = android::C2PlatformAllocatorStore::PLATFORM_END, //0x14 -}; diff --git a/plugin_store/include/mfx_c2_buffer_queue.h b/plugin_store/include/mfx_c2_buffer_queue.h deleted file mode 100755 index 03cdc872..00000000 --- a/plugin_store/include/mfx_c2_buffer_queue.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2021 Intel Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#pragma once - -#include - -#include -#include - -#include - -class MfxC2BufferQueueBlockPool : public C2BlockPool { -public: - MfxC2BufferQueueBlockPool(const std::shared_ptr &allocator, const local_id_t localId); - - virtual C2Allocator::id_t getAllocatorId() const override { - return android::C2PlatformAllocatorStore::BUFFERQUEUE; - }; - - virtual local_id_t getLocalId() const override { - return local_id_; - }; - - virtual c2_status_t fetchGraphicBlock( - uint32_t width, - uint32_t height, - uint32_t format, - C2MemoryUsage usage, - std::shared_ptr *block /* nonnull */) override; - - typedef std::function OnRenderCallback; - - /** - * Sets render callback. - * - * \param renderCallbak callback to call for all dequeue buffer. - */ - virtual void setRenderCallback(const OnRenderCallback &renderCallback = OnRenderCallback()); - - typedef ::android::hardware::graphics::bufferqueue::V2_0:: - IGraphicBufferProducer HGraphicBufferProducer; - /** - * Configures an IGBP in order to create blocks. A newly created block is - * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of - * blocks are passed via native_handle. Managing IGBP is responsibility of caller. - * When IGBP is not configured, block will be created via allocator. - * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer - * is configured as nullptr, unique id which is bundled in native_handle is zero. - * - * \param producer the IGBP, which will be used to fetch blocks - */ - virtual void configureProducer(const android::sp &producer); - - virtual c2_status_t ImportHandle( - const std::shared_ptr block, buffer_handle_t *hndl); - virtual c2_status_t requestNewBufferSet(int32_t bufferCount); - - virtual bool outputSurfaceSet(void); - -private: - const std::shared_ptr mAllocator; - const local_id_t local_id_; - - class Impl; - std::shared_ptr impl_; - - friend struct MfxC2BufferQueueBlockPoolData; -}; diff --git a/plugin_store/src/mfx_c2_buffer_queue.cpp b/plugin_store/src/mfx_c2_buffer_queue.cpp deleted file mode 100755 index 9f029bfd..00000000 --- a/plugin_store/src/mfx_c2_buffer_queue.cpp +++ /dev/null @@ -1,780 +0,0 @@ -// Copyright (c) 2021 Intel Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include "mfx_debug.h" -#include "mfx_c2_debug.h" -#include "mfx_c2_buffer_queue.h" - -using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS; -using ::android::C2AndroidMemoryUsage; -using ::android::Fence; -using ::android::GraphicBuffer; -using ::android::sp; -using ::android::status_t; -using ::android::wp; -using ::android::hardware::hidl_handle; -using ::android::hardware::Return; - -using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer; -using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status; -using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h; -using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b; -using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper; - -using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::V2_0 - ::IGraphicBufferProducer; -using namespace android; - -struct MfxC2BufferQueueBlockPoolData : public _C2BlockPoolData { - - bool held; - bool local; - uint32_t generation; - uint64_t bqId; - int32_t bqSlot; - bool transfer; // local transfer to remote - bool attach; // attach on remote - bool display; // display on remote; - std::weak_ptr owner; - sp igbp; - std::shared_ptr localPool; - mutable std::mutex lock; - - virtual type_t getType() const override { - return TYPE_BUFFERQUEUE; - } - - // Create a remote BlockPoolData. - MfxC2BufferQueueBlockPoolData( - uint32_t generation, uint64_t bqId, int32_t bqSlot, - const std::shared_ptr &owner, - const sp& producer); - - // Create a local BlockPoolData. - MfxC2BufferQueueBlockPoolData( - uint32_t generation, uint64_t bqId, int32_t bqSlot, - const std::shared_ptr& pool); - - virtual ~MfxC2BufferQueueBlockPoolData() override; - - int migrate(const sp& producer, - uint32_t toGeneration, uint64_t toBqId, - sp *buffers, uint32_t oldGeneration); -}; - -namespace { - -int64_t getTimestampNow() { - int64_t stamp; - struct timespec ts; - // TODO: CLOCK_MONOTONIC_COARSE? - clock_gettime(CLOCK_MONOTONIC, &ts); - stamp = ts.tv_nsec / 1000; - stamp += (ts.tv_sec * 1000000LL); - return stamp; -} - -bool getGenerationNumber(const sp &producer, - uint32_t *generation) { - MFX_DEBUG_TRACE_FUNC; - status_t status{}; - int slot{}; - bool bufferNeedsReallocation{}; - sp fence = new Fence(); - - using Input = HGraphicBufferProducer::DequeueBufferInput; - using Output = HGraphicBufferProducer::DequeueBufferOutput; - Return transResult = producer->dequeueBuffer( - Input{640, 480, HAL_PIXEL_FORMAT_YCBCR_420_888, 0}, - [&status, &slot, &bufferNeedsReallocation, &fence] - (HStatus hStatus, int32_t hSlot, Output const& hOutput) { - slot = static_cast(hSlot); - if (!h2b(hStatus, &status) || !h2b(hOutput.fence, &fence)) { - status = ::android::BAD_VALUE; - } else { - bufferNeedsReallocation = - hOutput.bufferNeedsReallocation; - } - }); - if (!transResult.isOk() || status != android::OK) { - return false; - } - HFenceWrapper hFenceWrapper{}; - if (!b2h(fence, &hFenceWrapper)) { - (void)producer->detachBuffer(static_cast(slot)).isOk(); - MFX_DEBUG_TRACE_PRINTF("Invalid fence received from dequeueBuffer."); - return false; - } - sp slotBuffer = new GraphicBuffer(); - // This assumes requestBuffer# returns an existing allocation - // instead of a new allocation. - transResult = producer->requestBuffer( - slot, - [&status, &slotBuffer, &generation]( - HStatus hStatus, - HBuffer const& hBuffer, - uint32_t generationNumber){ - if (h2b(hStatus, &status) && - h2b(hBuffer, &slotBuffer) && - slotBuffer) { - *generation = generationNumber; - slotBuffer->setGenerationNumber(generationNumber); - } else { - status = android::BAD_VALUE; - } - }); - if (!transResult.isOk()) { - return false; - } else if (status != android::NO_ERROR) { - (void)producer->detachBuffer(static_cast(slot)).isOk(); - return false; - } - (void)producer->detachBuffer(static_cast(slot)).isOk(); - return true; -} - -}; - -class MfxC2BufferQueueBlockPool::Impl - : public std::enable_shared_from_this { -private: - c2_status_t fetchFromIgbp_l( - uint32_t width, - uint32_t height, - uint32_t format, - C2MemoryUsage usage, - std::shared_ptr *block /* nonnull */) { - MFX_DEBUG_TRACE_FUNC; - // We have an IGBP now. - C2AndroidMemoryUsage androidUsage = usage; - status_t status{}; - int slot{}; - bool bufferNeedsReallocation{}; - sp fence = new Fence(); - - { // Call dequeueBuffer(). - using Input = HGraphicBufferProducer::DequeueBufferInput; - using Output = HGraphicBufferProducer::DequeueBufferOutput; - Return transResult = mProducer->dequeueBuffer( - Input{ - width, - height, - format, - androidUsage.asGrallocUsage()}, - [&status, &slot, &bufferNeedsReallocation, - &fence](HStatus hStatus, - int32_t hSlot, - Output const& hOutput) { - slot = static_cast(hSlot); - if (!h2b(hStatus, &status) || - !h2b(hOutput.fence, &fence)) { - status = ::android::BAD_VALUE; - } else { - bufferNeedsReallocation = - hOutput.bufferNeedsReallocation; - } - }); - if (!transResult.isOk() || status != android::OK) { - if (transResult.isOk()) { - ++mDqFailure; - if (status == android::INVALID_OPERATION || - status == android::TIMED_OUT || - status == android::WOULD_BLOCK) { - // Dequeue buffer is blocked temporarily. Retrying is - // required. - return C2_BLOCKING; - } - } - MFX_DEBUG_TRACE_PRINTF("cannot dequeue buffer %d", status); - return C2_BAD_VALUE; - } - mDqFailure = 0; - mLastDqTs = getTimestampNow(); - } - HFenceWrapper hFenceWrapper{}; - if (!b2h(fence, &hFenceWrapper)) { - MFX_DEBUG_TRACE_PRINTF("Invalid fence received from dequeueBuffer."); - return C2_BAD_VALUE; - } - MFX_DEBUG_TRACE_PRINTF("dequeued a buffer successfully"); - if (fence) { - static constexpr int kFenceWaitTimeMs = 10; - - status_t status = fence->wait(kFenceWaitTimeMs); - if (status == -ETIME) { - // fence is not signalled yet. - (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk(); - return C2_BLOCKING; - } - if (status != android::NO_ERROR) { - MFX_DEBUG_TRACE_PRINTF("buffer fence wait error %d", status); - (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk(); - return C2_BAD_VALUE; - } else if (mRenderCallback) { - nsecs_t signalTime = fence->getSignalTime(); - if (signalTime >= 0 && signalTime < INT64_MAX) { - mRenderCallback(mProducerId, slot, signalTime); - } else { - MFX_DEBUG_TRACE_PRINTF("got fence signal time of %lld", (long long)signalTime); - } - } - } - - sp &slotBuffer = mBuffers[slot]; - uint32_t outGeneration; - if (bufferNeedsReallocation || !slotBuffer) { - if (!slotBuffer) { - slotBuffer = new GraphicBuffer(); - } - // N.B. This assumes requestBuffer# returns an existing allocation - // instead of a new allocation. - Return transResult = mProducer->requestBuffer( - slot, - [&status, &slotBuffer, &outGeneration]( - HStatus hStatus, - HBuffer const& hBuffer, - uint32_t generationNumber){ - if (h2b(hStatus, &status) && - h2b(hBuffer, &slotBuffer) && - slotBuffer) { - slotBuffer->setGenerationNumber(generationNumber); - outGeneration = generationNumber; - } else { - status = android::BAD_VALUE; - } - }); - if (!transResult.isOk()) { - slotBuffer.clear(); - return C2_BAD_VALUE; - } else if (status != android::NO_ERROR) { - slotBuffer.clear(); - (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk(); - return C2_BAD_VALUE; - } - if (mGeneration == 0) { - // getting generation # lazily due to dequeue failure. - mGeneration = outGeneration; - } - } - if (slotBuffer) { - MFX_DEBUG_TRACE_PRINTF("buffer wraps %llu %d, handle:%p", (unsigned long long)mProducerId, slot,slotBuffer->handle); - C2Handle *c2Handle = WrapNativeCodec2GrallocHandle( - slotBuffer->handle, - slotBuffer->width, - slotBuffer->height, - slotBuffer->format, - slotBuffer->usage, - slotBuffer->stride, - slotBuffer->getGenerationNumber(), - mProducerId, slot); - if (c2Handle) { - std::shared_ptr alloc; - c2_status_t err = mAllocator->priorGraphicAllocation(c2Handle, &alloc); - if (err != C2_OK) { - native_handle_close(c2Handle); - native_handle_delete(c2Handle); - return err; - } - std::shared_ptr poolData = - std::make_shared( - slotBuffer->getGenerationNumber(), - mProducerId, slot, - shared_from_this()); - mPoolDatas[slot] = poolData; - *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData); - auto iter = gbuffer_.find(c2Handle); - if (iter == gbuffer_.end()) { - gbuffer_.emplace(c2Handle, slotBuffer->handle); - } else { - iter->second = slotBuffer->handle; - } - return C2_OK; - } - // Block was not created. call requestBuffer# again next time. - slotBuffer.clear(); - (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk(); - } - return C2_BAD_VALUE; - } - -public: - Impl(const std::shared_ptr &allocator) - : mInit(C2_OK), mProducerId(0), mGeneration(0), - mDqFailure(0), mLastDqTs(0), mLastDqLogTs(0), - mAllocator(allocator) { - } - - ~Impl() { - MFX_DEBUG_TRACE_FUNC; - bool noInit = false; - try { - for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) { - if (!noInit && mProducer) { - Return transResult = - mProducer->detachBuffer(static_cast(i)); - noInit = !transResult.isOk() || - static_cast(transResult) == HStatus::NO_INIT; - } - mBuffers[i].clear(); - } - gbuffer_.clear(); - } catch(const std::exception& e) { - MFX_DEBUG_TRACE_STREAM("Got an exception: " << e.what()); - } - } - - c2_status_t handle(const C2Handle * c2_hdl, buffer_handle_t *hndl){ - MFX_DEBUG_TRACE_FUNC; - auto iter = gbuffer_.find(c2_hdl); - if (iter != gbuffer_.end()) { - buffer_handle_t handle = iter->second; - if(handle != NULL) { - *hndl = handle; - return C2_OK; - } - } - MFX_DEBUG_TRACE_PRINTF("not BQ buffer" ); - return C2_CORRUPTED; - } - - c2_status_t fetchGraphicBlock( - uint32_t width, - uint32_t height, - uint32_t format, - C2MemoryUsage usage, - std::shared_ptr *block /* nonnull */) { - MFX_DEBUG_TRACE_FUNC; - block->reset(); - if (mInit != C2_OK) { - return mInit; - } - - static int kMaxIgbpRetryDelayUs = 10000; - - std::unique_lock lock(mMutex); - if (mLastDqLogTs == 0) { - mLastDqLogTs = getTimestampNow(); - } else { - int64_t now = getTimestampNow(); - if (now >= mLastDqLogTs + 5000000) { - if (now >= mLastDqTs + 1000000 || mDqFailure > 5) { - MFX_DEBUG_TRACE_PRINTF("last successful dequeue was %lld us ago, " - "%zu consecutive failures", - (long long)(now - mLastDqTs), mDqFailure); - } - mLastDqLogTs = now; - } - } - if (mProducerId == 0) { - std::shared_ptr alloc; - c2_status_t err = mAllocator->newGraphicAllocation( - width, height, format, usage, &alloc); - if (err != C2_OK) { - return err; - } - std::shared_ptr poolData = - std::make_shared( - 0, (uint64_t)0, ~0, shared_from_this()); - *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData); - MFX_DEBUG_TRACE_PRINTF("no producer allocated a buffer successfully"); - - return C2_OK; - } - c2_status_t status = fetchFromIgbp_l(width, height, format, usage, block); - if (status == C2_BLOCKING) { - lock.unlock(); - // in order not to drain cpu from component's spinning - ::usleep(kMaxIgbpRetryDelayUs); - } - - MFX_DEBUG_TRACE_I32(status); - return status; - } - - void setRenderCallback(const OnRenderCallback &renderCallback) { - MFX_DEBUG_TRACE_FUNC; - std::scoped_lock lock(mMutex); - mRenderCallback = renderCallback; - } - - void configureProducer(const sp &producer) { - MFX_DEBUG_TRACE_FUNC; - uint64_t producerId = 0; - uint32_t generation = 0; - bool haveGeneration = false; - if (producer) { - Return transResult = producer->getUniqueId(); - if (!transResult.isOk()) { - MFX_DEBUG_TRACE_PRINTF("configureProducer -- failed to connect to the producer"); - return; - } - producerId = static_cast(transResult); - // TODO: provide gneration number from parameter. - haveGeneration = getGenerationNumber(producer, &generation); - if (!haveGeneration) { - MFX_DEBUG_TRACE_PRINTF("get generationNumber failed %llu", - (unsigned long long)producerId); - } - } - int migrated = 0; - // poolDatas dtor should not be called during lock is held. - std::shared_ptr - poolDatas[NUM_BUFFER_SLOTS]; - { - sp buffers[NUM_BUFFER_SLOTS]; - std::scoped_lock lock(mMutex); - bool noInit = false; - for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) { - if (!noInit && mProducer) { - Return transResult = - mProducer->detachBuffer(static_cast(i)); - noInit = !transResult.isOk() || - static_cast(transResult) == HStatus::NO_INIT; - } - } - int32_t oldGeneration = mGeneration; - if (producer) { - mProducer = producer; - mProducerId = producerId; - mGeneration = haveGeneration ? generation : 0; - } else { - mProducer = nullptr; - mProducerId = 0; - mGeneration = 0; - MFX_DEBUG_TRACE_PRINTF("invalid producer producer(%d), generation(%d)", - (bool)producer, haveGeneration); - } - if (mProducer && haveGeneration) { // migrate buffers - for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) { - std::shared_ptr data = - mPoolDatas[i].lock(); - if (data) { - int slot = data->migrate( - mProducer, generation, - producerId, mBuffers, oldGeneration); - if (slot >= 0) { - buffers[slot] = mBuffers[i]; - mBuffers[i] = NULL; - poolDatas[slot] = data; - ++migrated; - } - } else { - // free buffer migrate - if (mBuffers[i]) { - sp const& graphicBuffer = mBuffers[i]; - graphicBuffer->setGenerationNumber(generation); - - HBuffer hBuffer{}; - uint32_t hGenerationNumber{}; - if (!b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) - { - MFX_DEBUG_TRACE_PRINTF("I to O conversion failed"); - continue; - } - - bool converted{}; - status_t bStatus{}; - int slot_new; - int *outSlot = &slot_new; - Return transResult = - producer->attachBuffer(hBuffer, hGenerationNumber, - [&converted, &bStatus, outSlot]( - HStatus hStatus, int32_t hSlot, bool releaseAll) { - converted = h2b(hStatus, &bStatus); - *outSlot = static_cast(hSlot); - if (converted && releaseAll && bStatus == android::OK) - { - bStatus = android::INVALID_OPERATION; - } - }); - if (!transResult.isOk() || !converted || bStatus != android::OK) - { - MFX_DEBUG_TRACE_PRINTF("attach failed %d", static_cast(bStatus)); - continue; - } - MFX_DEBUG_TRACE_PRINTF("local migration from gen %u : %u slot %d : %d", - oldGeneration, generation, i, slot_new); - - buffers[slot_new] = mBuffers[i]; - producer->cancelBuffer(slot_new, hidl_handle{}).isOk(); - ++migrated; - } - } - } - } - for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) { - mBuffers[i] = buffers[i]; - mPoolDatas[i] = poolDatas[i]; - } - } - if (producer && haveGeneration) { - MFX_DEBUG_TRACE_PRINTF("local generation change %u , " - "bqId: %llu migrated buffers # %d", - generation, (unsigned long long)producerId, migrated); - } - } - - c2_status_t requestNewBufferSet(int32_t bufferCount) { - MFX_DEBUG_TRACE_FUNC; - - if (bufferCount <= 0) { - MFX_DEBUG_TRACE_PRINTF("Invalid requested buffer count = %d", bufferCount); - return C2_BAD_VALUE; - } - - std::lock_guard lock(mMutex); - if (!mProducer) { - MFX_DEBUG_TRACE_PRINTF("No HGraphicBufferProducer is configured..."); - return C2_NO_INIT; - } - - mProducer->setMaxDequeuedBufferCount(bufferCount); - return C2_OK; - } - - void getBufferQueueProducer(sp &producer) { - producer = mProducer; - } - -private: - friend struct MfxC2BufferQueueBlockPoolData; - - void cancel(uint32_t generation, uint64_t igbp_id, int32_t igbp_slot) { - bool cancelled = false; - { - MFX_DEBUG_TRACE_FUNC; - try { - std::scoped_lock lock(mMutex); - if (generation == mGeneration && igbp_id == mProducerId && mProducer) { - (void)mProducer->cancelBuffer(igbp_slot, hidl_handle{}).isOk(); - cancelled = true; - } - } catch(const std::exception& e) { - MFX_DEBUG_TRACE_STREAM("Got an exception: " << e.what()); - } - } - } - - c2_status_t mInit; - uint64_t mProducerId; - uint32_t mGeneration; - OnRenderCallback mRenderCallback; - - size_t mDqFailure; - int64_t mLastDqTs; - int64_t mLastDqLogTs; - - const std::shared_ptr mAllocator; - - std::mutex mMutex; - sp mProducer; - sp mSavedProducer; - - sp mBuffers[NUM_BUFFER_SLOTS]; - std::weak_ptr mPoolDatas[NUM_BUFFER_SLOTS]; - std::map gbuffer_; -}; - -MfxC2BufferQueueBlockPoolData::MfxC2BufferQueueBlockPoolData( - uint32_t generation, uint64_t bqId, int32_t bqSlot, - const std::shared_ptr& owner, - const sp& producer) : - held(producer && bqId != 0), local(false), - generation(generation), bqId(bqId), bqSlot(bqSlot), - transfer(false), attach(false), display(false), - owner(owner), igbp(producer), - localPool() { - MFX_DEBUG_TRACE_FUNC; -} - -MfxC2BufferQueueBlockPoolData::MfxC2BufferQueueBlockPoolData( - uint32_t generation, uint64_t bqId, int32_t bqSlot, - const std::shared_ptr& pool) : - held(true), local(true), - generation(generation), bqId(bqId), bqSlot(bqSlot), - transfer(false), attach(false), display(false), - igbp(pool ? pool->mProducer : nullptr), - localPool(pool) { - MFX_DEBUG_TRACE_FUNC; -} - -MfxC2BufferQueueBlockPoolData::~MfxC2BufferQueueBlockPoolData() { - MFX_DEBUG_TRACE_FUNC; - if (!held || bqId == 0) { - return; - } - if (local) { - if (localPool) { - localPool->cancel(generation, bqId, bqSlot); - } - } else if (igbp && !owner.expired()) { - (void)igbp->cancelBuffer(bqSlot, hidl_handle{}).isOk(); - } -} - -int MfxC2BufferQueueBlockPoolData::migrate( - const sp& producer, - uint32_t toGeneration, uint64_t toBqId, - sp *buffers, uint32_t oldGeneration) { - MFX_DEBUG_TRACE_FUNC; - std::scoped_lock l(lock); - if (!held || bqId == 0) { - MFX_DEBUG_TRACE_PRINTF("buffer is not owned"); - return -1; - } - if (!local || !localPool) { - MFX_DEBUG_TRACE_PRINTF("pool is not local"); - return -1; - } - if (bqSlot < 0 || bqSlot >= NUM_BUFFER_SLOTS || !buffers[bqSlot]) { - MFX_DEBUG_TRACE_PRINTF("slot is not in effect"); - return -1; - } - if (toGeneration == generation && bqId == toBqId) { - MFX_DEBUG_TRACE_PRINTF("cannot migrate to same bufferqueue"); - return -1; - } - if (oldGeneration != generation) { - MFX_DEBUG_TRACE_PRINTF("cannot migrate stale buffer"); - } - if (transfer) { - // either transferred or detached. - MFX_DEBUG_TRACE_PRINTF("buffer is in transfer"); - return -1; - } - sp const& graphicBuffer = buffers[bqSlot]; - graphicBuffer->setGenerationNumber(toGeneration); - - HBuffer hBuffer{}; - uint32_t hGenerationNumber{}; - if (!b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) { - MFX_DEBUG_TRACE_PRINTF("I to O conversion failed"); - return -1; - } - - bool converted{}; - status_t bStatus{}; - int slot; - int *outSlot = &slot; - Return transResult = - producer->attachBuffer(hBuffer, hGenerationNumber, - [&converted, &bStatus, outSlot]( - HStatus hStatus, int32_t hSlot, bool releaseAll) { - converted = h2b(hStatus, &bStatus); - *outSlot = static_cast(hSlot); - if (converted && releaseAll && bStatus == android::OK) { - bStatus = android::INVALID_OPERATION; - } - }); - if (!transResult.isOk() || !converted || bStatus != android::OK) { - MFX_DEBUG_TRACE_PRINTF("attach failed %d", static_cast(bStatus)); - return -1; - } - MFX_DEBUG_TRACE_PRINTF("local migration from gen %u : %u slot %d : %d", - generation, toGeneration, bqSlot, slot); - generation = toGeneration; - bqId = toBqId; - bqSlot = slot; - return slot; -} -MfxC2BufferQueueBlockPool::MfxC2BufferQueueBlockPool( - const std::shared_ptr &allocator, const local_id_t localId) - : mAllocator(allocator), local_id_(localId), impl_(new Impl(allocator)) {} - -c2_status_t MfxC2BufferQueueBlockPool::fetchGraphicBlock( - uint32_t width, - uint32_t height, - uint32_t format, - C2MemoryUsage usage, - std::shared_ptr *block /* nonnull */) { - MFX_DEBUG_TRACE_FUNC; - if (impl_) { - return impl_->fetchGraphicBlock(width, height, format, usage, block); - } - return C2_CORRUPTED; -} - -void MfxC2BufferQueueBlockPool::configureProducer(const sp &producer) { - MFX_DEBUG_TRACE_FUNC; - ALOGE("MfxC2BufferQueueBlockPool::configureProducer, line:%d", __LINE__); - if (impl_) { - impl_->configureProducer(producer); - } -} - -void MfxC2BufferQueueBlockPool::setRenderCallback(const OnRenderCallback &renderCallback) { - MFX_DEBUG_TRACE_FUNC; - ALOGE("MfxC2BufferQueueBlockPool::setRenderCallback, line:%d", __LINE__); - if (impl_) { - impl_->setRenderCallback(renderCallback); - } -} - -c2_status_t MfxC2BufferQueueBlockPool::ImportHandle(const std::shared_ptr block, buffer_handle_t *hndl){ - MFX_DEBUG_TRACE_FUNC; - uint32_t width, height, format, stride, igbp_slot, generation; - uint64_t usage, igbp_id; - _UnwrapNativeCodec2GrallocMetadata(block->handle(), &width, &height, - &format, &usage, &stride, &generation, &igbp_id, - &igbp_slot); - - if (impl_ && igbp_slot < NUM_BUFFER_SLOTS) { - return impl_->handle(block->handle(), hndl); - } - - MFX_DEBUG_TRACE_PRINTF("invalid C2GraphicBlock, igbp_slot = %d", igbp_slot); - return C2_CORRUPTED; -} -c2_status_t MfxC2BufferQueueBlockPool::requestNewBufferSet(int32_t bufferCount) { - if (impl_) { - return impl_->requestNewBufferSet(bufferCount); - } - return C2_NO_INIT; -} - -bool MfxC2BufferQueueBlockPool::outputSurfaceSet(void) { - if (impl_) { - sp producer; - impl_->getBufferQueueProducer(producer); - - if (!producer) { - ALOGI("No HGraphicBufferProducer is configured..."); - return false; - } - } - return true; -} diff --git a/plugin_store/src/mfx_c2_plugin_store.cpp b/plugin_store/src/mfx_c2_plugin_store.cpp deleted file mode 100755 index 27c69671..00000000 --- a/plugin_store/src/mfx_c2_plugin_store.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2021 Intel Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include -#include -#include -#include - -#include - -#include "mfx_c2_buffer_queue.h" -#include "mfx_c2_allocator_id.h" -#include "mfx_debug.h" -#include "mfx_c2_debug.h" - -namespace android { - -C2Allocator* createAllocator(C2Allocator::id_t allocatorId) { - MFX_DEBUG_TRACE_FUNC; - MFX_DEBUG_TRACE_PRINTF("%s(): Fallback to create C2AllocatorGralloc (id=%u)", __func__, allocatorId); - return new C2AllocatorGralloc(allocatorId, true); -} - -std::shared_ptr fetchAllocator(C2Allocator::id_t allocatorId) { - MFX_DEBUG_TRACE_FUNC; - MFX_DEBUG_TRACE_PRINTF("%s(allocatorId=%d)", __func__, allocatorId); - static std::mutex sMutex; - static std::map> sCacheAllocators; - - std::lock_guard lock(sMutex); - - std::shared_ptr allocator; - auto iter = sCacheAllocators.find(allocatorId); - if (iter != sCacheAllocators.end()) { - allocator = iter->second.lock(); - if (allocator != nullptr) { - return allocator; - } - } - - allocator.reset(createAllocator(allocatorId)); - sCacheAllocators[allocatorId] = allocator; - return allocator; -} - -C2BlockPool* createBlockPool(C2Allocator::id_t allocatorId, C2BlockPool::local_id_t poolId) { - MFX_DEBUG_TRACE_FUNC; - MFX_DEBUG_TRACE_PRINTF("%s(allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId); - - std::shared_ptr allocator = fetchAllocator(allocatorId); - if (allocator == nullptr) { - MFX_DEBUG_TRACE_PRINTF("%s(): Failed to create allocator id=%u", __func__, allocatorId); - return nullptr; - } - - switch (allocatorId) { - case MFX_BUFFERQUEUE: - MFX_DEBUG_TRACE_PRINTF("%s(new MfxC2BufferQueueBlockPool allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId); - return new MfxC2BufferQueueBlockPool(allocator, poolId); - default: - MFX_DEBUG_TRACE_PRINTF("%s(): Unknown allocator id=%u", __func__, allocatorId); - return nullptr; - } -} - -} // namespace android - -extern "C" ::C2BlockPool* CreateBlockPool(::C2Allocator::id_t allocatorId, - ::C2BlockPool::local_id_t poolId) { - MFX_DEBUG_TRACE_FUNC; - MFX_DEBUG_TRACE_PRINTF("%s(allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId); - return ::android::createBlockPool(allocatorId, poolId); -} - -extern "C" ::C2Allocator* CreateAllocator(::C2Allocator::id_t allocatorId, ::c2_status_t* status) { - MFX_DEBUG_TRACE_FUNC; - MFX_DEBUG_TRACE_PRINTF("%s(allocatorId=%d)", __func__, allocatorId); - - ::C2Allocator* res = ::android::createAllocator(allocatorId); - *status = (res != nullptr) ? C2_OK : C2_BAD_INDEX; - return res; -} From fb91aca3dca402b4f55dbda76654b27bb8f2affa Mon Sep 17 00:00:00 2001 From: "Wan, Hao" Date: Wed, 16 Oct 2024 13:55:51 +0000 Subject: [PATCH 09/14] Fix coverity issue CID 398855 CID 398855: 'Constant' variable guards dead code Refer to the implementation of ImportBuffer in minigbm: hardware/intel/external/minigbm-intel/cros_gralloc/gralloc1/cros_gralloc1_module.cc int32_t CrosGralloc1::importBuffer(const buffer_handle_t rawHandle, buffer_handle_t *outBuffer) Tracked-On: OAM-126428 Signed-off-by: Wan, Hao (cherry picked from commit e87dd391c89b1cdc30d7f75b3b9022f079acd0a9) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_utils/src/mfx_gralloc1.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/c2_utils/src/mfx_gralloc1.cpp b/c2_utils/src/mfx_gralloc1.cpp index 038260c9..147dd157 100755 --- a/c2_utils/src/mfx_gralloc1.cpp +++ b/c2_utils/src/mfx_gralloc1.cpp @@ -277,20 +277,16 @@ buffer_handle_t MfxGralloc1Module::ImportBuffer(const buffer_handle_t rawHandle) { MFX_DEBUG_TRACE_FUNC; c2_status_t res = C2_OK; - buffer_handle_t *outBuffer = nullptr; - buffer_handle_t out = nullptr; + buffer_handle_t outBuffer = nullptr; - int32_t gr1_res = (*m_grImportBufferFunc)(m_gralloc1_dev, rawHandle, outBuffer); - if (GRALLOC1_ERROR_NONE != gr1_res || nullptr == outBuffer) { + int32_t gr1_res = (*m_grImportBufferFunc)(m_gralloc1_dev, rawHandle, &outBuffer); + if (GRALLOC1_ERROR_NONE != gr1_res) { MFX_DEBUG_TRACE_I32(gr1_res); res = C2_BAD_STATE; } - if (outBuffer) - out = const_cast(*outBuffer); - MFX_DEBUG_TRACE__android_c2_status_t(res); - return out; + return outBuffer; } c2_status_t MfxGralloc1Module::GetBackingStore(const buffer_handle_t rawHandle, uint64_t *id) From a0693375fba205d7bfe73c4347fdfdf7bb2e9bf5 Mon Sep 17 00:00:00 2001 From: Lina Sun Date: Sun, 29 Sep 2024 08:04:42 +0000 Subject: [PATCH 10/14] Remove dumping code related to macro MFX_DEBUG_DUMP_FRAME Will add dumping code in another way, input & output buffer dump for encoder & decoder will all be able to be configured by set property. Tracked-On: OAM-124732 Signed-off-by: Lina Sun (cherry picked from commit d150b3b51c43f6e8f0295ed172aefd09f3e85cfb) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_buffers/src/mfx_c2_frame_in.cpp | 6 -- .../include/mfx_c2_decoder_component.h | 6 -- .../src/mfx_c2_decoder_component.cpp | 69 ------------------- c2_utils/include/mfx_debug.h | 1 - 4 files changed, 82 deletions(-) diff --git a/c2_buffers/src/mfx_c2_frame_in.cpp b/c2_buffers/src/mfx_c2_frame_in.cpp index 8f80cd8e..9b150581 100755 --- a/c2_buffers/src/mfx_c2_frame_in.cpp +++ b/c2_buffers/src/mfx_c2_frame_in.cpp @@ -187,12 +187,6 @@ c2_status_t MfxC2FrameIn::MfxC2LoadSurfaceInSW(C2ConstGraphicBlock& c_graph_bloc } } -#if MFX_DEBUG_DUMP_FRAME == MFX_DEBUG_YES - static int frameIndex = 0; - static YUVWriter writer("/data/local/tmp",std::vector({}),"encoder_frame.log"); - writer.Write(m_yuvData.get(), stride, height, frameIndex++); -#endif - mfx_sts = InitMfxFrameSW(buf_pack.ordinal.timestamp.peeku(), buf_pack.ordinal.frameIndex.peeku(), m_yuvData.get(), m_yuvData.get()+y_plane_size, width, height, stride, MFX_FOURCC_NV12, m_mfxFrameInfo, m_pMfxFrameSurface); diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index b6f0c28e..e1789998 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -252,12 +252,6 @@ class MfxC2DecoderComponent : public MfxC2Component MFXVideoVPP* m_vpp; bool m_vppConversion = false; -#if MFX_DEBUG_DUMP_FRAME == MFX_DEBUG_YES - int m_count = 0; - std::mutex m_count_lock; - bool NeedDumpBuffer(); -#endif - /* -----------------------C2Parameters--------------------------- */ std::shared_ptr m_name; std::shared_ptr m_kind; diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index c66d3d4c..47594f6e 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -2256,42 +2256,6 @@ void MfxC2DecoderComponent::Drain(std::unique_ptr&& work) } } -#if MFX_DEBUG_DUMP_FRAME == MFX_DEBUG_YES -bool MfxC2DecoderComponent::NeedDumpBuffer() { - MFX_DEBUG_TRACE_FUNC; - const char* key = "mediacodec2.dump.buffer"; - char* value = new char[20]; - int len = property_get(key, value, "0"); - -#include -#include - - std::stringstream strValue; - strValue << value; - - unsigned int m_frame_number = 0; - strValue >> m_frame_number; - - m_count_lock.lock(); - if (m_count) { - delete[] value; - m_count_lock.unlock(); - return true; - } else { - delete[] value; - if (len > 0 && m_frame_number > 0) { - m_count = m_frame_number; - MFX_DEBUG_TRACE_PRINTF("--------triggered to dump %d buffers---------", m_frame_number); - property_set(key, "0"); - m_count_lock.unlock(); - return true; - } - m_count_lock.unlock(); - return false; - } -} -#endif - void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint sync_point) { MFX_DEBUG_TRACE_FUNC; @@ -2455,39 +2419,6 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn } m_updatingC2Configures.clear(); -#if MFX_DEBUG_DUMP_FRAME == MFX_DEBUG_YES - static FILE* m_f = 0; - if (NeedDumpBuffer()) { - const C2GraphicView& output_view = block->map().get(); - m_count_lock.lock(); - if (m_count) { - const uint8_t* srcY = output_view.data()[C2PlanarLayout::PLANE_Y]; - const uint8_t* srcU = output_view.data()[C2PlanarLayout::PLANE_U]; - const uint8_t* srcV = output_view.data()[C2PlanarLayout::PLANE_V]; - if (!m_f) { - m_f = fopen("/data/local/traces/decoder_frame.yuv", "w+"); - MFX_DEBUG_TRACE_STREAM("/data/local/traces/decoder_frame.yuv: create:" << m_f); - } - if (m_f) { - size_t copied_Y = 0, copied_U = 0; - copied_Y = fwrite(srcY, mfx_surface->Data.PitchLow * m_mfxVideoParams.mfx.FrameInfo.CropH, 1, m_f); - copied_U = fwrite(srcU, mfx_surface->Data.PitchLow * m_mfxVideoParams.mfx.FrameInfo.CropH / 2, 1, m_f); - MFX_DEBUG_TRACE_PRINTF("############# dumping #%d decoded buffer in size: %dx%d, Y:%zu, U:%zu #################", - m_count, mfx_surface->Data.PitchLow, m_mfxVideoParams.mfx.FrameInfo.CropH, copied_Y, copied_U); - if (copied_Y > 0 || copied_U > 0) - m_count--; - } - } - m_count_lock.unlock(); - } - m_count_lock.lock(); - if (m_count == 0 && m_f) { - fclose(m_f); - MFX_DEBUG_TRACE_MSG("dump file is closed"); - m_f = NULL; - } - m_count_lock.unlock(); -#endif worklet->output.buffers.push_back(out_buffer); block = nullptr; } diff --git a/c2_utils/include/mfx_debug.h b/c2_utils/include/mfx_debug.h index c4ecda8e..e41b8385 100755 --- a/c2_utils/include/mfx_debug.h +++ b/c2_utils/include/mfx_debug.h @@ -26,7 +26,6 @@ #define MFX_DEBUG MFX_DEBUG_NO // enables DEBUG output #define MFX_PERF MFX_DEBUG_NO // enables PERF output, doesn't depends on MFX_DEBUG #define MFX_ATRACE MFX_DEBUG_NO // enables systrace -#define MFX_DEBUG_DUMP_FRAME MFX_DEBUG_NO // enables write frame to file #define MFX_DEBUG_FILE MFX_DEBUG_NO // sends DEBUG and PERF output to file, otherwise to logcat From 4a67e1905d1e84bfe0341db33bc321afaa199de3 Mon Sep 17 00:00:00 2001 From: Lina Sun Date: Sat, 12 Oct 2024 13:53:54 +0000 Subject: [PATCH 11/14] Support dump of input & output for encoder & decoder Dump can be enabled by set property, detailed steps can be found in mfx_c2_encoder_component.cpp/mfx_c2_decoder_component.cpp, near InitDump(). Tracked-On: OAM-124732 Signed-off-by: Lina Sun (cherry picked from commit cebb891880b857c2786fcba880a390abe22dad7b) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_components/include/mfx_c2_component.h | 1 - .../include/mfx_c2_decoder_component.h | 13 + .../include/mfx_c2_encoder_component.h | 12 +- .../src/mfx_c2_decoder_component.cpp | 253 ++++++++++++++++++ .../src/mfx_c2_encoder_component.cpp | 166 ++++++++++-- ...droid.hardware.media.c2-default-arm.policy | 1 + ...oid.hardware.media.c2-default-arm64.policy | 1 + ...droid.hardware.media.c2-default-x86.policy | 1 + ...id.hardware.media.c2-default-x86_64.policy | 1 + c2_store/src/mfx_c2_store.cpp | 1 - c2_utils/include/mfx_c2_defs.h | 16 +- c2_utils/include/mfx_c2_utils.h | 11 +- c2_utils/include/mfx_c2_xml_parser.h | 2 - c2_utils/src/mfx_c2_utils.cpp | 4 +- c2_utils/src/mfx_c2_xml_parser.cpp | 24 +- 15 files changed, 451 insertions(+), 56 deletions(-) diff --git a/c2_components/include/mfx_c2_component.h b/c2_components/include/mfx_c2_component.h index 4d1ad096..2d4f0dd9 100755 --- a/c2_components/include/mfx_c2_component.h +++ b/c2_components/include/mfx_c2_component.h @@ -36,7 +36,6 @@ class MfxC2Component : public C2ComponentInterface, struct CreateConfig { int flags{0}; - bool dump_output{false}; uint32_t concurrent_instances{0}; bool low_power_mode{false}; }; diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index e1789998..006b725a 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -29,6 +29,7 @@ #include "mfx_frame_pool_allocator.h" #include "mfx_gralloc_instance.h" #include "mfx_c2_setters.h" +#include "mfx_c2_utils.h" #include class MfxC2DecoderComponent : public MfxC2Component @@ -252,6 +253,18 @@ class MfxC2DecoderComponent : public MfxC2Component MFXVideoVPP* m_vpp; bool m_vppConversion = false; + std::unique_ptr m_outputWriter; + std::unique_ptr m_inputWriter; + + std::mutex m_dump_output_lock; + std::mutex m_dump_input_lock; + + uint32_t m_dump_count = 0; + // decoder output dump file number, during decoding one bitstream, if + // dump output multiple times, the first dumped file named xxx_0.yuv, + // second dumped file named xxx_1.yuv ... + uint32_t m_file_num = 0; + /* -----------------------C2Parameters--------------------------- */ std::shared_ptr m_name; std::shared_ptr m_kind; diff --git a/c2_components/include/mfx_c2_encoder_component.h b/c2_components/include/mfx_c2_encoder_component.h index ed2de8fb..4354e601 100755 --- a/c2_components/include/mfx_c2_encoder_component.h +++ b/c2_components/include/mfx_c2_encoder_component.h @@ -29,6 +29,7 @@ #include "mfx_c2_utils.h" #include "mfx_c2_vpp_wrapp.h" #include "mfx_c2_setters.h" +#include // Assumes all calls are done from one (working) thread, no sync is needed. // m_ctrlOnce accumulates subsequent changes for one next frame. @@ -202,8 +203,6 @@ class MfxC2EncoderComponent : public MfxC2Component std::shared_ptr m_c2Allocator; - std::unique_ptr m_outputWriter; - bool m_bHeaderSent{false}; mfxFrameSurface1 *m_encSrfPool; @@ -220,6 +219,15 @@ class MfxC2EncoderComponent : public MfxC2Component // Input frame info with width or height not 16byte aligned mfxFrameInfo m_mfxInputInfo; + std::unique_ptr m_outputWriter; + std::unique_ptr m_inputWriter; + + std::mutex m_dump_output_lock; + std::mutex m_dump_input_lock; + + uint32_t m_dump_count = 0; + uint32_t m_dump_frames_number = 0; //total frames to dump + /* -----------------------C2Parameters--------------------------- */ std::mutex m_c2ParameterMutex; std::shared_ptr m_name; diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index 47594f6e..2eaf0766 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -731,6 +731,67 @@ c2_status_t MfxC2DecoderComponent::Init() return MfxStatusToC2(mfx_res); } +// Dump input/output for decoder/encoder steps: +// +// 1. $adb shell +// 2. In adb shell, $setenforce 0 +// 3. In adb shell, +// +// Case 1) For decoder input dump: $setprop c2.decoder.dump.input true +// Case 2) For decoder output dump: $setprop c2.decoder.dump.output.number 10 +// Case 3) For encoder input dump: $setprop c2.encoder.dump.input.number 10 +// Case 4) For encoder output dump: $setprop c2.encoder.dump.output true +// +// yuv frames number to dump can be set as needed. +// +// 4. Run decode/encoder, when done, dumped files can be found in /data/local/traces. +// +// For cases 1), 3) and 4), for one bitsteam decode or one yuv file encode, can +// only dump once, dumped files are named in: +// "decoder/encoder name - year - month - day - hour -minute - second". +// Dumped files will not be automatically deleted/overwritten in next run, will +// need be deleted manually. +// +// For case 2), for one bitstream decode, output can be dumped multiple times +// during decode process, setprop need be run again for each dump, dumped files +// are named in "xxx_0.yuv", "xxx_1.yuv" ... +// +// 5. When viewing yuv frames, check surface width & height in logs. + +static void InitDump(std::unique_ptr& input_writer, + std::shared_ptr decoder_name) +{ + MFX_DEBUG_TRACE_FUNC; + + bool dump_input_enabled = false; + char* value = new char[20]; + if(property_get(DECODER_DUMP_INPUT_KEY, value, NULL) > 0) { + if(strcasecmp(value, "true") == 0) { + dump_input_enabled = true; + property_set(DECODER_DUMP_INPUT_KEY, NULL); + } + } + + if (dump_input_enabled) { + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::time_t now_c = std::chrono::system_clock::to_time_t(now); + std::ostringstream file_name; + std::tm local_tm; + localtime_r(&now_c, &local_tm); + + file_name << decoder_name->m.value << "-" << + std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".bin"; + + MFX_DEBUG_TRACE_STREAM("Decoder input dump is started to " << + MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_DECODER_SUB_DIR << "/" + <(MFX_C2_DUMP_DIR, + std::vector({MFX_C2_DUMP_DECODER_SUB_DIR, + MFX_C2_DUMP_INPUT_SUB_DIR}), file_name.str()); + } +} + c2_status_t MfxC2DecoderComponent::DoStart() { MFX_DEBUG_TRACE_FUNC; @@ -751,6 +812,8 @@ c2_status_t MfxC2DecoderComponent::DoStart() mfx_res = InitSession(); if (MFX_ERR_NONE != mfx_res) break; + InitDump(m_inputWriter, m_name); + m_workingQueue.Start(); m_waitingQueue.Start(); } while(false); @@ -799,6 +862,16 @@ c2_status_t MfxC2DecoderComponent::DoStop(bool abort) m_c2Bitstream->GetFrameConstructor()->Close(); } + if(m_outputWriter.get() != NULL && m_outputWriter->IsOpen()) { + m_outputWriter->Close(); + } + m_outputWriter.reset(); + + if(m_inputWriter.get() != NULL && m_inputWriter->IsOpen()) { + m_inputWriter->Close(); + } + m_inputWriter.reset(); + m_OperationState = OperationState::STOPPED; return C2_OK; } @@ -2083,6 +2156,14 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr&& work) if (!m_bSetHdrStatic) UpdateHdrStaticInfo(); mfxBitstream *bs = m_c2Bitstream->GetFrameConstructor()->GetMfxBitstream().get(); + + { + std::lock_guard lock(m_dump_input_lock); + if (m_inputWriter.get() != NULL && bs != NULL && bs->DataLength > 0) { + m_inputWriter->Write(bs->Data, bs->DataLength); + } + } + MfxC2FrameOut frame_out; do { // check bitsream is empty @@ -2256,6 +2337,170 @@ void MfxC2DecoderComponent::Drain(std::unique_ptr&& work) } } +const u_int16_t ytile_width = 16; +const u_int16_t ytile_height = 32; +static void one_ytiled_to_linear(const unsigned char *src, char *dst, u_int16_t x, u_int16_t y, + u_int16_t width, u_int16_t height, uint32_t offset) +{ + // x and y follow linear + u_int32_t count = x + y * width / ytile_width; + + for (int j = 0; j < ytile_width * ytile_height; j += ytile_width) { + memcpy(dst + offset + width * ytile_height * y + width * j / ytile_width + x * ytile_width, + src + offset + j + ytile_width * ytile_height * count, ytile_width); + } +} + +static void* ytiled_to_linear(uint32_t total_size, uint32_t y_size, uint32_t stride, + const unsigned char *src) +{ + char* dst = (char*)malloc(total_size * 2); + if (NULL == dst) return NULL; + + memset(dst, 0, total_size * 2); + + u_int16_t height = y_size / stride; + + // Y + u_int16_t y_hcount = height / ytile_height + (height % ytile_height != 0); + for (u_int16_t x = 0; x < stride / ytile_width; x ++) { + for (u_int16_t y = 0; y < y_hcount; y ++) { + one_ytiled_to_linear(src, dst, x, y, stride, height, 0); + } + } + + // UV + u_int16_t uv_hcount = (height / ytile_height / 2) + (height % (ytile_height * 2) != 0); + for (u_int16_t x = 0; x < stride / ytile_width; x ++) { + for (u_int16_t y = 0; y < uv_hcount; y ++) { + one_ytiled_to_linear(src, dst, x, y, stride, height / 2, y_size); + } + } + + return dst; +} + +static bool NeedDumpOutput(uint32_t& dump_count, + std::unique_ptr& output_writer, + std::shared_ptr decoder_name, + uint32_t& file_num) +{ + MFX_DEBUG_TRACE_FUNC; + bool result = false; + char* value = new char[20]; + unsigned int frame_number = 0; + + if(property_get(DECODER_DUMP_OUTPUT_KEY, value, NULL) > 0) { + std::stringstream strValue; + strValue << value; + strValue >> frame_number; + } + + if (dump_count) { + delete[] value; + result = true; + } else { + delete[] value; + if (frame_number > 0) { + property_set(DECODER_DUMP_OUTPUT_KEY, NULL); + + std::ostringstream file_name; + file_name << decoder_name->m.value << "frame_" << std::to_string(file_num) << ".yuv"; + + MFX_DEBUG_TRACE_STREAM("Decoder output dump is started to " << + MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_DECODER_SUB_DIR << "/" + <(MFX_C2_DUMP_DIR, + std::vector({MFX_C2_DUMP_DECODER_SUB_DIR, + MFX_C2_DUMP_OUTPUT_SUB_DIR}), file_name.str()); + + if(output_writer) { + dump_count = frame_number; + file_num ++; + MFX_DEBUG_TRACE_PRINTF("--------triggered to dump %d buffers---------", frame_number); + result = true; + } else { + MFX_DEBUG_TRACE_PRINTF("create output writer failed"); + result = false; + } + } + } + return result; +} + +static void DumpOutput(std::shared_ptr block, + std::shared_ptr mfx_surface, + uint32_t& dump_count, mfxVideoParam mfxVideoParams, + std::unique_ptr& output_writer) +{ + MFX_DEBUG_TRACE_FUNC; + static std::ofstream dump_stream; + + const C2GraphicView& output_view = block->map().get(); + + if (dump_count) { + const unsigned char* srcY = (const unsigned char*)output_view.data()[C2PlanarLayout::PLANE_Y]; + const unsigned char* srcUV = (const unsigned char*)output_view.data()[C2PlanarLayout::PLANE_U]; + + if (output_writer && srcY != NULL && srcUV != NULL) { + if(MFX_IOPATTERN_OUT_VIDEO_MEMORY == mfxVideoParams.IOPattern) { + const uint32_t align_width = 128; + const uint32_t align_height = 32; + + uint32_t surface_width = mfx_surface->Info.Width % align_width == 0? mfx_surface->Info.Width : + (mfx_surface->Info.Width / align_width + 1) * align_width; + uint32_t surface_height = mfx_surface->Info.Height % align_height == 0? mfx_surface->Info.Height : + (mfx_surface->Info.Height / align_height + 1) * align_height; + + uint32_t pix_len = (MFX_FOURCC_P010 == mfx_surface->Info.FourCC) ? 2 : 1; + + uint32_t total_size = surface_width * pix_len * surface_height * 3 / 2; + uint32_t y_size = surface_width * pix_len * surface_height; + uint32_t stride = surface_width * pix_len; + + unsigned char* srcY_linear = (unsigned char *)ytiled_to_linear(total_size, + y_size, stride, (const unsigned char *)srcY); + + if (NULL != srcY_linear) { + + output_writer->Write(srcY_linear, total_size); + free(srcY_linear); + srcY_linear = NULL; + + dump_count --; + + MFX_DEBUG_TRACE_PRINTF("######## dumping #%d to last decoded buffer in size: %dx%d ########", + dump_count, surface_width, surface_height); + } + } else { // IOPattern is system memory + if (NULL != srcY && NULL != srcUV) { + output_writer->Write(srcY, mfx_surface->Data.PitchLow * mfxVideoParams.mfx.FrameInfo.CropH); + output_writer->Write(srcUV, mfx_surface->Data.PitchLow * mfxVideoParams.mfx.FrameInfo.CropH / 2); + + uint32_t dump_width = (MFX_FOURCC_P010 == mfx_surface->Info.FourCC) ? + mfx_surface->Data.PitchLow / 2 : mfx_surface->Data.PitchLow; + + dump_count --; + + MFX_DEBUG_TRACE_PRINTF("######## dumping #%d to last decoded buffer in size: %dx%d ########", + dump_count, dump_width, mfxVideoParams.mfx.FrameInfo.CropH); + + } + } + } + } + + if (dump_count == 0 && output_writer.get() != NULL) { + output_writer->Close(); + output_writer.reset(); + + MFX_DEBUG_TRACE_MSG("Output writer reset"); + } + + return; +} + void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint sync_point) { MFX_DEBUG_TRACE_FUNC; @@ -2419,6 +2664,14 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn } m_updatingC2Configures.clear(); + { + std::lock_guard lock(m_dump_output_lock); + + if (NeedDumpOutput(m_dump_count, m_outputWriter, m_name, m_file_num)) { + DumpOutput(block, mfx_surface, m_dump_count, m_mfxVideoParams, m_outputWriter); + } + } + worklet->output.buffers.push_back(out_buffer); block = nullptr; } diff --git a/c2_components/src/mfx_c2_encoder_component.cpp b/c2_components/src/mfx_c2_encoder_component.cpp index 5278935f..e62e834b 100755 --- a/c2_components/src/mfx_c2_encoder_component.cpp +++ b/c2_components/src/mfx_c2_encoder_component.cpp @@ -604,6 +604,101 @@ c2_status_t MfxC2EncoderComponent::Init() return MfxStatusToC2(mfx_res); } +// Dump input/output for decoder/encoder steps: +// +// 1. $adb shell +// 2. In adb shell, $setenforce 0 +// 3. In adb shell, +// +// Case 1) For decoder input dump: $setprop c2.decoder.dump.input true +// Case 2) For decoder output dump: $setprop c2.decoder.dump.output.number 10 +// Case 3) For encoder input dump: $setprop c2.encoder.dump.input.number 10 +// Case 4) For encoder output dump: $setprop c2.encoder.dump.output true +// +// yuv frames number to dump can be set as needed. +// +// 4. Run decode/encoder, when done, dumped files can be found in /data/local/traces. +// +// For cases 1), 3) and 4), for one bitsteam decode or one yuv file encode, can +// only dump once, dumped files are named in: +// "decoder/encoder name - year - month - day - hour -minute - second". +// Dumped files will not be automatically deleted/overwritten in next run, will +// need be deleted manually. +// +// For case 2), for one bitstream decode, output can be dumped multiple times +// during decode process, setprop need be run again for each dump, dumped files +// are named in "xxx_0.yuv", "xxx_1.yuv" ... +// +// 5. When viewing yuv frames, check surface width & height in logs. + +static void InitDump(std::unique_ptr& output_writer, + std::unique_ptr& input_writer, + uint32_t& dump_frames_number, + std::shared_ptr encoder_name) +{ + MFX_DEBUG_TRACE_FUNC; + + bool dump_output_enabled = false; + bool dump_input_enabled = false; + char* value = new char[20]; + + if(property_get(ENCODER_DUMP_OUTPUT_KEY, value, NULL) > 0) { + if(strcasecmp(value, "true") == 0) { + dump_output_enabled = true; + property_set(ENCODER_DUMP_OUTPUT_KEY, NULL); + } + } + + memset(value, sizeof(value), 0); + + if(property_get(ENCODER_DUMP_INPUT_KEY, value, NULL) > 0) { + std::stringstream strValue; + strValue << value; + strValue >> dump_frames_number; + + if(dump_frames_number > 0) { + dump_input_enabled = true; + property_set(ENCODER_DUMP_INPUT_KEY, NULL); + } + } + + if (dump_output_enabled || dump_input_enabled) { + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::time_t now_c = std::chrono::system_clock::to_time_t(now); + std::ostringstream file_name; + std::tm local_tm; + localtime_r(&now_c, &local_tm); + + // make dump directory and create dump file + if(dump_output_enabled) { + file_name << encoder_name->m.value << "-" << + std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".bin"; + + MFX_DEBUG_TRACE_STREAM("Encoder output dump is started to " << + MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_ENCODER_SUB_DIR << "/" << + MFX_C2_DUMP_OUTPUT_SUB_DIR << "/" << file_name.str()); + + output_writer = std::make_unique(MFX_C2_DUMP_DIR, + std::vector({MFX_C2_DUMP_ENCODER_SUB_DIR, + MFX_C2_DUMP_OUTPUT_SUB_DIR}), file_name.str()); + } + + if(dump_input_enabled) { + file_name.str(""); + file_name << encoder_name->m.value << "-" << + std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".yuv"; + + MFX_DEBUG_TRACE_STREAM("Encoder input dump is started to " << + MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_ENCODER_SUB_DIR << "/" << + MFX_C2_DUMP_INPUT_SUB_DIR << "/" << file_name.str()); + + input_writer = std::make_unique(MFX_C2_DUMP_DIR, + std::vector({MFX_C2_DUMP_ENCODER_SUB_DIR, + MFX_C2_DUMP_INPUT_SUB_DIR}), file_name.str()); + } + } +} + c2_status_t MfxC2EncoderComponent::DoStart() { MFX_DEBUG_TRACE_FUNC; @@ -653,27 +748,11 @@ c2_status_t MfxC2EncoderComponent::DoStart() } m_bAllocatorSet = allocator_required; } - m_workingQueue.Start(); - m_waitingQueue.Start(); - if (m_createConfig.dump_output) { - - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - std::time_t now_c = std::chrono::system_clock::to_time_t(now); - std::ostringstream oss; - std::tm local_tm; - localtime_r(&now_c, &local_tm); - - oss << m_name << "-" << std::put_time(std::localtime(&now_c), "%Y%m%d%H%M%S") << ".bin"; - - MFX_DEBUG_TRACE_STREAM("Encoder output dump is started to " << - MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_OUTPUT_SUB_DIR << "/" << - oss.str()); - - m_outputWriter = std::make_unique(MFX_C2_DUMP_DIR, - std::vector({MFX_C2_DUMP_OUTPUT_SUB_DIR}), oss.str()); - } + InitDump(m_outputWriter, m_inputWriter, m_dump_frames_number, m_name); + m_workingQueue.Start(); + m_waitingQueue.Start(); } while(false); return C2_OK; @@ -705,8 +784,16 @@ c2_status_t MfxC2EncoderComponent::DoStop(bool abort) FreeEncoder(); + if(m_outputWriter.get() != NULL && m_outputWriter->IsOpen()) { + m_outputWriter->Close(); + } m_outputWriter.reset(); + if(m_inputWriter.get() != NULL && m_inputWriter->IsOpen()) { + m_inputWriter->Close(); + } + m_inputWriter.reset(); + return C2_OK; } @@ -1432,6 +1519,37 @@ void MfxC2EncoderComponent::DoWork(std::unique_ptr&& work) } } + { + std::lock_guard lock(m_dump_input_lock); + + if (m_inputWriter.get() != NULL && m_dump_count < m_dump_frames_number + && MFX_IOPATTERN_IN_SYSTEM_MEMORY == m_mfxVideoParamsConfig.IOPattern + && (MFX_FOURCC_NV12 == m_mfxVideoParamsState.mfx.FrameInfo.FourCC + || MFX_FOURCC_P010 == m_mfxVideoParamsState.mfx.FrameInfo.FourCC)) { + + mfxFrameSurface1* mfx_surface = mfx_frame_in.GetMfxFrameSurface(); + const uint8_t* srcY = mfx_surface->Data.Y; + const uint8_t* srcUV = mfx_surface->Data.UV; + + if (NULL != srcY && NULL != srcUV) { + m_inputWriter->Write(srcY, mfx_surface->Data.PitchLow * mfx_surface->Info.CropH); + m_inputWriter->Write(srcUV, mfx_surface->Data.PitchLow * mfx_surface->Info.CropH / 2); + + uint32_t dump_width = (MFX_FOURCC_P010 == m_mfxVideoParamsState.mfx.FrameInfo.FourCC) ? + mfx_surface->Data.PitchLow / 2 : mfx_surface->Data.PitchLow; + + m_dump_count ++; + + MFX_DEBUG_TRACE_PRINTF("######## dumping #%d encoder input buffer in size: %dx%d ########", + m_dump_count, dump_width, mfx_surface->Info.CropH); + } + + if(m_dump_count == m_dump_frames_number) { + m_inputWriter->Close(); + } + } + } + MfxC2BitstreamOut mfx_bitstream; res = AllocateBitstream(work, &mfx_bitstream); if(C2_OK != res) break; @@ -1610,9 +1728,13 @@ void MfxC2EncoderComponent::WaitWork(std::unique_ptr&& work, else { MFX_DEBUG_TRACE_STREAM(NAMED(mfx_bitstream->DataOffset) << NAMED(mfx_bitstream->DataLength)); - if (m_outputWriter && mfx_bitstream->DataLength > 0) { - m_outputWriter->Write(mfx_bitstream->Data + mfx_bitstream->DataOffset, - mfx_bitstream->DataLength); + { + std::lock_guard lock(m_dump_output_lock); + + if (m_outputWriter.get() != NULL && mfx_bitstream->DataLength > 0) { + m_outputWriter->Write(mfx_bitstream->Data + mfx_bitstream->DataOffset, + mfx_bitstream->DataLength); + } } C2ConstLinearBlock const_linear = bit_stream.GetC2LinearBlock()->share( diff --git a/c2_store/seccomp_policy/android.hardware.media.c2-default-arm.policy b/c2_store/seccomp_policy/android.hardware.media.c2-default-arm.policy index 9042cd77..408121d2 100644 --- a/c2_store/seccomp_policy/android.hardware.media.c2-default-arm.policy +++ b/c2_store/seccomp_policy/android.hardware.media.c2-default-arm.policy @@ -64,6 +64,7 @@ restart_syscall: 1 rt_sigreturn: 1 getrandom: 1 madvise: 1 +mkdirat: 1 # crash dump policy additions sigreturn: 1 diff --git a/c2_store/seccomp_policy/android.hardware.media.c2-default-arm64.policy b/c2_store/seccomp_policy/android.hardware.media.c2-default-arm64.policy index 5d0284f6..241d6385 100644 --- a/c2_store/seccomp_policy/android.hardware.media.c2-default-arm64.policy +++ b/c2_store/seccomp_policy/android.hardware.media.c2-default-arm64.policy @@ -60,6 +60,7 @@ restart_syscall: 1 rt_sigreturn: 1 getrandom: 1 madvise: 1 +mkdirat: 1 # crash dump policy additions clock_gettime: 1 diff --git a/c2_store/seccomp_policy/android.hardware.media.c2-default-x86.policy b/c2_store/seccomp_policy/android.hardware.media.c2-default-x86.policy index 50edbde8..8547727d 100644 --- a/c2_store/seccomp_policy/android.hardware.media.c2-default-x86.policy +++ b/c2_store/seccomp_policy/android.hardware.media.c2-default-x86.policy @@ -63,6 +63,7 @@ uname: 1 memfd_create: 1 ftruncate: 1 ftruncate64: 1 +mkdirat: 1 # Required by AddressSanitizer gettid: 1 diff --git a/c2_store/seccomp_policy/android.hardware.media.c2-default-x86_64.policy b/c2_store/seccomp_policy/android.hardware.media.c2-default-x86_64.policy index 0c196092..e5581eed 100644 --- a/c2_store/seccomp_policy/android.hardware.media.c2-default-x86_64.policy +++ b/c2_store/seccomp_policy/android.hardware.media.c2-default-x86_64.policy @@ -63,6 +63,7 @@ uname: 1 memfd_create: 1 ftruncate: 1 ftruncate64: 1 +mkdirat: 1 # Required by AddressSanitizer gettid: 1 diff --git a/c2_store/src/mfx_c2_store.cpp b/c2_store/src/mfx_c2_store.cpp index 0c64af8a..84dc850c 100644 --- a/c2_store/src/mfx_c2_store.cpp +++ b/c2_store/src/mfx_c2_store.cpp @@ -327,7 +327,6 @@ c2_status_t MfxC2ComponentStore::readConfigFile() MfxC2Component::CreateConfig config; config.flags = flags; - config.dump_output = m_xmlParser.dumpOutputEnabled(name.c_str()); config.concurrent_instances = m_xmlParser.getConcurrentInstances(name.c_str()); config.low_power_mode = m_xmlParser.getLowPowerMode(name.c_str()); diff --git a/c2_utils/include/mfx_c2_defs.h b/c2_utils/include/mfx_c2_defs.h index 48809dad..857b7ab5 100755 --- a/c2_utils/include/mfx_c2_defs.h +++ b/c2_utils/include/mfx_c2_defs.h @@ -34,8 +34,20 @@ #define MFX_C2_CONFIG_XML_FILE_NAME "media_codecs_intel_c2_video.xml" #define MFX_C2_CONFIG_XML_FILE_PATH "/vendor/etc" -#define MFX_C2_DUMP_DIR "/data/local/tmp" -#define MFX_C2_DUMP_OUTPUT_SUB_DIR "c2-output" +#define MFX_C2_DUMP_DIR "/data/local/traces" +#define MFX_C2_DUMP_DECODER_SUB_DIR "c2-intel-decoder" +#define MFX_C2_DUMP_ENCODER_SUB_DIR "c2-intel-encoder" +#define MFX_C2_DUMP_OUTPUT_SUB_DIR "output" +#define MFX_C2_DUMP_INPUT_SUB_DIR "input" + +// dump when dump frames number > 0 +#define DECODER_DUMP_OUTPUT_KEY "c2.decoder.dump.output.number" +// dump when property set to true +#define DECODER_DUMP_INPUT_KEY "c2.decoder.dump.input" +// dump when property set to true +#define ENCODER_DUMP_OUTPUT_KEY "c2.encoder.dump.output" +// dump when dump frames number > 0 +#define ENCODER_DUMP_INPUT_KEY "c2.encoder.dump.input.number" const c2_nsecs_t MFX_SECOND_NS = 1000000000; // 1e9 diff --git a/c2_utils/include/mfx_c2_utils.h b/c2_utils/include/mfx_c2_utils.h index 4006a2c5..cde6a964 100755 --- a/c2_utils/include/mfx_c2_utils.h +++ b/c2_utils/include/mfx_c2_utils.h @@ -187,9 +187,18 @@ class BinaryWriter stream_.write((const char*)data, length); } + bool IsOpen() + { + return stream_.is_open(); + } + + void Close() + { + stream_.close(); + } + private: std::ofstream stream_; - std::mutex m_mutex; }; // Writes YUV format frame to file.It useful for debug. diff --git a/c2_utils/include/mfx_c2_xml_parser.h b/c2_utils/include/mfx_c2_xml_parser.h index dd18cdbd..ae8675c6 100755 --- a/c2_utils/include/mfx_c2_xml_parser.h +++ b/c2_utils/include/mfx_c2_xml_parser.h @@ -50,7 +50,6 @@ class MfxXmlParser C2Component::kind_t getKind(const char *name); C2String getMediaType(const char *name); uint32_t getConcurrentInstances(const char *name); - bool dumpOutputEnabled(const char *name); bool getLowPowerMode(const char *name); private: @@ -61,7 +60,6 @@ class MfxXmlParser bool isEncoder; // whether this codec is an encoder or a decoder size_t order; // order of appearance in the file (starting from 0) std::map typeMap; // map of types supported by this codec - bool dump_output{false}; uint32_t concurrentInstance{0}; bool lowPowerMode{false}; }; diff --git a/c2_utils/src/mfx_c2_utils.cpp b/c2_utils/src/mfx_c2_utils.cpp index 54b66eac..a352e2e8 100755 --- a/c2_utils/src/mfx_c2_utils.cpp +++ b/c2_utils/src/mfx_c2_utils.cpp @@ -689,8 +689,6 @@ BinaryWriter::BinaryWriter(const std::string& dir, std::stringstream full_name; full_name << dir << "/"; - std::lock_guard lock(m_mutex); - for(const std::string& sub_dir : sub_dirs) { full_name << sub_dir; @@ -883,4 +881,4 @@ void ParseGop( if (iInterval) { iInterval = iInt; } -} \ No newline at end of file +} diff --git a/c2_utils/src/mfx_c2_xml_parser.cpp b/c2_utils/src/mfx_c2_xml_parser.cpp index 18a14342..93304f8f 100755 --- a/c2_utils/src/mfx_c2_xml_parser.cpp +++ b/c2_utils/src/mfx_c2_xml_parser.cpp @@ -94,18 +94,6 @@ uint32_t MfxXmlParser::getConcurrentInstances(const char *name) { return codec->second.concurrentInstance; } -bool MfxXmlParser::dumpOutputEnabled(const char *name) { - - MFX_DEBUG_TRACE_FUNC; - - auto codec = m_codecMap.find(name); - if (codec == m_codecMap.end()) { - MFX_DEBUG_TRACE_STREAM("codec " << name << "wasn't found"); - return false; - } - return codec->second.dump_output; -} - bool MfxXmlParser::getLowPowerMode(const char *name) { MFX_DEBUG_TRACE_FUNC; @@ -190,20 +178,12 @@ c2_status_t MfxXmlParser::addLimits(const char **attrs) { MFX_DEBUG_TRACE_MSG("concurrent-instances is null"); return C2_BAD_VALUE; } - } else if (strcmp(attrs[i], "dumpOutput") == 0) { - if (strcmp(attrs[++i], "value") == 0) { - m_currentCodec->second.dump_output = parseBoolean(attrs[++i]); - MFX_DEBUG_TRACE_PRINTF("m_currentCodec->second.dump_output = %d", m_currentCodec->second.dump_output); - } else { - MFX_DEBUG_TRACE_MSG("dumpOutput is null"); - return C2_BAD_VALUE; - } - } else if (strcmp(attrs[i], "lowPowerMode") == 0) { + } else if (strcmp(attrs[i], "low-power-mode") == 0) { if (strcmp(attrs[++i], "value") == 0) { m_currentCodec->second.lowPowerMode = parseBoolean(attrs[++i]); MFX_DEBUG_TRACE_PRINTF("m_currentCodec->second.lowPowerMode = %d ", m_currentCodec->second.lowPowerMode); } else { - MFX_DEBUG_TRACE_MSG("lowPowerMode is null"); + MFX_DEBUG_TRACE_MSG("low-power-mode is null"); return C2_BAD_VALUE; } } From 9b2500377cdc1c4742e931737eb25dec63533a7e Mon Sep 17 00:00:00 2001 From: Nana Zhang Date: Wed, 23 Oct 2024 06:10:11 +0000 Subject: [PATCH 12/14] Fix timestamp precision loss in onevpl In widevine L3 stream play test, the timestamps between Load and Decode have gaps. Tracked-On: OAM-124689 Signed-off-by: Nana Zhang (cherry picked from commit 5cb9ea7995017b547db0259158bc8b9162906b00) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_components/src/mfx_c2_decoder_component.cpp | 7 +++++-- c2_utils/include/mfx_c2_utils.h | 14 +++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index 2eaf0766..0ad2f3a1 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -2550,7 +2550,7 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn } } - decltype(C2WorkOrdinalStruct::timestamp) ready_timestamp{mfx_surface->Data.TimeStamp}; + uint64_t ready_timestamp = mfx_surface->Data.TimeStamp; std::unique_ptr work; std::unique_ptr read_view; @@ -2559,7 +2559,10 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn std::lock_guard lock(m_pendingWorksMutex); auto it = find_if(m_pendingWorks.begin(), m_pendingWorks.end(), [ready_timestamp] (const auto &item) { - return item.second->input.ordinal.timestamp == ready_timestamp; + // In some cases, operations in oneVPL may result in timestamp gaps. + // To ensure that we correctly identify the work, we replicate the same operations as performed in oneVPL. + return item.second->input.ordinal.timestamp.peeku() == ready_timestamp || + GetMfxTimeStamp(GetUmcTimeStamp(item.second->input.ordinal.timestamp.peeku())) == ready_timestamp; }); if (it != m_pendingWorks.end()) { diff --git a/c2_utils/include/mfx_c2_utils.h b/c2_utils/include/mfx_c2_utils.h index cde6a964..dc9c0e43 100755 --- a/c2_utils/include/mfx_c2_utils.h +++ b/c2_utils/include/mfx_c2_utils.h @@ -28,9 +28,21 @@ c2_status_t MfxStatusToC2(mfxStatus mfx_status); +static const mfxU32 MFX_TIME_STAMP_FREQUENCY = 90000; + +inline mfxF64 GetUmcTimeStamp(mfxU64 ts) +{ + return ts / (mfxF64)MFX_TIME_STAMP_FREQUENCY; +} + +inline mfxU64 GetMfxTimeStamp(mfxF64 ts) +{ + return (mfxU64)(ts * MFX_TIME_STAMP_FREQUENCY + .5); +} + inline mfxU64 TimestampC2ToMfx(uint64_t timestamp) { - return timestamp * 90000 / MFX_SECOND_NS; + return timestamp * MFX_TIME_STAMP_FREQUENCY / MFX_SECOND_NS; } c2_status_t GetC2ConstGraphicBlock( From 449ab47772b9a4efe911856364992d5b5ccd7aae Mon Sep 17 00:00:00 2001 From: Lina Sun Date: Thu, 7 Nov 2024 07:08:13 +0000 Subject: [PATCH 13/14] [c2][encoder] Fix AV1 encoder issue Fix AV1 encode issue of "Encoder configure failed" and test be always waiting and can not run to end when running ffmpeg. "Encoder configure failed" is because in mfx_set_RateControlMethod function AV1 encoder case in not handled. Test always wait and can't run to end is because GopRefDist is not set when initializing AV1 encoder, default value of 8 from vpl is used, which caused mediasdk_c2 can't send work done notification to framework codec, so framework codec can't queue more works after queuing initial 4 works. Besides, use PROFILE_AV1_0 & LEVEL_AV1_5_3 as default AV1 encoder profile & level instead of PROFILE_AV1_0 & LEVEL_AV1_7_3, as the latter can not work. Tracked-On: OAM-124081 Signed-off-by: Lina Sun (cherry picked from commit d48d495bd7846a78719ce9b633bc4689ff84e834) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- c2_components/src/mfx_c2_encoder_component.cpp | 4 ++-- c2_utils/src/mfx_defaults.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/c2_components/src/mfx_c2_encoder_component.cpp b/c2_components/src/mfx_c2_encoder_component.cpp index e62e834b..86e9547b 100755 --- a/c2_components/src/mfx_c2_encoder_component.cpp +++ b/c2_components/src/mfx_c2_encoder_component.cpp @@ -83,7 +83,7 @@ C2R MfxC2EncoderComponent::AV1_ProfileLevelSetter(bool mayBlock, C2Pmfx.TargetKbps = 3000; break; + case MFX_CODEC_AV1: + params->mfx.TargetKbps = 3000; + break; default: MFX_DEBUG_TRACE_MSG("Unsupported Codec ID"); res = MFX_ERR_INVALID_VIDEO_PARAM; @@ -213,6 +216,21 @@ mfxStatus mfx_set_defaults_mfxVideoParam_enc(mfxVideoParam* params) params->mfx.NumRefFrame = 1; params->mfx.LowPower = MFX_CODINGOPTION_ON; break; + case MFX_CODEC_AV1: + res = mfx_set_RateControlMethod(MFX_RATECONTROL_CBR, params); + // If GopRefDist is not set, during Encoder Initialization, default + // value of 8 will be read from onevpl and used, which will cause problem. + // In framework during codec start, 4 works are queued to work queue, then + // codec will wait for work done notification to queue more works, while + // in mediasdk_c2, when handling the 4 works from framework, if GopRefDist + // is 8, the first 4 works will wait for future works to notify framework + // work done, so in framework codec will always be waiting for work done + // notification from mediasdk_c2, and mediasdk_c2 will always be waiting for + // more works from framework. + params->mfx.GopRefDist = 1; + params->mfx.GopPicSize = 16; + params->mfx.NumRefFrame = 1; + break; default: break; }; From dd00ed4b428a9f2fbce0bce5bac90565b25cb751 Mon Sep 17 00:00:00 2001 From: Weifeng Liu Date: Thu, 17 Oct 2024 09:53:01 +0000 Subject: [PATCH 14/14] Enforce linear buffer for decoding in the case of hybrid-GPU In hybrid GPU case, video decoder could be iGPU and the coded images would be consumed by dGPU. Unfortunately, it's likely that we can hardly find a tiling format supported by both of them. To achieve best compatibility and make our life better, simply use linear buffers for decoded images. By setting CPU_READ and CPU_WRITE flags, we force OneVPL to allocate internal buffers and blit decoded content to external buffers. In this way we can work around hardware limitation that DG2 cannot decode to linear buffers. We will detect the GPU group type and decide whether to use linear buffers or not. Tracked-On: OAM-126399 Signed-off-by: Weifeng Liu (cherry picked from commit bfcd81e5b90f2d69fd0b9bd6bdb03533ff569b18) Tracked-On: OAM-128364 Signed-off-by: Lina Sun --- .../include/mfx_c2_decoder_component.h | 2 + .../src/mfx_c2_decoder_component.cpp | 16 + c2_utils/Android.bp | 1 + c2_utils/include/mfx_intel_device.h | 54 ++ c2_utils/src/mfx_c2_utils.cpp | 4 + c2_utils/src/mfx_intel_device.cpp | 743 ++++++++++++++++++ 6 files changed, 820 insertions(+) create mode 100644 c2_utils/include/mfx_intel_device.h create mode 100644 c2_utils/src/mfx_intel_device.cpp diff --git a/c2_components/include/mfx_c2_decoder_component.h b/c2_components/include/mfx_c2_decoder_component.h index 006b725a..c8689ad3 100755 --- a/c2_components/include/mfx_c2_decoder_component.h +++ b/c2_components/include/mfx_c2_decoder_component.h @@ -28,6 +28,7 @@ #include "mfx_c2_bitstream_in.h" #include "mfx_frame_pool_allocator.h" #include "mfx_gralloc_instance.h" +#include "mfx_intel_device.h" #include "mfx_c2_setters.h" #include "mfx_c2_utils.h" #include @@ -264,6 +265,7 @@ class MfxC2DecoderComponent : public MfxC2Component // dump output multiple times, the first dumped file named xxx_0.yuv, // second dumped file named xxx_1.yuv ... uint32_t m_file_num = 0; + bool m_needCpuAccess = false; /* -----------------------C2Parameters--------------------------- */ std::shared_ptr m_name; diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index 0ad2f3a1..19e186fe 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -21,6 +21,7 @@ #include "mfx_c2_decoder_component.h" #include "mfx_debug.h" +#include "mfx_intel_device.h" #include "mfx_msdk_debug.h" #include "mfx_c2_debug.h" #include "mfx_c2_components_registry.h" @@ -178,6 +179,12 @@ MfxC2DecoderComponent::MfxC2DecoderComponent(const C2String name, const CreateCo MFX_DEBUG_TRACE_FUNC; const unsigned int SINGLE_STREAM_ID = 0u; + // We need to enable CPU access to the buffers of decoded images when + // 1. decode with DG2 and display with RPL-p iGPU; + // 2. decode with RPL-p iGPU and display with DG2. + // The displaying GPU will appear as virtio-GPU. + m_needCpuAccess = enforceLinearBuffer(); + addParameter( DefineParam(m_kind, C2_PARAMKEY_COMPONENT_KIND) .withConstValue(new C2ComponentKindSetting(C2Component::KIND_DECODER)) @@ -226,6 +233,11 @@ MfxC2DecoderComponent::MfxC2DecoderComponent(const C2String name, const CreateCo .build()); m_consumerUsage = C2AndroidMemoryUsage::FromGrallocUsage(kDefaultConsumerUsage).expected; + // We need these flags in the case of hybrid GPU. + if (m_needCpuAccess) { + m_consumerUsage |= C2AndroidMemoryUsage::CPU_READ; + m_consumerUsage |= C2AndroidMemoryUsage::CPU_WRITE; + } addParameter( DefineParam(m_outputUsage, C2_PARAMKEY_OUTPUT_STREAM_USAGE) .withDefault(new C2StreamUsageTuning::output(SINGLE_STREAM_ID, m_consumerUsage)) @@ -1575,6 +1587,10 @@ void MfxC2DecoderComponent::DoUpdateMfxParam(const std::vector ¶ms case kParamIndexUsage: { if (C2StreamUsageTuning::output::PARAM_TYPE == param->index()) { m_consumerUsage = m_outputUsage->value; + if (m_needCpuAccess) { + m_consumerUsage |= C2AndroidMemoryUsage::CPU_READ; + m_consumerUsage |= C2AndroidMemoryUsage::CPU_WRITE; + } // Set memory type according to consumer usage sent from framework m_mfxVideoParams.IOPattern = (m_consumerUsage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)) ? MFX_IOPATTERN_OUT_SYSTEM_MEMORY : MFX_IOPATTERN_OUT_VIDEO_MEMORY; diff --git a/c2_utils/Android.bp b/c2_utils/Android.bp index ac1a17ca..1f98be8b 100644 --- a/c2_utils/Android.bp +++ b/c2_utils/Android.bp @@ -27,6 +27,7 @@ cc_library_static { ], shared_libs: [ + "libdrm", "liblog", "libgralloctypes", "libstagefright_foundation", diff --git a/c2_utils/include/mfx_intel_device.h b/c2_utils/include/mfx_intel_device.h new file mode 100644 index 00000000..21a360ea --- /dev/null +++ b/c2_utils/include/mfx_intel_device.h @@ -0,0 +1,54 @@ +// Copyright (c) 2024 Intel Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +enum { + GPU_GRP_TYPE_INTEL_IGPU_IDX = 0, + GPU_GRP_TYPE_INTEL_DGPU_IDX = 1, + GPU_GRP_TYPE_VIRTIO_GPU_BLOB_IDX = 2, + // virtio-GPU with allow-p2p feature, implying its display is backed by dGPU + GPU_GRP_TYPE_VIRTIO_GPU_BLOB_P2P_IDX = 3, + GPU_GRP_TYPE_VIRTIO_GPU_NO_BLOB_IDX = 4, + GPU_GRP_TYPE_VIRTIO_GPU_IVSHMEM_IDX = 5, + GPU_GRP_TYPE_NR, +}; + +#define GPU_GRP_TYPE_HAS_INTEL_IGPU_BIT (1ull << GPU_GRP_TYPE_INTEL_IGPU_IDX) +#define GPU_GRP_TYPE_HAS_INTEL_DGPU_BIT (1ull << GPU_GRP_TYPE_INTEL_DGPU_IDX) +#define GPU_GRP_TYPE_HAS_VIRTIO_GPU_BLOB_BIT (1ull << GPU_GRP_TYPE_VIRTIO_GPU_BLOB_IDX) +#define GPU_GRP_TYPE_HAS_VIRTIO_GPU_BLOB_P2P_BIT (1ull << GPU_GRP_TYPE_VIRTIO_GPU_BLOB_P2P_IDX) +#define GPU_GRP_TYPE_HAS_VIRTIO_GPU_NO_BLOB_BIT (1ull << GPU_GRP_TYPE_VIRTIO_GPU_NO_BLOB_IDX) +#define GPU_GRP_TYPE_HAS_VIRTIO_GPU_IVSHMEM_BIT (1ull << GPU_GRP_TYPE_VIRTIO_GPU_IVSHMEM_IDX) + +#define DRIVER_DEVICE_FEATURE_I915_DGPU (1ull << 1) +#define DRIVER_DEVICE_FEATURE_VIRGL_RESOURCE_BLOB (1ull << 2) +#define DRIVER_DEVICE_FEATURE_VIRGL_QUERY_DEV (1ull << 3) +#define DRIVER_DEVICE_FEATURE_VIRGL_ALLOW_P2P (1ull << 4) + +bool isIntelDg2(int fd); +bool isVirtioGpuAllowP2p(int virtgpu_fd); +bool isVirtioGpuPciDevice(int virtgpu_fd); +bool isVirtioGpuWithBlob(int virtgpu_fd); + +uint64_t getGpuGroupType(); +bool enforceLinearBuffer(); diff --git a/c2_utils/src/mfx_c2_utils.cpp b/c2_utils/src/mfx_c2_utils.cpp index a352e2e8..4e19ce50 100755 --- a/c2_utils/src/mfx_c2_utils.cpp +++ b/c2_utils/src/mfx_c2_utils.cpp @@ -22,6 +22,7 @@ #include "mfx_c2_utils.h" #include "mfx_debug.h" #include "mfx_c2_debug.h" +#include "mfx_intel_device.h" #include #include @@ -573,6 +574,9 @@ int MfxFourCCToGralloc(mfxU32 fourcc, bool using_video_memory) MFX_DEBUG_TRACE_FUNC; MFX_DEBUG_TRACE_U32(fourcc); + if (enforceLinearBuffer()) { + using_video_memory = false; + } switch (fourcc) { case MFX_FOURCC_NV12: diff --git a/c2_utils/src/mfx_intel_device.cpp b/c2_utils/src/mfx_intel_device.cpp new file mode 100644 index 00000000..1aaf4adc --- /dev/null +++ b/c2_utils/src/mfx_intel_device.cpp @@ -0,0 +1,743 @@ +// Copyright (c) 2024 Intel Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mfx_intel_device.h" + +#define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A))) + +#define GEN_VERSION_X10(dev) ((dev)->graphics_version * 10 + (dev)->sub_version) + +#define VIRTGPU_PARAM_QUERY_DEV 11 /* Query the virtio device name. */ +#define VIRTGPU_PARAM_ALLOW_P2P 12 + +static int gem_param(int fd, int name) +{ + int v = -1; /* No param uses (yet) the sign bit, reserve it for errors */ + + struct drm_i915_getparam gp = {.param = name, .value = &v }; + if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) + return -1; + + return v; +} + +enum eMFXVAType +{ + MFX_HW_NO = 0, + MFX_HW_D3D9 = 1, + MFX_HW_D3D11 = 2, + MFX_HW_VAAPI = 4,// Linux VA-API +}; + +enum eMFXHWType +{ + MFX_HW_UNKNOWN = 0, + MFX_HW_SNB = 0x300000, + + MFX_HW_IVB = 0x400000, + + MFX_HW_HSW = 0x500000, + MFX_HW_HSW_ULT = 0x500001, + + MFX_HW_VLV = 0x600000, + + MFX_HW_BDW = 0x700000, + + MFX_HW_CHT = 0x800000, + + MFX_HW_SCL = 0x900000, + + MFX_HW_APL = 0x1000000, + + MFX_HW_KBL = 0x1100000, + MFX_HW_GLK = MFX_HW_KBL + 1, + MFX_HW_CFL = MFX_HW_KBL + 2, + + MFX_HW_CNL = 0x1200000, + + MFX_HW_ICL = 0x1400000, + MFX_HW_ICL_LP = MFX_HW_ICL + 1, + MFX_HW_JSL = 0x1500001, + MFX_HW_EHL = 0x1500002, + + MFX_HW_TGL_LP = 0x1600000, + MFX_HW_RKL = MFX_HW_TGL_LP + 2, + MFX_HW_DG1 = MFX_HW_TGL_LP + 3, + MFX_HW_ADL_S = MFX_HW_TGL_LP + 4, + MFX_HW_ADL_P = MFX_HW_TGL_LP + 5, + MFX_HW_ADL_N = MFX_HW_TGL_LP + 6, + MFX_HW_XE_HP_SDV = MFX_HW_TGL_LP + 7, + MFX_HW_DG2 = MFX_HW_TGL_LP + 8, + + MFX_HW_PVC = MFX_HW_XE_HP_SDV + 2, + + MFX_HW_MTL = 0x1700000, + MFX_HW_ARL = MFX_HW_MTL + 1, + MFX_HW_BMG = MFX_HW_MTL + 2, + MFX_HW_LNL = MFX_HW_MTL + 3, + +}; + +enum eMFXGTConfig +{ + MFX_GT_UNKNOWN = 0, + MFX_GT1 = 1, + MFX_GT2 = 2, + MFX_GT3 = 3, + MFX_GT4 = 4 +}; + +typedef struct { + int device_id; + eMFXHWType platform; + eMFXGTConfig config; +} mfx_device_item; + +// list of legal dev ID for Intel's graphics + const mfx_device_item listLegalDevIDs[] = { + /*IVB*/ + { 0x0156, MFX_HW_IVB, MFX_GT1 }, /* GT1 mobile */ + { 0x0166, MFX_HW_IVB, MFX_GT2 }, /* GT2 mobile */ + { 0x0152, MFX_HW_IVB, MFX_GT1 }, /* GT1 desktop */ + { 0x0162, MFX_HW_IVB, MFX_GT2 }, /* GT2 desktop */ + { 0x015a, MFX_HW_IVB, MFX_GT1 }, /* GT1 server */ + { 0x016a, MFX_HW_IVB, MFX_GT2 }, /* GT2 server */ + /*HSW*/ + { 0x0402, MFX_HW_HSW, MFX_GT1 }, /* GT1 desktop */ + { 0x0412, MFX_HW_HSW, MFX_GT2 }, /* GT2 desktop */ + { 0x0422, MFX_HW_HSW, MFX_GT2 }, /* GT2 desktop */ + { 0x041e, MFX_HW_HSW, MFX_GT2 }, /* Core i3-4130 */ + { 0x040a, MFX_HW_HSW, MFX_GT1 }, /* GT1 server */ + { 0x041a, MFX_HW_HSW, MFX_GT2 }, /* GT2 server */ + { 0x042a, MFX_HW_HSW, MFX_GT2 }, /* GT2 server */ + { 0x0406, MFX_HW_HSW, MFX_GT1 }, /* GT1 mobile */ + { 0x0416, MFX_HW_HSW, MFX_GT2 }, /* GT2 mobile */ + { 0x0426, MFX_HW_HSW, MFX_GT2 }, /* GT2 mobile */ + { 0x0C02, MFX_HW_HSW, MFX_GT1 }, /* SDV GT1 desktop */ + { 0x0C12, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 desktop */ + { 0x0C22, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 desktop */ + { 0x0C0A, MFX_HW_HSW, MFX_GT1 }, /* SDV GT1 server */ + { 0x0C1A, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 server */ + { 0x0C2A, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 server */ + { 0x0C06, MFX_HW_HSW, MFX_GT1 }, /* SDV GT1 mobile */ + { 0x0C16, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 mobile */ + { 0x0C26, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 mobile */ + { 0x0A02, MFX_HW_HSW, MFX_GT1 }, /* ULT GT1 desktop */ + { 0x0A12, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 desktop */ + { 0x0A22, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 desktop */ + { 0x0A0A, MFX_HW_HSW, MFX_GT1 }, /* ULT GT1 server */ + { 0x0A1A, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 server */ + { 0x0A2A, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 server */ + { 0x0A06, MFX_HW_HSW, MFX_GT1 }, /* ULT GT1 mobile */ + { 0x0A16, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 mobile */ + { 0x0A26, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 mobile */ + { 0x0D02, MFX_HW_HSW, MFX_GT1 }, /* CRW GT1 desktop */ + { 0x0D12, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 desktop */ + { 0x0D22, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 desktop */ + { 0x0D0A, MFX_HW_HSW, MFX_GT1 }, /* CRW GT1 server */ + { 0x0D1A, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 server */ + { 0x0D2A, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 server */ + { 0x0D06, MFX_HW_HSW, MFX_GT1 }, /* CRW GT1 mobile */ + { 0x0D16, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 mobile */ + { 0x0D26, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 mobile */ + { 0x040B, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_B_GT1 *//* Reserved */ + { 0x041B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_B_GT2*/ + { 0x042B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_B_GT3*/ + { 0x040E, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_E_GT1*//* Reserved */ + { 0x041E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_E_GT2*/ + { 0x042E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_E_GT3*/ + + { 0x0C0B, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_SDV_B_GT1*/ /* Reserved */ + { 0x0C1B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_SDV_B_GT2*/ + { 0x0C2B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_SDV_B_GT3*/ + { 0x0C0E, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_SDV_B_GT1*//* Reserved */ + { 0x0C1E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_SDV_B_GT2*/ + { 0x0C2E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_SDV_B_GT3*/ + + { 0x0A0B, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_ULT_B_GT1*/ /* Reserved */ + { 0x0A1B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_ULT_B_GT2*/ + { 0x0A2B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_ULT_B_GT3*/ + { 0x0A0E, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_ULT_E_GT1*/ /* Reserved */ + { 0x0A1E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_ULT_E_GT2*/ + { 0x0A2E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_ULT_E_GT3*/ + + { 0x0D0B, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_CRW_B_GT1*/ /* Reserved */ + { 0x0D1B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_CRW_B_GT2*/ + { 0x0D2B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_CRW_B_GT3*/ + { 0x0D0E, MFX_HW_HSW, MFX_GT1 }, /*HASWELL_CRW_E_GT1*/ /* Reserved */ + { 0x0D1E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_CRW_E_GT2*/ + { 0x0D2E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_CRW_E_GT3*/ + + /* VLV */ + { 0x0f30, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */ + { 0x0f31, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */ + { 0x0f32, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */ + { 0x0f33, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */ + { 0x0157, MFX_HW_VLV, MFX_GT1 }, + { 0x0155, MFX_HW_VLV, MFX_GT1 }, + + /* BDW */ + /*GT3: */ + { 0x162D, MFX_HW_BDW, MFX_GT3 }, + { 0x162A, MFX_HW_BDW, MFX_GT3 }, + /*GT2: */ + { 0x161D, MFX_HW_BDW, MFX_GT2 }, + { 0x161A, MFX_HW_BDW, MFX_GT2 }, + /* GT1: */ + { 0x160D, MFX_HW_BDW, MFX_GT1 }, + { 0x160A, MFX_HW_BDW, MFX_GT1 }, + /* BDW-ULT */ + /* (16x2 - ULT, 16x6 - ULT, 16xB - Iris, 16xE - ULX) */ + /*GT3: */ + { 0x162E, MFX_HW_BDW, MFX_GT3 }, + { 0x162B, MFX_HW_BDW, MFX_GT3 }, + { 0x1626, MFX_HW_BDW, MFX_GT3 }, + { 0x1622, MFX_HW_BDW, MFX_GT3 }, + { 0x1636, MFX_HW_BDW, MFX_GT3 }, /* ULT */ + { 0x163B, MFX_HW_BDW, MFX_GT3 }, /* Iris */ + { 0x163E, MFX_HW_BDW, MFX_GT3 }, /* ULX */ + { 0x1632, MFX_HW_BDW, MFX_GT3 }, /* ULT */ + { 0x163A, MFX_HW_BDW, MFX_GT3 }, /* Server */ + { 0x163D, MFX_HW_BDW, MFX_GT3 }, /* Workstation */ + + /* GT2: */ + { 0x161E, MFX_HW_BDW, MFX_GT2 }, + { 0x161B, MFX_HW_BDW, MFX_GT2 }, + { 0x1616, MFX_HW_BDW, MFX_GT2 }, + { 0x1612, MFX_HW_BDW, MFX_GT2 }, + /* GT1: */ + { 0x160E, MFX_HW_BDW, MFX_GT1 }, + { 0x160B, MFX_HW_BDW, MFX_GT1 }, + { 0x1606, MFX_HW_BDW, MFX_GT1 }, + { 0x1602, MFX_HW_BDW, MFX_GT1 }, + + /* CHT */ + { 0x22b0, MFX_HW_CHT, MFX_GT1 }, + { 0x22b1, MFX_HW_CHT, MFX_GT1 }, + { 0x22b2, MFX_HW_CHT, MFX_GT1 }, + { 0x22b3, MFX_HW_CHT, MFX_GT1 }, + + /* SCL */ + /* GT1F */ + { 0x1902, MFX_HW_SCL, MFX_GT1 }, // DT, 2x1F, 510 + { 0x1906, MFX_HW_SCL, MFX_GT1 }, // U-ULT, 2x1F, 510 + { 0x190A, MFX_HW_SCL, MFX_GT1 }, // Server, 4x1F + { 0x190B, MFX_HW_SCL, MFX_GT1 }, + { 0x190E, MFX_HW_SCL, MFX_GT1 }, // Y-ULX 2x1F + /*GT1.5*/ + { 0x1913, MFX_HW_SCL, MFX_GT1 }, // U-ULT, 2x1.5 + { 0x1915, MFX_HW_SCL, MFX_GT1 }, // Y-ULX, 2x1.5 + { 0x1917, MFX_HW_SCL, MFX_GT1 }, // DT, 2x1.5 + /* GT2 */ + { 0x1912, MFX_HW_SCL, MFX_GT2 }, // DT, 2x2, 530 + { 0x1916, MFX_HW_SCL, MFX_GT2 }, // U-ULD 2x2, 520 + { 0x191A, MFX_HW_SCL, MFX_GT2 }, // 2x2,4x2, Server + { 0x191B, MFX_HW_SCL, MFX_GT2 }, // DT, 2x2, 530 + { 0x191D, MFX_HW_SCL, MFX_GT2 }, // 4x2, WKS, P530 + { 0x191E, MFX_HW_SCL, MFX_GT2 }, // Y-ULX, 2x2, P510,515 + { 0x1921, MFX_HW_SCL, MFX_GT2 }, // U-ULT, 2x2F, 540 + /* GT3 */ + { 0x1923, MFX_HW_SCL, MFX_GT3 }, // U-ULT, 2x3, 535 + { 0x1926, MFX_HW_SCL, MFX_GT3 }, // U-ULT, 2x3, 540 (15W) + { 0x1927, MFX_HW_SCL, MFX_GT3 }, // U-ULT, 2x3e, 550 (28W) + { 0x192A, MFX_HW_SCL, MFX_GT3 }, // Server, 2x3 + { 0x192B, MFX_HW_SCL, MFX_GT3 }, // Halo 3e + { 0x192D, MFX_HW_SCL, MFX_GT3 }, + /* GT4e*/ + { 0x1932, MFX_HW_SCL, MFX_GT4 }, // DT + { 0x193A, MFX_HW_SCL, MFX_GT4 }, // SRV + { 0x193B, MFX_HW_SCL, MFX_GT4 }, // Halo + { 0x193D, MFX_HW_SCL, MFX_GT4 }, // WKS + + /* APL */ + { 0x0A84, MFX_HW_APL, MFX_GT1 }, + { 0x0A85, MFX_HW_APL, MFX_GT1 }, + { 0x0A86, MFX_HW_APL, MFX_GT1 }, + { 0x0A87, MFX_HW_APL, MFX_GT1 }, + { 0x1A84, MFX_HW_APL, MFX_GT1 }, + { 0x1A85, MFX_HW_APL, MFX_GT1 }, + { 0x5A84, MFX_HW_APL, MFX_GT1 }, + { 0x5A85, MFX_HW_APL, MFX_GT1 }, + + /* KBL */ + { 0x5902, MFX_HW_KBL, MFX_GT1 }, // DT GT1 + { 0x5906, MFX_HW_KBL, MFX_GT1 }, // ULT GT1 + { 0x5908, MFX_HW_KBL, MFX_GT1 }, // HALO GT1F + { 0x590A, MFX_HW_KBL, MFX_GT1 }, // SERV GT1 + { 0x590B, MFX_HW_KBL, MFX_GT1 }, // HALO GT1 + { 0x590E, MFX_HW_KBL, MFX_GT1 }, // ULX GT1 + { 0x5912, MFX_HW_KBL, MFX_GT2 }, // DT GT2 + { 0x5913, MFX_HW_KBL, MFX_GT1 }, // ULT GT1 5 + { 0x5915, MFX_HW_KBL, MFX_GT1 }, // ULX GT1 5 + { 0x5916, MFX_HW_KBL, MFX_GT2 }, // ULT GT2 + { 0x5917, MFX_HW_KBL, MFX_GT2 }, // ULT GT2 R + { 0x591A, MFX_HW_KBL, MFX_GT2 }, // SERV GT2 + { 0x591B, MFX_HW_KBL, MFX_GT2 }, // HALO GT2 + { 0x591C, MFX_HW_KBL, MFX_GT2 }, // ULX GT2 + { 0x591D, MFX_HW_KBL, MFX_GT2 }, // WRK GT2 + { 0x591E, MFX_HW_KBL, MFX_GT2 }, // ULX GT2 + { 0x5921, MFX_HW_KBL, MFX_GT2 }, // ULT GT2F + { 0x5923, MFX_HW_KBL, MFX_GT3 }, // ULT GT3 + { 0x5926, MFX_HW_KBL, MFX_GT3 }, // ULT GT3 15W + { 0x5927, MFX_HW_KBL, MFX_GT3 }, // ULT GT3 28W + { 0x592A, MFX_HW_KBL, MFX_GT3 }, // SERV GT3 + { 0x592B, MFX_HW_KBL, MFX_GT3 }, // HALO GT3 + { 0x5932, MFX_HW_KBL, MFX_GT4 }, // DT GT4 + { 0x593A, MFX_HW_KBL, MFX_GT4 }, // SERV GT4 + { 0x593B, MFX_HW_KBL, MFX_GT4 }, // HALO GT4 + { 0x593D, MFX_HW_KBL, MFX_GT4 }, // WRK GT4 + { 0x87C0, MFX_HW_KBL, MFX_GT2 }, // ULX GT2 + + /* GLK */ + { 0x3184, MFX_HW_GLK, MFX_GT1 }, + { 0x3185, MFX_HW_GLK, MFX_GT1 }, + + /* CFL */ + { 0x3E90, MFX_HW_CFL, MFX_GT1 }, + { 0x3E91, MFX_HW_CFL, MFX_GT2 }, + { 0x3E92, MFX_HW_CFL, MFX_GT2 }, + { 0x3E93, MFX_HW_CFL, MFX_GT1 }, + { 0x3E94, MFX_HW_CFL, MFX_GT2 }, + { 0x3E96, MFX_HW_CFL, MFX_GT2 }, + { 0x3E98, MFX_HW_CFL, MFX_GT2 }, + { 0x3E99, MFX_HW_CFL, MFX_GT1 }, + { 0x3E9A, MFX_HW_CFL, MFX_GT2 }, + { 0x3E9C, MFX_HW_CFL, MFX_GT1 }, + { 0x3E9B, MFX_HW_CFL, MFX_GT2 }, + { 0x3EA5, MFX_HW_CFL, MFX_GT3 }, + { 0x3EA6, MFX_HW_CFL, MFX_GT3 }, + { 0x3EA7, MFX_HW_CFL, MFX_GT3 }, + { 0x3EA8, MFX_HW_CFL, MFX_GT3 }, + { 0x3EA9, MFX_HW_CFL, MFX_GT2 }, + { 0x87CA, MFX_HW_CFL, MFX_GT2 }, + + /* WHL */ + { 0x3EA0, MFX_HW_CFL, MFX_GT2 }, + { 0x3EA1, MFX_HW_CFL, MFX_GT1 }, + { 0x3EA2, MFX_HW_CFL, MFX_GT3 }, + { 0x3EA3, MFX_HW_CFL, MFX_GT2 }, + { 0x3EA4, MFX_HW_CFL, MFX_GT1 }, + + + /* CML GT1 */ + { 0x9b21, MFX_HW_CFL, MFX_GT1 }, + { 0x9baa, MFX_HW_CFL, MFX_GT1 }, + { 0x9bab, MFX_HW_CFL, MFX_GT1 }, + { 0x9bac, MFX_HW_CFL, MFX_GT1 }, + { 0x9ba0, MFX_HW_CFL, MFX_GT1 }, + { 0x9ba5, MFX_HW_CFL, MFX_GT1 }, + { 0x9ba8, MFX_HW_CFL, MFX_GT1 }, + { 0x9ba4, MFX_HW_CFL, MFX_GT1 }, + { 0x9ba2, MFX_HW_CFL, MFX_GT1 }, + + /* CML GT2 */ + { 0x9b41, MFX_HW_CFL, MFX_GT2 }, + { 0x9bca, MFX_HW_CFL, MFX_GT2 }, + { 0x9bcb, MFX_HW_CFL, MFX_GT2 }, + { 0x9bcc, MFX_HW_CFL, MFX_GT2 }, + { 0x9bc0, MFX_HW_CFL, MFX_GT2 }, + { 0x9bc5, MFX_HW_CFL, MFX_GT2 }, + { 0x9bc8, MFX_HW_CFL, MFX_GT2 }, + { 0x9bc4, MFX_HW_CFL, MFX_GT2 }, + { 0x9bc2, MFX_HW_CFL, MFX_GT2 }, + { 0x9bc6, MFX_HW_CFL, MFX_GT2 }, + { 0x9be6, MFX_HW_CFL, MFX_GT2 }, + { 0x9bf6, MFX_HW_CFL, MFX_GT2 }, + + + /* CNL */ + { 0x5A51, MFX_HW_CNL, MFX_GT2 }, + { 0x5A52, MFX_HW_CNL, MFX_GT2 }, + { 0x5A5A, MFX_HW_CNL, MFX_GT2 }, + { 0x5A40, MFX_HW_CNL, MFX_GT2 }, + { 0x5A42, MFX_HW_CNL, MFX_GT2 }, + { 0x5A4A, MFX_HW_CNL, MFX_GT2 }, + { 0x5A4C, MFX_HW_CNL, MFX_GT1 }, + { 0x5A50, MFX_HW_CNL, MFX_GT2 }, + { 0x5A54, MFX_HW_CNL, MFX_GT1 }, + { 0x5A59, MFX_HW_CNL, MFX_GT2 }, + { 0x5A5C, MFX_HW_CNL, MFX_GT1 }, + { 0x5A41, MFX_HW_CNL, MFX_GT2 }, + { 0x5A44, MFX_HW_CNL, MFX_GT1 }, + { 0x5A49, MFX_HW_CNL, MFX_GT2 }, + + /* ICL LP */ + { 0xFF05, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A50, MFX_HW_ICL_LP, MFX_GT2 }, + { 0x8A51, MFX_HW_ICL_LP, MFX_GT2 }, + { 0x8A52, MFX_HW_ICL_LP, MFX_GT2 }, + { 0x8A53, MFX_HW_ICL_LP, MFX_GT2 }, + { 0x8A54, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A56, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A57, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A58, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A59, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A5A, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A5B, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A5C, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A5D, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A70, MFX_HW_ICL_LP, MFX_GT1 }, + { 0x8A71, MFX_HW_ICL_LP, MFX_GT1 }, // GT05, but 1 ok in this context + + /* JSL */ + { 0x4E51, MFX_HW_JSL, MFX_GT2 }, + { 0x4E55, MFX_HW_JSL, MFX_GT2 }, + { 0x4E61, MFX_HW_JSL, MFX_GT2 }, + { 0x4E71, MFX_HW_JSL, MFX_GT2 }, + + /* EHL */ + { 0x4500, MFX_HW_EHL, MFX_GT2 }, + { 0x4541, MFX_HW_EHL, MFX_GT2 }, + { 0x4551, MFX_HW_EHL, MFX_GT2 }, + { 0x4555, MFX_HW_EHL, MFX_GT2 }, + { 0x4569, MFX_HW_EHL, MFX_GT2 }, + { 0x4571, MFX_HW_EHL, MFX_GT2 }, + + /* TGL */ + { 0x9A40, MFX_HW_TGL_LP, MFX_GT2 }, + { 0x9A49, MFX_HW_TGL_LP, MFX_GT2 }, + { 0x9A59, MFX_HW_TGL_LP, MFX_GT2 }, + { 0x9A60, MFX_HW_TGL_LP, MFX_GT2 }, + { 0x9A68, MFX_HW_TGL_LP, MFX_GT2 }, + { 0x9A70, MFX_HW_TGL_LP, MFX_GT2 }, + { 0x9A78, MFX_HW_TGL_LP, MFX_GT2 }, + + /* DG1/SG1 */ + { 0x4905, MFX_HW_DG1, MFX_GT2 }, + { 0x4906, MFX_HW_DG1, MFX_GT2 }, + { 0x4907, MFX_HW_DG1, MFX_GT2 }, // SG1 + { 0x4908, MFX_HW_DG1, MFX_GT2 }, + + /* RKL */ + { 0x4C80, MFX_HW_RKL, MFX_GT1 }, // RKL-S + { 0x4C8A, MFX_HW_RKL, MFX_GT1 }, // RKL-S + { 0x4C81, MFX_HW_RKL, MFX_GT1 }, // RKL-S + { 0x4C8B, MFX_HW_RKL, MFX_GT1 }, // RKL-S + { 0x4C90, MFX_HW_RKL, MFX_GT1 }, // RKL-S + { 0x4C9A, MFX_HW_RKL, MFX_GT1 }, // RKL-S + + /* ADL-S */ + { 0x4680, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4681, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4682, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4683, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4688, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x468A, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x468B, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4690, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4691, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4692, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4693, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4698, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + { 0x4699, MFX_HW_ADL_S, MFX_GT1 },//ADL-S + + /* RPL-S */ + { 0xA780, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA781, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA782, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA783, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA784, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA785, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA786, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA787, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA788, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA789, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA78A, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA78B, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA78C, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA78D, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + { 0xA78E, MFX_HW_ADL_S, MFX_GT1 },//RPL-S + + { 0xA7AA, MFX_HW_ADL_S, MFX_GT1 },//RPL + { 0xA7AB, MFX_HW_ADL_S, MFX_GT1 },//RPL + { 0xA7AC, MFX_HW_ADL_S, MFX_GT1 },//RPL + { 0xA7AD, MFX_HW_ADL_S, MFX_GT1 },//RPL + + /* ADL-P */ + { 0x46A0, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46A1, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46A2, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46A3, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46A6, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x4626, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + + { 0x46B0, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46B1, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46B2, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46B3, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46A8, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x4628, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + + { 0x46C0, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46C1, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46C2, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46C3, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x46AA, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + { 0x462A, MFX_HW_ADL_P, MFX_GT2 },//ADL-P + + /* RPL-P */ + { 0xA7A0, MFX_HW_ADL_P, MFX_GT2 }, + { 0xA720, MFX_HW_ADL_P, MFX_GT2 }, + { 0xA7A8, MFX_HW_ADL_P, MFX_GT2 }, + { 0xA7A1, MFX_HW_ADL_P, MFX_GT2 }, + { 0xA721, MFX_HW_ADL_P, MFX_GT2 }, + { 0xA7A9, MFX_HW_ADL_P, MFX_GT2 }, + + /* ADL-N */ + { 0x46D0, MFX_HW_ADL_N, MFX_GT1 },//ADL-N + { 0x46D1, MFX_HW_ADL_N, MFX_GT1 },//ADL-N + { 0x46D2, MFX_HW_ADL_N, MFX_GT1 },//ADL-N + + /* TWL */ + { 0x46D3, MFX_HW_ADL_N, MFX_GT1 },//TWL + { 0x46D4, MFX_HW_ADL_N, MFX_GT1 },//TWL + + /* DG2 */ + { 0x4F80, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F81, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F82, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F83, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F84, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F85, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F86, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F87, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x4F88, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5690, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5691, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5692, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5693, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5694, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5695, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5696, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x5697, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A0, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A1, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A2, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A3, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A4, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A5, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56A6, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56B0, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56B1, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56B2, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56B3, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56C0, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56C1, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56BA, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56BB, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56BC, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56BD, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56BE, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56BF, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56C2, MFX_HW_DG2, MFX_GT4 }, // DG2 + { 0x56AF, MFX_HW_DG2, MFX_GT4 }, // DG2 + + /* PVC */ + { 0x0BD0, MFX_HW_PVC, MFX_GT4 }, + { 0x0BD5, MFX_HW_PVC, MFX_GT4 }, + { 0x0BD6, MFX_HW_PVC, MFX_GT4 }, + { 0x0BD7, MFX_HW_PVC, MFX_GT4 }, + { 0x0BD8, MFX_HW_PVC, MFX_GT4 }, + { 0x0BD9, MFX_HW_PVC, MFX_GT4 }, + { 0x0BDA, MFX_HW_PVC, MFX_GT4 }, + { 0x0BDB, MFX_HW_PVC, MFX_GT4 }, + { 0x0BE0, MFX_HW_PVC, MFX_GT4 }, + { 0x0BE1, MFX_HW_PVC, MFX_GT4 }, + { 0x0BE5, MFX_HW_PVC, MFX_GT4 }, + + + /* MTL */ + { 0x7D40, MFX_HW_MTL, MFX_GT2 }, + { 0x7D50, MFX_HW_MTL, MFX_GT2 }, + { 0x7D55, MFX_HW_MTL, MFX_GT2 }, + { 0x7D57, MFX_HW_MTL, MFX_GT2 }, + { 0x7D60, MFX_HW_MTL, MFX_GT2 }, + { 0x7D70, MFX_HW_MTL, MFX_GT2 }, + { 0x7D75, MFX_HW_MTL, MFX_GT2 }, + { 0x7D79, MFX_HW_MTL, MFX_GT2 }, + { 0x7D76, MFX_HW_MTL, MFX_GT2 }, + { 0x7D66, MFX_HW_MTL, MFX_GT2 }, + { 0x7DD5, MFX_HW_MTL, MFX_GT2 }, + { 0x7DD7, MFX_HW_MTL, MFX_GT2 }, + { 0x7D45, MFX_HW_MTL, MFX_GT2 }, + { 0x7DE0, MFX_HW_MTL, MFX_GT2 }, + + /* ARL S */ + { 0x7D67, MFX_HW_ARL, MFX_GT2 }, + + /* ARL H*/ + { 0x7D51, MFX_HW_ARL, MFX_GT2 }, + { 0x7DD1, MFX_HW_ARL, MFX_GT2 }, + { 0x7D41, MFX_HW_ARL, MFX_GT2 }, + + /* BMG */ + { 0xE202, MFX_HW_BMG, MFX_GT4 }, + { 0xE20B, MFX_HW_BMG, MFX_GT4 }, + { 0xE20C, MFX_HW_BMG, MFX_GT4 }, + { 0xE20D, MFX_HW_BMG, MFX_GT4 }, + { 0xE212, MFX_HW_BMG, MFX_GT4 }, + + /* LNL */ + { 0x6420, MFX_HW_LNL, MFX_GT2 }, + { 0x6480, MFX_HW_LNL, MFX_GT2 }, + { 0x64A0, MFX_HW_LNL, MFX_GT2 }, + { 0x64B0, MFX_HW_LNL, MFX_GT2 }, + +}; + +int getIntelHwType(uint16_t device_id) +{ + for (int i = 0; i < ARRAY_SIZE(listLegalDevIDs); ++i) { + if (listLegalDevIDs[i].device_id == device_id) { + return listLegalDevIDs[i].platform; + } + } + return -1; +} + +bool isIntelDg2(int fd) +{ + int ret; + uint16_t device_id; + + ret = gem_param(fd, I915_PARAM_CHIPSET_ID); + if (ret == -1) { + return false; + } + device_id = (uint16_t) ret; + ret = getIntelHwType(device_id); + return ret == MFX_HW_DG2; +} + +bool isVirtioGpuAllowP2p(int virtgpu_fd) { + struct drm_virtgpu_getparam get_param = { 0, 0 }; + uint64_t value = 0; + get_param.param = VIRTGPU_PARAM_ALLOW_P2P; + get_param.value = (__u64) &value; + int ret = drmIoctl(virtgpu_fd, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param); + if (ret || value != 1) { + return false; + } + return true; +} + +bool isVirtioGpuPciDevice(int virtgpu_fd) { + struct drm_virtgpu_getparam get_param = { 0, 0 }; + uint64_t value = 0; + get_param.param = VIRTGPU_PARAM_QUERY_DEV; + get_param.value = (__u64) &value; + int ret = drmIoctl(virtgpu_fd, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param); + if (ret || value != 1) { + return false; + } + return true; +} + +bool isVirtioGpuWithBlob(int virtgpu_fd) { + struct drm_virtgpu_getparam get_param = { 0, 0 }; + uint64_t value = 0; + get_param.param = VIRTGPU_PARAM_RESOURCE_BLOB; + get_param.value = (__u64) &value; + int ret = drmIoctl(virtgpu_fd, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param); + if (ret || value != 1) { + return false; + } + return true; +} + +uint64_t getGpuGroupType() { + static bool cached = false; + static uint64_t gpu_grp_type = 0; + if (cached) { + return gpu_grp_type; + } + for (int i = 0; i < 16; ++i) { + char path[64]; + snprintf(path, sizeof(path), "/dev/dri/renderD%d", 128 + i); + int fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) { + continue; + } + drmVersionPtr version = drmGetVersion(fd); + if (version == NULL) { + close(fd); + continue; + } + if (strcmp(version->name, "i915") == 0) { + if (isIntelDg2(fd)) { + gpu_grp_type |= GPU_GRP_TYPE_HAS_INTEL_DGPU_BIT; + } else { + gpu_grp_type |= GPU_GRP_TYPE_HAS_INTEL_IGPU_BIT; + } + } else if (strcmp(version->name, "virtio_gpu") == 0) { + if (!isVirtioGpuPciDevice(fd)) { + gpu_grp_type |= GPU_GRP_TYPE_HAS_VIRTIO_GPU_IVSHMEM_BIT; + } else { + if (!isVirtioGpuWithBlob(fd)) { + gpu_grp_type |= GPU_GRP_TYPE_HAS_VIRTIO_GPU_NO_BLOB_BIT; + } else { + if (isVirtioGpuAllowP2p(fd)) { + gpu_grp_type |= GPU_GRP_TYPE_HAS_VIRTIO_GPU_BLOB_P2P_BIT; + } else { + gpu_grp_type |= GPU_GRP_TYPE_HAS_VIRTIO_GPU_BLOB_BIT; + } + } + } + } + drmFreeVersion(version); + close(fd); + } + cached = true; + return gpu_grp_type; +} + +// Returns true in hybrid-GPU case. +bool enforceLinearBuffer() { + // virtio-GPU without blob feature cannot import external buffers at all, + // we must use linear system memory buffers. + uint64_t gpu_grp_type = getGpuGroupType(); + if (gpu_grp_type & GPU_GRP_TYPE_HAS_VIRTIO_GPU_NO_BLOB_BIT) { + return true; + } + // virtio-GPU backed by DG2 (virtio-GPU with ALLOW_P2P feature) whereas + // rendering/decoding uses iGPU. + if ((gpu_grp_type & GPU_GRP_TYPE_HAS_VIRTIO_GPU_BLOB_P2P_BIT) && + (gpu_grp_type & GPU_GRP_TYPE_HAS_INTEL_IGPU_BIT)) { + return true; + } + // virtio-GPU backed by iGPU whereas rendering/decoding uses DG2. + if ((gpu_grp_type & GPU_GRP_TYPE_HAS_VIRTIO_GPU_BLOB_BIT) && + (gpu_grp_type & GPU_GRP_TYPE_HAS_INTEL_DGPU_BIT)) { + return true; + } + return false; +} +