-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
1,017 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) 2017-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 "mfx_c2_component.h" | ||
#include "mfx_c2_decoder_component.h" | ||
#include "mfx_c2_components_registry.h" | ||
#include "mfx_dev.h" | ||
#include "mfx_c2_setters.h" | ||
#include <cutils/properties.h> | ||
|
||
class MfxC2SecureDecoderComponent : public MfxC2DecoderComponent | ||
{ | ||
public: | ||
MfxC2SecureDecoderComponent(const C2String name, const CreateConfig& config, | ||
std::shared_ptr<C2ReflectorHelper> reflector, DecoderType decoder_type); | ||
|
||
virtual ~MfxC2SecureDecoderComponent(); | ||
|
||
static void RegisterClass(MfxC2ComponentsRegistry& registry); | ||
|
||
MFX_CLASS_NO_COPY(MfxC2SecureDecoderComponent) | ||
|
||
protected: | ||
void DoWork(std::unique_ptr<C2Work>&& work); | ||
|
||
private: | ||
/* -----------------------C2Parameters--------------------------- */ | ||
std::shared_ptr<C2SecureModeTuning> m_secureMode; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
// Copyright (c) 2017-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 "mfx_c2_secure_decoder_component.h" | ||
|
||
#include "mfx_defs.h" | ||
#include "mfx_c2_utils.h" | ||
|
||
#include "mfx_debug.h" | ||
#include "mfx_msdk_debug.h" | ||
#include "mfx_c2_debug.h" | ||
#include "mfx_c2_components_registry.h" | ||
#include "mfx_defaults.h" | ||
#include "C2PlatformSupport.h" | ||
|
||
#undef MFX_DEBUG_MODULE_NAME | ||
#define MFX_DEBUG_MODULE_NAME "mfx_c2_secure_decoder_component" | ||
|
||
constexpr c2_nsecs_t TIMEOUT_NS = MFX_SECOND_NS; | ||
|
||
|
||
MfxC2SecureDecoderComponent::MfxC2SecureDecoderComponent(const C2String name, const CreateConfig& config, | ||
std::shared_ptr<C2ReflectorHelper> reflector, DecoderType decoder_type) : | ||
MfxC2DecoderComponent(name, config, std::move(reflector), decoder_type) | ||
{ | ||
MFX_DEBUG_TRACE_FUNC; | ||
|
||
const unsigned int SINGLE_STREAM_ID = 0u; | ||
|
||
// ALOGD("ZHDEBUG: No SM_READ_PROTECTED_WITH_ENCRYPTED in initialization"); | ||
|
||
addParameter( | ||
DefineParam(m_secureMode, C2_PARAMKEY_SECURE_MODE) | ||
.withConstValue(new C2SecureModeTuning(C2Config::secure_mode_t::SM_READ_PROTECTED_WITH_ENCRYPTED)) | ||
.build()); | ||
} | ||
|
||
MfxC2SecureDecoderComponent::~MfxC2SecureDecoderComponent() | ||
{ | ||
MFX_DEBUG_TRACE_FUNC; | ||
|
||
MfxC2DecoderComponent::Release(); | ||
} | ||
|
||
void MfxC2SecureDecoderComponent::RegisterClass(MfxC2ComponentsRegistry& registry) | ||
{ | ||
MFX_DEBUG_TRACE_FUNC; | ||
|
||
registry.RegisterMfxC2Component("c2.intel.avc.decoder.secure", | ||
&MfxC2Component::Factory<MfxC2SecureDecoderComponent, DecoderType>::Create<DECODER_H264_SECURE>); | ||
|
||
registry.RegisterMfxC2Component("c2.intel.hevc.decoder.secure", | ||
&MfxC2Component::Factory<MfxC2SecureDecoderComponent, DecoderType>::Create<DECODER_H265_SECURE>); | ||
} | ||
|
||
void MfxC2SecureDecoderComponent::DoWork(std::unique_ptr<C2Work>&& work) | ||
{ | ||
MFX_DEBUG_TRACE_FUNC; | ||
|
||
if (m_bFlushing) { | ||
m_flushedWorks.push_back(std::move(work)); | ||
return; | ||
} | ||
|
||
c2_status_t res = C2_OK; | ||
mfxStatus mfx_sts = MFX_ERR_NONE; | ||
|
||
const auto incoming_frame_index = work->input.ordinal.frameIndex; | ||
const auto incoming_flags = work->input.flags; | ||
|
||
MFX_DEBUG_TRACE_STREAM("work: " << work.get() << "; index: " << incoming_frame_index.peeku() << | ||
" flags: " << std::hex << incoming_flags); | ||
|
||
|
||
bool expect_output = false; | ||
bool flushing = false; | ||
bool codecConfig = ((incoming_flags & C2FrameData::FLAG_CODEC_CONFIG) != 0); | ||
// Av1 and VP9 don't need the bs which flag is config. | ||
if (codecConfig && (DECODER_AV1 == m_decoderType || DECODER_VP9 == m_decoderType)) { | ||
FillEmptyWork(std::move(work), C2_OK); | ||
if (true == m_bInitialized) { | ||
mfxStatus format_change_sts = HandleFormatChange(); | ||
MFX_DEBUG_TRACE__mfxStatus(format_change_sts); | ||
mfx_sts = format_change_sts; | ||
if (MFX_ERR_NONE != mfx_sts) { | ||
FreeDecoder(); | ||
} | ||
} | ||
return; | ||
} else if (DECODER_AV1 == m_decoderType && m_c2Bitstream->IsInReset()) { | ||
if (true == m_bInitialized) { | ||
mfxStatus format_change_sts = HandleFormatChange(); | ||
MFX_DEBUG_TRACE__mfxStatus(format_change_sts); | ||
mfx_sts = format_change_sts; | ||
if (MFX_ERR_NONE != mfx_sts) { | ||
FreeDecoder(); | ||
} | ||
} | ||
} | ||
|
||
do { | ||
std::unique_ptr<C2ReadView> read_view; | ||
res = m_c2Bitstream->AppendFrame(work->input, TIMEOUT_NS, &read_view); | ||
if (C2_OK != res) break; | ||
|
||
{ | ||
std::lock_guard<std::mutex> lock(m_readViewMutex); | ||
m_readViews.emplace(incoming_frame_index.peeku(), std::move(read_view)); | ||
MFX_DEBUG_TRACE_I32(m_readViews.size()); | ||
} | ||
|
||
if (work->input.buffers.size() == 0) break; | ||
|
||
PushPending(std::move(work)); | ||
|
||
if (!m_c2Allocator) { | ||
res = GetCodec2BlockPool(m_outputPoolId, | ||
shared_from_this(), &m_c2Allocator); | ||
if (res != C2_OK) break; | ||
#ifdef MFX_BUFFER_QUEUE | ||
bool hasSurface = std::static_pointer_cast<MfxC2BufferQueueBlockPool>(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; | ||
do { | ||
if (!m_bInitialized) { | ||
mfx_sts = InitDecoder(m_c2Allocator); | ||
if(MFX_ERR_NONE != mfx_sts) { | ||
MFX_DEBUG_TRACE__mfxStatus(mfx_sts); | ||
if (MFX_ERR_MORE_DATA == mfx_sts) { | ||
mfx_sts = MFX_ERR_NONE; // not enough data for InitDecoder should not cause an error | ||
} | ||
res = MfxStatusToC2(mfx_sts); | ||
break; | ||
} | ||
if (!m_bInitialized) { | ||
MFX_DEBUG_TRACE_MSG("Cannot initialize mfx decoder"); | ||
res = C2_BAD_VALUE; | ||
break; | ||
} | ||
} | ||
|
||
if (!m_bSetHdrStatic) UpdateHdrStaticInfo(); | ||
|
||
mfxBitstream *bs = m_c2Bitstream->GetFrameConstructor()->GetMfxBitstream().get(); | ||
MfxC2FrameOut frame_out; | ||
do { | ||
// check bitsream is empty | ||
if (bs && bs->DataLength == 0) { | ||
mfx_sts = MFX_ERR_MORE_DATA; | ||
break; | ||
} | ||
|
||
res = AllocateFrame(&frame_out); | ||
if (C2_OK != res) break; | ||
|
||
mfx_sts = DecodeFrame(bs, std::move(frame_out), &flushing, &expect_output); | ||
} while (mfx_sts == MFX_ERR_NONE || mfx_sts == MFX_ERR_MORE_SURFACE); | ||
|
||
if (MFX_ERR_MORE_DATA == mfx_sts) { | ||
mfx_sts = MFX_ERR_NONE; // valid result of DecodeFrame | ||
} | ||
|
||
resolution_change = (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == mfx_sts); | ||
if (resolution_change) { | ||
frame_out = MfxC2FrameOut(); // release the frame to be used in Drain | ||
|
||
Drain(nullptr); | ||
|
||
// Clear up all queue of works after drain except last work | ||
// which caused resolution change and should be used again. | ||
{ | ||
std::lock_guard<std::mutex> lock(m_pendingWorksMutex); | ||
auto it = m_pendingWorks.begin(); | ||
while (it != m_pendingWorks.end()) { | ||
if (it->first != incoming_frame_index) { | ||
MFX_DEBUG_TRACE_STREAM("Work removed: " << NAMED(it->second->input.ordinal.frameIndex.peeku())); | ||
NotifyWorkDone(std::move(it->second), C2_NOT_FOUND); | ||
it = m_pendingWorks.erase(it); | ||
} else { | ||
++it; | ||
} | ||
} | ||
} | ||
|
||
mfxStatus format_change_sts = HandleFormatChange(); | ||
MFX_DEBUG_TRACE__mfxStatus(format_change_sts); | ||
mfx_sts = format_change_sts; | ||
if (MFX_ERR_NONE != mfx_sts) { | ||
FreeDecoder(); | ||
} | ||
} | ||
|
||
} while (resolution_change); // try again as it is a resolution change | ||
|
||
if (C2_OK != res) break; // if loop above was interrupted by C2 error | ||
|
||
if (MFX_ERR_NONE != mfx_sts) { | ||
MFX_DEBUG_TRACE__mfxStatus(mfx_sts); | ||
res = MfxStatusToC2(mfx_sts); | ||
break; | ||
} | ||
|
||
res = m_c2Bitstream->Unload(); | ||
if (C2_OK != res) break; | ||
|
||
} while(false); // fake loop to have a cleanup point there | ||
|
||
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()); | ||
|
||
// notify listener in case of failure or empty output | ||
if (C2_OK != res || !expect_output || incomplete_frame || flushing) { | ||
if (!work) { | ||
std::lock_guard<std::mutex> lock(m_pendingWorksMutex); | ||
auto it = m_pendingWorks.find(incoming_frame_index); | ||
if (it != m_pendingWorks.end()) { | ||
work = std::move(it->second); | ||
m_pendingWorks.erase(it); | ||
} else { | ||
MFX_DEBUG_TRACE_STREAM("Not found C2Work, index = " << incoming_frame_index.peeku()); | ||
// If not found, it might be removed by WaitWork. We don't need to return an error. | ||
// FatalError(C2_CORRUPTED); | ||
} | ||
} | ||
if (work) { | ||
if (flushing) { | ||
m_flushedWorks.push_back(std::move(work)); | ||
} else { | ||
FillEmptyWork(std::move(work), res); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.