blob: eef40762bc07578196f01acbda0c39e323e0967f [file] [log] [blame]
/*
* Copyright (c) 2020-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.
*/
//!
//! \file decode_vp9_pipeline.cpp
//! \brief Defines the interface for vp9 decode pipeline
//!
#include "decode_vp9_pipeline.h"
#include "decode_utils.h"
#include "media_user_settings_mgr_g12_plus.h"
#include "codechal_setting.h"
#include "decode_vp9_phase_single.h"
#include "decode_vp9_phase_front_end.h"
#include "decode_vp9_phase_back_end.h"
#include "decode_vp9_feature_manager.h"
#include "decode_vp9_buffer_update.h"
namespace decode
{
Vp9Pipeline::Vp9Pipeline(
CodechalHwInterface *hwInterface,
CodechalDebugInterface *debugInterface)
: DecodePipeline(hwInterface, debugInterface)
{
MOS_STATUS m_status = InitUserSetting(m_userSettingPtr);
}
MOS_STATUS Vp9Pipeline::Initialize(void *settings)
{
DECODE_FUNC_CALL();
DECODE_CHK_STATUS(DecodePipeline::Initialize(settings));
// Create basic GPU context
DecodeScalabilityPars scalPars;
MOS_ZeroMemory(&scalPars, sizeof(scalPars));
DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, &scalPars, &m_scalability));
m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
m_basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
DECODE_CHK_NULL(m_basicFeature);
auto *codecSettings = (CodechalSetting *)settings;
DECODE_CHK_NULL(codecSettings);
auto *bufferUpdatePipeline = MOS_New(DecodeVp9BufferUpdate, this, m_task, m_numVdbox);
DECODE_CHK_NULL(bufferUpdatePipeline);
DECODE_CHK_STATUS(m_preSubPipeline->Register(*bufferUpdatePipeline));
DECODE_CHK_STATUS(bufferUpdatePipeline->Init(*codecSettings));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::Prepare(void *params)
{
DECODE_FUNC_CALL();
DECODE_CHK_NULL(params);
auto basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
DECODE_CHK_NULL(basicFeature);
DECODE_CHK_STATUS(DecodePipeline::Prepare(params));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::Uninitialize()
{
DECODE_FUNC_CALL();
#if (_DEBUG || _RELEASE_INTERNAL)
// Report real tile frame count and virtual tile frame count
MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
userFeatureWriteData.Value.i32Data = m_vtFrameCount;
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_ENABLE_HEVC_DECODE_VT_FRAME_COUNT_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
#endif
DECODE_CHK_STATUS(DestoryPhaseList());
return DecodePipeline::Uninitialize();
}
MOS_STATUS Vp9Pipeline::UserFeatureReport()
{
DECODE_FUNC_CALL();
DECODE_CHK_STATUS(DecodePipeline::UserFeatureReport());
#if (_DEBUG || _RELEASE_INTERNAL)
WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_APOGEIOS_VP9D_ENABLE_ID, 1, m_osInterface->pOsContext);
#endif
#ifdef _MMC_SUPPORTED
CODECHAL_DEBUG_TOOL(
if (m_mmcState != nullptr) {
m_mmcState->UpdateUserFeatureKey(&(m_basicFeature->m_destSurface));
})
#endif
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::Execute()
{
DECODE_FUNC_CALL();
#if (_DEBUG || _RELEASE_INTERNAL)
if (GetDecodeMode() == virtualTileDecodeMode)
{
m_vtFrameCount++;
}
#endif
for (auto &phase : m_phaseList)
{
DECODE_ASSERT(phase != nullptr);
if (phase->RequiresContextSwitch())
{
// switch context
DecodeScalabilityOption *scalabOption = phase->GetDecodeScalabilityOption();
DECODE_CHK_NULL(scalabOption);
DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, *scalabOption, &m_scalability));
if (scalabOption->IsScalabilityOptionMatched(m_scalabOption))
{
m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
}
}
StateParams stateProperty;
stateProperty.currentPipe = phase->GetPipe();
stateProperty.currentPass = phase->GetPass();
stateProperty.pipeIndexForSubmit = phase->GetPipe() + 1;
stateProperty.componentState = phase;
DECODE_CHK_STATUS(ActivatePacket(phase->GetPktId(), phase->ImmediateSubmit(), stateProperty));
if (phase->ImmediateSubmit())
{
m_scalability->SetPassNumber(phase->GetPass() + 1);
DECODE_CHK_STATUS(ExecuteActivePackets());
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::CreateFeatureManager()
{
DECODE_FUNC_CALL();
m_featureManager = MOS_New(DecodeVp9FeatureManager, m_allocator, m_hwInterface);
DECODE_CHK_NULL(m_featureManager);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::CreateSubPackets(DecodeSubPacketManager &subPacketManager, CodechalSetting &codecSettings)
{
DECODE_FUNC_CALL();
DECODE_CHK_STATUS(DecodePipeline::CreateSubPackets(subPacketManager, codecSettings));
return MOS_STATUS_SUCCESS;
}
Vp9Pipeline::Vp9DecodeMode Vp9Pipeline::GetDecodeMode()
{
return m_decodeMode;
}
MOS_STATUS Vp9Pipeline::InitContexOption(Vp9BasicFeature &basicFeature)
{
DecodeScalabilityPars scalPars;
MOS_ZeroMemory(&scalPars, sizeof(scalPars));
scalPars.usingHcp = true;
scalPars.enableVE = MOS_VE_SUPPORTED(m_osInterface);
scalPars.disableScalability = m_hwInterface->IsDisableScalability();
scalPars.surfaceFormat = basicFeature.m_destSurface.Format;
scalPars.frameWidth = basicFeature.m_frameWidthAlignedMinBlk;
scalPars.frameHeight = basicFeature.m_frameHeightAlignedMinBlk;
scalPars.numVdbox = m_numVdbox;
#if (_DEBUG || _RELEASE_INTERNAL)
if (m_osInterface->bHcpDecScalabilityMode == MOS_SCALABILITY_ENABLE_MODE_FALSE)
{
scalPars.disableScalability = true;
}
else if (m_osInterface->bHcpDecScalabilityMode == MOS_SCALABILITY_ENABLE_MODE_USER_FORCE)
{
scalPars.disableScalability = false;
}
scalPars.modeSwithThreshold1 =
ReadUserFeature(m_userSettingPtr, "HCP Decode Mode Switch TH1", MediaUserSetting::Group::Sequence).Get<uint32_t>();
scalPars.modeSwithThreshold2 =
ReadUserFeature(m_userSettingPtr, "HCP Decode Mode Switch TH2", MediaUserSetting::Group::Sequence).Get<uint32_t>();
scalPars.forceMultiPipe =
ReadUserFeature(m_userSettingPtr, "HCP Decode Always Frame Split", MediaUserSetting::Group::Sequence).Get<bool>();
scalPars.userPipeNum =
ReadUserFeature(m_userSettingPtr, "HCP Decode User Pipe Num", MediaUserSetting::Group::Sequence).Get<uint8_t>();
#endif
#ifdef _DECODE_PROCESSING_SUPPORTED
DecodeDownSamplingFeature *downSamplingFeature = dynamic_cast<DecodeDownSamplingFeature *>(
m_featureManager->GetFeature(DecodeFeatureIDs::decodeDownSampling));
if (downSamplingFeature != nullptr && downSamplingFeature->IsEnabled())
{
scalPars.usingSfc = true;
if (!MEDIA_IS_SKU(m_skuTable, FtrSfcScalability))
{
scalPars.disableScalability = true;
}
}
//Disable Scalability when histogram is enabled
if (downSamplingFeature != nullptr && (downSamplingFeature->m_histogramDestSurf || downSamplingFeature->m_histogramDebug))
{
scalPars.disableScalability = true;
}
#endif
DECODE_CHK_STATUS(m_scalabOption.SetScalabilityOption(&scalPars));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::InitDecodeMode(ScalabilityMode scalabMode)
{
if (scalabMode == scalabilityVirtualTileMode)
{
m_decodeMode = virtualTileDecodeMode;
}
else if (scalabMode == scalabilitySingleMode)
{
m_decodeMode = baseDecodeMode;
}
else
{
return MOS_STATUS_INVALID_PARAMETER;
}
return MOS_STATUS_SUCCESS;
}
template <typename T>
MOS_STATUS Vp9Pipeline::CreatePhase(uint8_t pass, uint8_t pipe, uint8_t activePipeNum)
{
DECODE_FUNC_CALL();
T *phase = MOS_New(T, *this, m_scalabOption);
DECODE_CHK_NULL(phase);
DECODE_CHK_STATUS(phase->Initialize(pass, pipe, activePipeNum));
m_phaseList.push_back(phase);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::CreatePhaseList(const ScalabilityMode scalabMode, const uint8_t numPipe)
{
DECODE_FUNC_CALL();
DECODE_ASSERT(m_phaseList.empty());
if (scalabMode == scalabilityVirtualTileMode)
{
DECODE_CHK_STATUS(CreatePhase<Vp9PhaseFrontEnd>());
for (uint8_t i = 0; i < numPipe; i++)
{
DECODE_CHK_STATUS(CreatePhase<Vp9PhaseBackEnd>(0, i, numPipe));
}
}
else
{
DECODE_CHK_STATUS(CreatePhase<Vp9PhaseSingle>());
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::DestoryPhaseList()
{
for (auto &phase : m_phaseList)
{
MOS_Delete(phase);
}
m_phaseList.clear();
return MOS_STATUS_SUCCESS;
}
#if USE_CODECHAL_DEBUG_TOOL
MOS_STATUS Vp9Pipeline::DumpPicParams(CODEC_VP9_PIC_PARAMS *picParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(picParams);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "CurrPic FrameIdx: " << std::hex << +picParams->CurrPic.FrameIdx << std::endl;
oss << "CurrPic PicFlags: " << std::hex << +picParams->CurrPic.PicFlags << std::endl;
for (uint8_t i = 0; i < 8; ++i)
{
oss << "RefFrameList[" << +i << "] FrameIdx:" << std::hex << +picParams->RefFrameList[i].FrameIdx << std::endl;
oss << "RefFrameList[" << +i << "] PicFlags:" << std::hex << +picParams->RefFrameList[i].PicFlags << std::endl;
}
oss << "FrameWidthMinus1: " << std::hex << +picParams->FrameWidthMinus1 << std::endl;
oss << "FrameHeightMinus1: " << std::hex << +picParams->FrameHeightMinus1 << std::endl;
oss << "PicFlags value: " << std::hex << +picParams->PicFlags.value << std::endl;
oss << "frame_type: " << std::hex << +picParams->PicFlags.fields.frame_type << std::endl;
oss << "show_frame: " << std::hex << +picParams->PicFlags.fields.show_frame << std::endl;
oss << "error_resilient_mode: " << std::hex << +picParams->PicFlags.fields.error_resilient_mode << std::endl;
oss << "intra_only: " << std::hex << +picParams->PicFlags.fields.intra_only << std::endl;
oss << "LastRefIdx: " << std::hex << +picParams->PicFlags.fields.LastRefIdx << std::endl;
oss << "LastRefSignBias: " << std::hex << +picParams->PicFlags.fields.LastRefSignBias << std::endl;
oss << "GoldenRefIdx: " << std::hex << +picParams->PicFlags.fields.GoldenRefIdx << std::endl;
oss << "GoldenRefSignBias: " << std::hex << +picParams->PicFlags.fields.GoldenRefSignBias << std::endl;
oss << "AltRefIdx: " << std::hex << +picParams->PicFlags.fields.AltRefIdx << std::endl;
oss << "AltRefSignBias: " << std::hex << +picParams->PicFlags.fields.AltRefSignBias << std::endl;
oss << "allow_high_precision_mv: " << std::hex << +picParams->PicFlags.fields.allow_high_precision_mv << std::endl;
oss << "mcomp_filter_type: " << std::hex << +picParams->PicFlags.fields.mcomp_filter_type << std::endl;
oss << "frame_parallel_decoding_mode: " << std::hex << +picParams->PicFlags.fields.frame_parallel_decoding_mode << std::endl;
oss << "segmentation_enabled: " << std::hex << +picParams->PicFlags.fields.segmentation_enabled << std::endl;
oss << "segmentation_temporal_update: " << std::hex << +picParams->PicFlags.fields.segmentation_temporal_update << std::endl;
oss << "segmentation_update_map: " << std::hex << +picParams->PicFlags.fields.segmentation_update_map << std::endl;
oss << "reset_frame_context: " << std::hex << +picParams->PicFlags.fields.reset_frame_context << std::endl;
oss << "refresh_frame_context: " << std::hex << +picParams->PicFlags.fields.refresh_frame_context << std::endl;
oss << "frame_context_idx: " << std::hex << +picParams->PicFlags.fields.frame_context_idx << std::endl;
oss << "LosslessFlag: " << std::hex << +picParams->PicFlags.fields.LosslessFlag << std::endl;
oss << "ReservedField: " << std::hex << +picParams->PicFlags.fields.ReservedField << std::endl;
oss << "filter_level: " << std::hex << +picParams->filter_level << std::endl;
oss << "sharpness_level: " << std::hex << +picParams->sharpness_level << std::endl;
oss << "log2_tile_rows: " << std::hex << +picParams->log2_tile_rows << std::endl;
oss << "log2_tile_columns: " << std::hex << +picParams->log2_tile_columns << std::endl;
oss << "UncompressedHeaderLengthInBytes: " << std::hex << +picParams->UncompressedHeaderLengthInBytes << std::endl;
oss << "FirstPartitionSize: " << std::hex << +picParams->FirstPartitionSize << std::endl;
oss << "profile: " << std::hex << +picParams->profile << std::endl;
oss << "BitDepthMinus8: " << std::hex << +picParams->BitDepthMinus8 << std::endl;
oss << "subsampling_x: " << std::hex << +picParams->subsampling_x << std::endl;
oss << "subsampling_y: " << std::hex << +picParams->subsampling_y << std::endl;
for (uint8_t i = 0; i < 7; ++i)
{
oss << "SegTreeProbs[" << +i << "]: " << std::hex << +picParams->SegTreeProbs[i] << std::endl;
}
for (uint8_t i = 0; i < 3; ++i)
{
oss << "SegPredProbs[" << +i << "]: " << std::hex << +picParams->SegPredProbs[i] << std::endl;
}
oss << "BSBytesInBuffer: " << std::hex << +picParams->BSBytesInBuffer << std::endl;
oss << "StatusReportFeedbackNumber: " << std::hex << +picParams->StatusReportFeedbackNumber << std::endl;
const char *fileName = m_debugInterface->CreateFileName(
"_DEC",
CodechalDbgBufferType::bufPicParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Vp9Pipeline::DumpSegmentParams(CODEC_VP9_SEGMENT_PARAMS *segmentParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSegmentParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(segmentParams);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
for (uint8_t i = 0; i < 8; ++i)
{
oss << "SegData[" << +i << "] SegmentFlags value: " << std::hex << +segmentParams->SegData[i].SegmentFlags.value << std::endl;
oss << "SegData[" << +i << "] SegmentReferenceEnabled: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled << std::endl;
oss << "SegData[" << +i << "] SegmentReference: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReference << std::endl;
oss << "SegData[" << +i << "] SegmentReferenceSkipped: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceSkipped << std::endl;
oss << "SegData[" << +i << "] ReservedField3: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.ReservedField3 << std::endl;
for (uint8_t j = 0; j < 4; ++j)
{
oss << "SegData[" << +i << "] FilterLevel[" << +j << "]:";
oss << std::hex << +segmentParams->SegData[i].FilterLevel[j][0] << " ";
oss << std::hex << +segmentParams->SegData[i].FilterLevel[j][1] << std::endl;
}
oss << "SegData[" << +i << "] LumaACQuantScale: " << std::hex << +segmentParams->SegData[i].LumaACQuantScale << std::endl;
oss << "SegData[" << +i << "] LumaDCQuantScale: " << std::hex << +segmentParams->SegData[i].LumaDCQuantScale << std::endl;
oss << "SegData[" << +i << "] ChromaACQuantScale: " << std::hex << +segmentParams->SegData[i].ChromaACQuantScale << std::endl;
oss << "SegData[" << +i << "] ChromaDCQuantScale: " << std::hex << +segmentParams->SegData[i].ChromaDCQuantScale << std::endl;
}
const char *fileName = m_debugInterface->CreateFileName(
"_DEC",
CodechalDbgBufferType::bufSegmentParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
return MOS_STATUS_SUCCESS;
}
#endif
} // namespace decode