blob: 7c2fd698c86e2bd9e41227f3785cde1e8f940a08 [file] [log] [blame]
/*
* Copyright (c) 2018-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_pipeline.cpp
//! \brief Defines the common interface for decode pipeline
//! \details The decode pipeline interface is further sub-divided by codec standard,
//! this file is for the base interface which is shared by all codecs.
//!
#include "decode_pipeline.h"
#include "decode_utils.h"
#include "decode_status_report.h"
#include "media_packet.h"
#include "decode_predication_packet.h"
#include "decode_marker_packet.h"
#include "decode_downsampling_packet.h"
#include "codechal_setting.h"
#include "decode_basic_feature.h"
#include "mos_solo_generic.h"
#include "decode_sfc_histogram_postsubpipeline.h"
#include "decode_common_feature_defs.h"
namespace decode {
DecodePipeline::DecodePipeline(
CodechalHwInterface *hwInterface,
CodechalDebugInterface *debugInterface):
MediaPipeline(hwInterface ? hwInterface->GetOsInterface() : nullptr)
{
DECODE_FUNC_CALL();
DECODE_ASSERT(hwInterface != nullptr);
m_hwInterface = hwInterface;
m_singleTaskPhaseSupported =
ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_SINGLE_TASK_PHASE_ENABLE_ID, m_osInterface ? m_osInterface->pOsContext : nullptr).i32Data ? true : false;
CODECHAL_DEBUG_TOOL(
DECODE_ASSERT(debugInterface != nullptr);
m_debugInterface = debugInterface;
);
}
MOS_STATUS DecodePipeline::CreateStatusReport()
{
m_statusReport = MOS_New(DecodeStatusReport, m_allocator, true);
DECODE_CHK_NULL(m_statusReport);
DECODE_CHK_STATUS(m_statusReport->Create());
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::CreatePreSubPipeLines(DecodeSubPipelineManager &subPipelineManager)
{
m_bitstream = MOS_New(DecodeInputBitstream, this, m_task, m_numVdbox);
DECODE_CHK_NULL(m_bitstream);
DECODE_CHK_STATUS(subPipelineManager.Register(*m_bitstream));
m_streamout = MOS_New(DecodeStreamOut, this, m_task, m_numVdbox);
DECODE_CHK_NULL(m_streamout);
DECODE_CHK_STATUS(subPipelineManager.Register(*m_streamout));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::CreatePostSubPipeLines(DecodeSubPipelineManager &subPipelineManager)
{
DECODE_FUNC_CALL();
#ifdef _DECODE_PROCESSING_SUPPORTED
auto sfcHistogramPostSubPipeline = MOS_New(DecodeSfcHistogramSubPipeline, this, m_task, m_numVdbox);
DECODE_CHK_NULL(sfcHistogramPostSubPipeline);
DECODE_CHK_STATUS(m_postSubPipeline->Register(*sfcHistogramPostSubPipeline));
#endif
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::CreateSubPipeLineManager(CodechalSetting* codecSettings)
{
m_preSubPipeline = MOS_New(DecodeSubPipelineManager, *this);
DECODE_CHK_NULL(m_preSubPipeline);
DECODE_CHK_STATUS(CreatePreSubPipeLines(*m_preSubPipeline));
DECODE_CHK_STATUS(m_preSubPipeline->Init(*codecSettings));
m_postSubPipeline = MOS_New(DecodeSubPipelineManager, *this);
DECODE_CHK_NULL(m_postSubPipeline);
DECODE_CHK_STATUS(CreatePostSubPipeLines(*m_postSubPipeline));
DECODE_CHK_STATUS(m_postSubPipeline->Init(*codecSettings));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::CreateSubPackets(DecodeSubPacketManager& subPacketManager, CodechalSetting &codecSettings)
{
DecodePredicationPkt *predicationPkt = MOS_New(DecodePredicationPkt, this, m_hwInterface);
DECODE_CHK_NULL(predicationPkt);
DECODE_CHK_STATUS(subPacketManager.Register(
DecodePacketId(this, predicationSubPacketId), *predicationPkt));
DecodeMarkerPkt *markerPkt = MOS_New(DecodeMarkerPkt, this, m_hwInterface);
DECODE_CHK_NULL(markerPkt);
DECODE_CHK_STATUS(subPacketManager.Register(
DecodePacketId(this, markerSubPacketId), *markerPkt));
return MOS_STATUS_SUCCESS;
}
DecodeSubPacket* DecodePipeline::GetSubPacket(uint32_t subPacketId)
{
return m_subPacketManager->GetSubPacket(subPacketId);
}
MOS_STATUS DecodePipeline::CreateSubPacketManager(CodechalSetting* codecSettings)
{
DECODE_CHK_NULL(codecSettings);
m_subPacketManager = MOS_New(DecodeSubPacketManager);
DECODE_CHK_NULL(m_subPacketManager);
DECODE_CHK_STATUS(CreateSubPackets(*m_subPacketManager, *codecSettings));
DECODE_CHK_STATUS(m_subPacketManager->Init());
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::Initialize(void *settings)
{
DECODE_FUNC_CALL();
DECODE_CHK_NULL(settings);
DECODE_CHK_STATUS(MediaPipeline::InitPlatform());
DECODE_CHK_STATUS(MediaPipeline::CreateMediaCopy());
DECODE_CHK_NULL(m_waTable);
auto *codecSettings = (CodechalSetting*)settings;
DECODE_CHK_NULL(m_hwInterface);
DECODE_CHK_STATUS(m_hwInterface->Initialize(codecSettings));
m_mediaContext = MOS_New(MediaContext, scalabilityDecoder, m_hwInterface, m_osInterface);
DECODE_CHK_NULL(m_mediaContext);
m_task = CreateTask(MediaTask::TaskType::cmdTask);
DECODE_CHK_NULL(m_task);
m_numVdbox = GetSystemVdboxNumber();
m_allocator = MOS_New(DecodeAllocator, m_osInterface);
DECODE_CHK_NULL(m_allocator);
DECODE_CHK_STATUS(CreateStatusReport());
m_decodecp = Create_DecodeCpInterface(codecSettings, m_hwInterface);
if(m_decodecp)
{
m_decodecp->RegisterParams(codecSettings);
}
DECODE_CHK_STATUS(CreateFeatureManager());
DECODE_CHK_STATUS(m_featureManager->Init(codecSettings));
DECODE_CHK_STATUS(CreateSubPipeLineManager(codecSettings));
DECODE_CHK_STATUS(CreateSubPacketManager(codecSettings));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::Uninitialize()
{
DECODE_FUNC_CALL();
Delete_DecodeCpInterface(m_decodecp);
m_decodecp = nullptr;
MOS_Delete(m_mediaContext);
MOS_Delete(m_statusReport);
MOS_Delete(m_featureManager);
MOS_Delete(m_preSubPipeline);
MOS_Delete(m_postSubPipeline);
MOS_Delete(m_subPacketManager);
MOS_Delete(m_allocator);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::UserFeatureReport()
{
DECODE_FUNC_CALL();
return MediaPipeline::UserFeatureReport();
}
bool DecodePipeline::IsFirstProcessPipe(const DecodePipelineParams& pipelineParams)
{
if (pipelineParams.m_pipeMode != decodePipeModeProcess)
{
return false;
}
CodechalDecodeParams *decodeParams = pipelineParams.m_params;
if (decodeParams == nullptr)
{
return false;
}
return (decodeParams->m_executeCallIndex == 0);
}
uint8_t DecodePipeline::GetSystemVdboxNumber()
{
uint8_t numVdbox = 1;
MEDIA_SYSTEM_INFO *gtSystemInfo = m_osInterface->pfnGetGtSystemInfo(m_osInterface);
if (gtSystemInfo != nullptr)
{
// Both VE mode and media solo mode should be able to get the VDBOX number via the same interface
numVdbox = (uint8_t)(gtSystemInfo->VDBoxInfo.NumberOfVDBoxEnabled);
}
return numVdbox;
}
MOS_STATUS DecodePipeline::Prepare(void *params)
{
DECODE_FUNC_CALL();
DECODE_CHK_NULL(params);
DecodePipelineParams *pipelineParams = (DecodePipelineParams *)params;
CodechalDecodeParams *decodeParams = pipelineParams->m_params;
DECODE_CHK_NULL(decodeParams);
DECODE_CHK_NULL(m_featureManager);
DECODE_CHK_STATUS(m_featureManager->CheckFeatures(decodeParams));
DECODE_CHK_STATUS(m_featureManager->Update(decodeParams));
if(m_decodecp)
{
m_decodecp->UpdateParams(true);
}
DECODE_CHK_STATUS(m_subPacketManager->Prepare());
DECODE_CHK_STATUS(Mos_Solo_SetGpuAppTaskEvent(m_osInterface, decodeParams->m_gpuAppTaskEvent));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::ExecuteActivePackets()
{
DECODE_FUNC_CALL();
MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
// Last element in m_activePacketList must be immediately submitted
m_activePacketList.back().immediateSubmit = true;
for (PacketProperty prop : m_activePacketList)
{
prop.stateProperty.singleTaskPhaseSupported = m_singleTaskPhaseSupported;
prop.stateProperty.statusReport = m_statusReport;
MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_INFO, &prop.packetId, sizeof(uint32_t), nullptr, 0);
MediaTask *task = prop.packet->GetActiveTask();
DECODE_CHK_STATUS(task->AddPacket(&prop));
if (prop.immediateSubmit)
{
DECODE_CHK_STATUS(task->Submit(true, m_scalability, m_debugInterface));
DECODE_CHK_STATUS(task->Clear());
}
}
m_activePacketList.clear();
MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return MOS_STATUS_SUCCESS;
}
bool DecodePipeline::IsCompleteBitstream()
{
return (m_bitstream == nullptr) ? false : m_bitstream->IsComplete();
}
#ifdef _DECODE_PROCESSING_SUPPORTED
bool DecodePipeline::IsDownSamplingSupported()
{
DECODE_ASSERT(m_subPacketManager != nullptr);
DecodeDownSamplingPkt *downSamplingPkt = dynamic_cast<DecodeDownSamplingPkt *>(
GetSubPacket(DecodePacketId(this, downSamplingSubPacketId)));
if (downSamplingPkt == nullptr)
{
return false;
}
return downSamplingPkt->IsSupported();
}
#endif
MOS_SURFACE* DecodePipeline::GetDummyReference()
{
auto* feature = dynamic_cast<DecodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
return (feature != nullptr) ? &(feature->m_dummyReference) : nullptr;
}
CODECHAL_DUMMY_REFERENCE_STATUS DecodePipeline::GetDummyReferenceStatus()
{
auto* feature = dynamic_cast<DecodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
return (feature != nullptr) ? feature->m_dummyReferenceStatus : CODECHAL_DUMMY_REFERENCE_INVALID;
}
void DecodePipeline::SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_STATUS status)
{
auto* feature = dynamic_cast<DecodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
if (feature != nullptr)
{
feature->m_dummyReferenceStatus = status;
}
}
#if USE_CODECHAL_DEBUG_TOOL
#ifdef _DECODE_PROCESSING_SUPPORTED
MOS_STATUS DecodePipeline::DumpDownSamplingParams(DecodeDownSamplingFeature &downSamplingParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeProcParams))
{
return MOS_STATUS_SUCCESS;
}
if(!downSamplingParams.IsEnabled())
{
return MOS_STATUS_SUCCESS;
}
DECODE_CHK_NULL(downSamplingParams.m_inputSurface);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "Input Surface Resolution: "
<< +downSamplingParams.m_inputSurface->dwWidth << " x " << +downSamplingParams.m_inputSurface->dwHeight << std::endl;
oss << "Input Region Resolution: "
<< +downSamplingParams.m_inputSurfaceRegion.m_width << " x " << +downSamplingParams.m_inputSurfaceRegion.m_height << std::endl;
oss << "Input Region Offset: ("
<< +downSamplingParams.m_inputSurfaceRegion.m_x << "," << +downSamplingParams.m_inputSurfaceRegion.m_y << ")" << std::endl;
oss << "Input Surface Format: "
<< (downSamplingParams.m_inputSurface->Format == Format_NV12 ? "NV12" : "P010" )<< std::endl;
oss << "Output Surface Resolution: "
<< +downSamplingParams.m_outputSurface.dwWidth << " x " << +downSamplingParams.m_outputSurface.dwHeight << std::endl;
oss << "Output Region Resolution: "
<< +downSamplingParams.m_outputSurfaceRegion.m_width << " x " << +downSamplingParams.m_outputSurfaceRegion.m_height << std::endl;
oss << "Output Region Offset: ("
<< +downSamplingParams.m_outputSurfaceRegion.m_x << ", " << +downSamplingParams.m_outputSurfaceRegion.m_y << ")" << std::endl;
oss << "Output Surface Format: "
<< (downSamplingParams.m_outputSurface.Format == Format_NV12 ? "NV12" : "YUY2" )<< std::endl;
const char* filePath = m_debugInterface->CreateFileName(
"_DEC",
CodechalDbgBufferType::bufDecProcParams,
CodechalDbgExtType::txt);
std::ofstream ofs(filePath, std::ios::out);
ofs << oss.str();
ofs.close();
return MOS_STATUS_SUCCESS;
}
#endif
MOS_STATUS DecodePipeline::DumpOutput(const DecodeStatusReportData& reportData)
{
DECODE_FUNC_CALL();
MOS_SURFACE dstSurface;
MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
dstSurface.Format = Format_NV12;
dstSurface.OsResource = reportData.currDecodedPicRes;
DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&dstSurface));
DECODE_CHK_STATUS(m_debugInterface->DumpYUVSurface(
&dstSurface, CodechalDbgAttr::attrDecodeOutputSurface, "DstSurf"));
#ifdef _DECODE_PROCESSING_SUPPORTED
DecodeDownSamplingFeature* downSamplingFeature = dynamic_cast<DecodeDownSamplingFeature*>(
m_featureManager->GetFeature(DecodeFeatureIDs::decodeDownSampling));
if (downSamplingFeature != nullptr && downSamplingFeature->IsEnabled())
{
if (reportData.currSfcOutputPicRes != nullptr)
{
MOS_SURFACE sfcDstSurface;
MOS_ZeroMemory(&sfcDstSurface, sizeof(sfcDstSurface));
sfcDstSurface.Format = Format_NV12;
sfcDstSurface.OsResource = *reportData.currSfcOutputPicRes;
if (!Mos_ResourceIsNull(&sfcDstSurface.OsResource))
{
DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&sfcDstSurface));
DECODE_CHK_STATUS(m_debugInterface->DumpYUVSurface(
&sfcDstSurface, CodechalDbgAttr::attrSfcOutputSurface, "SfcDstSurf"));
}
}
}
#endif
return MOS_STATUS_SUCCESS;
}
#endif
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_STATUS DecodePipeline::ReportVdboxIds(const DecodeStatusMfx& status)
{
DECODE_FUNC_CALL();
// report the VDBOX IDs to user feature
uint32_t vdboxIds = ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_VDBOX_ID_USED, m_osInterface->pOsContext).u32Data;
for (auto i = 0; i < csInstanceIdMax; i++)
{
CsEngineId csEngineId;
csEngineId.value = status.m_mmioCsEngineIdReg[i];
if (csEngineId.value != 0)
{
DECODE_ASSERT(csEngineId.fields.classId == classIdVideoEngine);
DECODE_ASSERT(csEngineId.fields.instanceId < csInstanceIdMax);
vdboxIds |= 1 << ((csEngineId.fields.instanceId) << 2);
}
}
if (vdboxIds != 0)
{
WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_VDBOX_ID_USED, vdboxIds, m_osInterface->pOsContext);
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS DecodePipeline::StatusCheck()
{
DECODE_FUNC_CALL();
uint32_t completedCount = m_statusReport->GetCompletedCount();
if (completedCount <= m_statusCheckCount)
{
DECODE_CHK_COND(completedCount < m_statusCheckCount, "Invalid statuc check count");
return MOS_STATUS_SUCCESS;
}
DecodeStatusReport* statusReport = dynamic_cast<DecodeStatusReport*>(m_statusReport);
DECODE_CHK_NULL(statusReport);
while (m_statusCheckCount < completedCount)
{
const DecodeStatusMfx& status = statusReport->GetMfxStatus(m_statusCheckCount);
if (status.status != DecodeStatusReport::queryEnd)
{
DECODE_ASSERTMESSAGE("Media reset may have occured at frame %d.", m_statusCheckCount);
}
DECODE_CHK_STATUS(ReportVdboxIds(status));
#if USE_CODECHAL_DEBUG_TOOL
const DecodeStatusReportData& reportData = statusReport->GetReportData(m_statusCheckCount);
auto bufferDumpNumTemp = m_debugInterface->m_bufferDumpFrameNum;
auto currPicTemp = m_debugInterface->m_currPic;
auto frameTypeTemp = m_debugInterface->m_frameType;
m_debugInterface->m_bufferDumpFrameNum = m_statusCheckCount;
m_debugInterface->m_currPic = reportData.currDecodedPic;
m_debugInterface->m_frameType = reportData.frameType;
DECODE_CHK_STATUS(DumpOutput(reportData));
m_debugInterface->m_bufferDumpFrameNum = bufferDumpNumTemp;
m_debugInterface->m_currPic = currPicTemp;
m_debugInterface->m_frameType = frameTypeTemp;
#endif
m_statusCheckCount++;
}
return MOS_STATUS_SUCCESS;
}
#endif
}