blob: 5807066d90a8c27f2de003917abd9acd200cd55d [file] [log] [blame]
/*
* Copyright (c) 2017-2020, 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 media_ddi_decode_base.cpp
//! \brief The class implementation of DdiDecodeBase for all decoders
//!
#include "media_libva_decoder.h"
#include "media_libva_vp.h"
#include "media_libva_util.h"
#include "media_ddi_decode_base.h"
#include "codechal.h"
#include "codechal_memdecomp.h"
#include "media_interfaces_codechal.h"
#include "media_interfaces_mmd.h"
#include "mos_solo_generic.h"
DdiMediaDecode::DdiMediaDecode(DDI_DECODE_CONFIG_ATTR *ddiDecodeAttr)
: DdiMediaBase()
{
m_ddiDecodeAttr = ddiDecodeAttr;
m_ddiDecodeCtx = nullptr;
MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface));
m_groupIndex = 0;
m_picWidthInMB = 0;
m_picHeightInMB = 0;
m_decProcessingType = 0;
m_width = 0;
m_height = 0;
m_streamOutEnabled = false;
m_sliceParamBufNum = 0;
m_sliceCtrlBufNum = 0;
m_codechalSettings = CodechalSetting::CreateCodechalSetting();
}
VAStatus DdiMediaDecode::BasicInit(
DDI_DECODE_CONFIG_ATTR *ddiConfAttr)
{
if (ddiConfAttr == nullptr)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
m_ddiDecodeAttr = (DDI_DECODE_CONFIG_ATTR *)MOS_AllocAndZeroMemory(
sizeof(DDI_DECODE_CONFIG_ATTR));
if (m_ddiDecodeAttr && ddiConfAttr)
{
MOS_SecureMemcpy(m_ddiDecodeAttr, sizeof(DDI_DECODE_CONFIG_ATTR), ddiConfAttr, sizeof(DDI_DECODE_CONFIG_ATTR));
}
m_ddiDecodeCtx = (DDI_DECODE_CONTEXT *)MOS_AllocAndZeroMemory(
sizeof(DDI_DECODE_CONTEXT));
if ((m_ddiDecodeAttr == nullptr) ||
(m_ddiDecodeCtx == nullptr))
{
MOS_FreeMemory(m_ddiDecodeAttr);
m_ddiDecodeAttr = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx);
m_ddiDecodeCtx = nullptr;
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
return VA_STATUS_SUCCESS;
}
uint32_t DdiMediaDecode::GetBsBufOffset(int32_t sliceGroup)
{
return m_ddiDecodeCtx->BufMgr.pSliceData[sliceGroup].uiOffset;
}
VAStatus DdiMediaDecode::ParseProcessingBuffer(
DDI_MEDIA_CONTEXT *mediaCtx,
void *bufAddr)
{
#ifdef _DECODE_PROCESSING_SUPPORTED
VAProcPipelineParameterBuffer *procBuf =
(VAProcPipelineParameterBuffer *)bufAddr;
DDI_CHK_NULL(procBuf, "nullptr Processing buffer", VA_STATUS_ERROR_INVALID_PARAMETER)
if (m_decProcessingType == VA_DEC_PROCESSING)
{
if(m_procBuf == nullptr)
{
m_procBuf = (VAProcPipelineParameterBuffer*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineParameterBuffer));
DDI_CHK_NULL(m_procBuf, "nullptr m_procBuf", VA_STATUS_ERROR_ALLOCATION_FAILED);
MOS_SecureMemcpy(m_procBuf, sizeof(VAProcPipelineParameterBuffer), procBuf, sizeof(VAProcPipelineParameterBuffer));
}
auto decProcessingParams =
(DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams;
auto decProcessingSurface = decProcessingParams->m_outputSurface;
memset(decProcessingSurface, 0, sizeof(MOS_SURFACE));
PDDI_MEDIA_SURFACE surface =
DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, procBuf->additional_outputs[0]);
DDI_CHK_NULL(surface, "Null surface in Processing buffer", VA_STATUS_ERROR_INVALID_PARAMETER)
DdiMedia_MediaSurfaceToMosResource(surface, &(decProcessingSurface->OsResource));
decProcessingSurface->dwWidth = decProcessingSurface->OsResource.iWidth;
decProcessingSurface->dwHeight = decProcessingSurface->OsResource.iHeight;
decProcessingSurface->dwPitch = decProcessingSurface->OsResource.iPitch;
decProcessingSurface->TileType = decProcessingSurface->OsResource.TileType;
decProcessingSurface->Format = decProcessingSurface->OsResource.Format;
decProcessingParams->m_inputSurfaceRegion.m_x = procBuf->surface_region->x;
decProcessingParams->m_inputSurfaceRegion.m_y = procBuf->surface_region->y;
decProcessingParams->m_inputSurfaceRegion.m_width = procBuf->surface_region->width;
decProcessingParams->m_inputSurfaceRegion.m_height = procBuf->surface_region->height;
decProcessingParams->m_outputSurface = decProcessingSurface;
decProcessingParams->m_outputSurfaceRegion.m_x = procBuf->output_region->x;
decProcessingParams->m_outputSurfaceRegion.m_y = procBuf->output_region->y;
decProcessingParams->m_outputSurfaceRegion.m_width = procBuf->output_region->width;
decProcessingParams->m_outputSurfaceRegion.m_height = procBuf->output_region->height;
// Interpolation flags
// Set the vdbox scaling mode
uint32_t uInterpolationflags = 0;
#if VA_CHECK_VERSION(1, 9, 0)
uInterpolationflags = procBuf->filter_flags & VA_FILTER_INTERPOLATION_MASK;
#endif
switch (uInterpolationflags)
{
#if VA_CHECK_VERSION(1, 9, 0)
case VA_FILTER_INTERPOLATION_NEAREST_NEIGHBOR:
decProcessingParams->m_scalingMode = CODECHAL_SCALING_NEAREST;
break;
case VA_FILTER_INTERPOLATION_BILINEAR:
decProcessingParams->m_scalingMode = CODECHAL_SCALING_BILINEAR;
break;
case VA_FILTER_INTERPOLATION_ADVANCED:
case VA_FILTER_INTERPOLATION_DEFAULT:
#endif
default:
decProcessingParams->m_scalingMode = CODECHAL_SCALING_AVS;
break;
}
// Chroma siting
// Set the vertical chroma siting info
uint32_t chromaSitingFlags = 0;
chromaSitingFlags = procBuf->input_color_properties.chroma_sample_location & 0x3;
decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
decProcessingParams->m_rotationState = 0;
decProcessingParams->m_blendState = 0;
decProcessingParams->m_mirrorState = 0;
switch (chromaSitingFlags)
{
case VA_CHROMA_SITING_VERTICAL_TOP:
decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_TOP;
break;
case VA_CHROMA_SITING_VERTICAL_CENTER:
decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_CENTER;
break;
case VA_CHROMA_SITING_VERTICAL_BOTTOM:
decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_BOTTOM;
break;
default:
decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
break;
}
if (decProcessingParams->m_chromaSitingType != CODECHAL_CHROMA_SITING_NONE)
{
// Set the horizontal chroma siting info
chromaSitingFlags = procBuf->input_color_properties.chroma_sample_location & 0xc;
switch (chromaSitingFlags)
{
case VA_CHROMA_SITING_HORIZONTAL_LEFT:
decProcessingParams->m_chromaSitingType |= CODECHAL_CHROMA_SITING_HORZ_LEFT;
break;
case VA_CHROMA_SITING_HORIZONTAL_CENTER:
decProcessingParams->m_chromaSitingType |= CODECHAL_CHROMA_SITING_HORZ_CENTER;
break;
default:
decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
break;
}
}
}
return VA_STATUS_SUCCESS;
#else
return VA_STATUS_ERROR_INVALID_PARAMETER;
#endif
}
VAStatus DdiMediaDecode::BeginPicture(
VADriverContextP ctx,
VAContextID context,
VASurfaceID renderTarget)
{
DDI_FUNCTION_ENTER();
PDDI_MEDIA_CONTEXT mediaCtx;
/* As it is already checked in the upper caller, skip the check */
mediaCtx = DdiMedia_GetMediaContext(ctx);
#ifdef _DECODE_PROCESSING_SUPPORTED
//renderTarget is decode output surface; set renderTarget as vp sfc input surface m_procBuf->surface = rederTarget
if(m_procBuf)
{
m_procBuf->surface = renderTarget;
}
#endif
DDI_MEDIA_SURFACE *curRT;
curRT = (DDI_MEDIA_SURFACE *)DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, renderTarget);
DDI_CHK_NULL(curRT, "nullptr pCurRT", VA_STATUS_ERROR_INVALID_SURFACE);
curRT->pDecCtx = m_ddiDecodeCtx;
DDI_CODEC_RENDER_TARGET_TABLE *RTtbl;
RTtbl = &(m_ddiDecodeCtx->RTtbl);
RTtbl->pCurrentRT = curRT;
m_streamOutEnabled = false;
m_ddiDecodeCtx->DecodeParams.m_numSlices = 0;
m_ddiDecodeCtx->DecodeParams.m_dataSize = 0;
m_ddiDecodeCtx->DecodeParams.m_dataOffset = 0;
m_ddiDecodeCtx->DecodeParams.m_deblockDataSize = 0;
m_ddiDecodeCtx->DecodeParams.m_executeCallIndex = 0;
m_ddiDecodeCtx->DecodeParams.m_cencBuf = nullptr;
m_groupIndex = 0;
// register render targets
DDI_CHK_RET(RegisterRTSurfaces(&m_ddiDecodeCtx->RTtbl, curRT),"RegisterRTSurfaces failed!");
if (nullptr == m_ddiDecodeCtx->pCodecHal)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
MOS_STATUS eStatus = m_ddiDecodeCtx->pCodecHal->BeginFrame();
if (eStatus != MOS_STATUS_SUCCESS)
{
return VA_STATUS_ERROR_DECODING_ERROR;
}
DDI_FUNCTION_EXIT(VA_STATUS_SUCCESS);
return VA_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::DecodeCombineBitstream(DDI_MEDIA_CONTEXT *mediaCtx)
{
DDI_CODEC_COM_BUFFER_MGR *bufMgr;
/* As it is checked in previous caller, it is skipped. */
bufMgr = &(m_ddiDecodeCtx->BufMgr);
if (bufMgr && (bufMgr->bIsSliceOverSize == false))
{
return VA_STATUS_SUCCESS;
}
PDDI_MEDIA_BUFFER newBitstreamBuffer;
//allocate a new bit stream buffer
newBitstreamBuffer = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
if (newBitstreamBuffer == nullptr)
{
DDI_ASSERTMESSAGE("DDI:AllocAndZeroMem return failure.");
return VA_STATUS_ERROR_DECODING_ERROR;
}
newBitstreamBuffer->iSize = m_ddiDecodeCtx->DecodeParams.m_dataSize;
newBitstreamBuffer->uiType = VASliceDataBufferType;
newBitstreamBuffer->format = Media_Format_Buffer;
newBitstreamBuffer->uiOffset = 0;
newBitstreamBuffer->pMediaCtx = mediaCtx;
VAStatus vaStatus;
vaStatus = DdiMediaUtil_CreateBuffer(newBitstreamBuffer,
mediaCtx->pDrmBufMgr);
if (vaStatus != VA_STATUS_SUCCESS)
{
MOS_FreeMemory(newBitstreamBuffer);
newBitstreamBuffer = nullptr;
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
uint8_t *newBitStreamBase;
newBitStreamBase = (uint8_t *)DdiMediaUtil_LockBuffer(newBitstreamBuffer, MOS_LOCKFLAG_WRITEONLY);
if (newBitStreamBase == nullptr)
{
DdiMediaUtil_FreeBuffer(newBitstreamBuffer);
MOS_FreeMemory(newBitstreamBuffer);
newBitstreamBuffer = nullptr;
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
uint32_t slcInd;
//copy data to new bit stream
for (slcInd = 0; slcInd < bufMgr->dwNumSliceData; slcInd++)
{
if (bufMgr->pSliceData[slcInd].bIsUseExtBuf == true)
{
if (bufMgr->pSliceData[slcInd].pSliceBuf)
{
MOS_SecureMemcpy(newBitStreamBase + bufMgr->pSliceData[slcInd].uiOffset,
bufMgr->pSliceData[slcInd].uiLength,
bufMgr->pSliceData[slcInd].pSliceBuf,
bufMgr->pSliceData[slcInd].uiLength);
MOS_FreeMemory(bufMgr->pSliceData[slcInd].pSliceBuf);
bufMgr->pSliceData[slcInd].pSliceBuf = nullptr;
bufMgr->pSliceData[slcInd].bIsUseExtBuf = false;
}
}
else
{
MOS_SecureMemcpy(newBitStreamBase + bufMgr->pSliceData[slcInd].uiOffset,
bufMgr->pSliceData[slcInd].uiLength,
bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] + bufMgr->pSliceData[slcInd].uiOffset,
bufMgr->pSliceData[slcInd].uiLength);
}
}
//free original buffers
if (bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex])
{
DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = nullptr;
}
if (bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex])
{
DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
MOS_FreeMemory(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex] = nullptr;
}
//set new bitstream buffer
bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex] = newBitstreamBuffer;
bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = newBitStreamBase;
DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[bufMgr->dwBitstreamIndex], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
return VA_STATUS_SUCCESS;
}
void DdiMediaDecode::DestroyContext(VADriverContextP ctx)
{
Codechal *codecHal;
/* as they are already checked in caller, this is skipped */
codecHal = m_ddiDecodeCtx->pCodecHal;
if (codecHal != nullptr)
{
if (codecHal->GetOsInterface() && codecHal->GetOsInterface()->pOsContext)
{
MOS_FreeMemory(codecHal->GetOsInterface()->pOsContext->pPerfData);
codecHal->GetOsInterface()->pOsContext->pPerfData = nullptr;
}
// destroy codechal
codecHal->Destroy();
MOS_Delete(codecHal);
m_ddiDecodeCtx->pCodecHal = nullptr;
}
int32_t i;
for (i = 0; i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT; i++)
{
if ((m_ddiDecodeCtx->RTtbl.pRT[i] != nullptr) &&
(m_ddiDecodeCtx->RTtbl.pRT[i]->pDecCtx == m_ddiDecodeCtx))
{
m_ddiDecodeCtx->RTtbl.pRT[i]->pDecCtx = nullptr;
}
}
if (m_ddiDecodeCtx->pCpDdiInterface)
{
Delete_DdiCpInterface(m_ddiDecodeCtx->pCpDdiInterface);
m_ddiDecodeCtx->pCpDdiInterface = nullptr;
}
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_huffmanTable);
m_ddiDecodeCtx->DecodeParams.m_huffmanTable = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_extPicParams);
m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_advPicParams);
m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_extSliceParams);
m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_subsetParams);
m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
#ifdef _DECODE_PROCESSING_SUPPORTED
if (m_ddiDecodeCtx->DecodeParams.m_procParams != nullptr)
{
auto procParams =
(DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams;
MOS_FreeMemory(procParams->m_outputSurface);
procParams->m_outputSurface = nullptr;
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_procParams);
m_ddiDecodeCtx->DecodeParams.m_procParams = nullptr;
}
#endif
return;
}
int32_t DdiMediaDecode::GetBitstreamBufIndexFromBuffer(DDI_CODEC_COM_BUFFER_MGR *bufMgr, DDI_MEDIA_BUFFER *buf)
{
int32_t i;
for(i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
{
if(bufMgr->pBitStreamBuffObject[i]->bo == buf->bo)
{
return i;
}
}
return DDI_CODEC_INVALID_BUFFER_INDEX;
}
VAStatus DdiMediaDecode::AllocBsBuffer(
DDI_CODEC_COM_BUFFER_MGR *bufMgr,
DDI_MEDIA_BUFFER *buf)
{
uint32_t index, i;
VAStatus vaStatus;
uint8_t *sliceBuf;
DDI_MEDIA_BUFFER *bsBufObj = nullptr;
uint8_t *bsBufBaseAddr = nullptr;
bool createBsBuffer = false;
if ( nullptr == bufMgr || nullptr == buf || nullptr == (m_ddiDecodeCtx->pMediaCtx) )
{
DDI_ASSERTMESSAGE("invalidate input parameters.");
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
index = bufMgr->dwNumSliceData;
vaStatus = VA_STATUS_SUCCESS;
sliceBuf = nullptr;
/* the pSliceData needs to be reallocated in order to contain more SliceDataBuf */
if (index >= bufMgr->m_maxNumSliceData)
{
/* In theroy it can resize the m_maxNumSliceData one by one. But in order to
* avoid calling realloc frequently, it will try to allocate 10 to hold more
* SliceDataBuf. This is only for the optimized purpose.
*/
int32_t reallocSize = bufMgr->m_maxNumSliceData + 10;
bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)realloc(bufMgr->pSliceData, sizeof(bufMgr->pSliceData[0]) * reallocSize);
if (bufMgr->pSliceData == nullptr)
{
DDI_ASSERTMESSAGE("fail to reallocate pSliceData\n.");
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
memset(bufMgr->pSliceData + bufMgr->m_maxNumSliceData, 0,
sizeof(bufMgr->pSliceData[0]) * 10);
bufMgr->m_maxNumSliceData += 10;
}
if(index >= 1)
{
buf->uiOffset = bufMgr->pSliceData[index-1].uiOffset + bufMgr->pSliceData[index-1].uiLength;
if((buf->uiOffset + buf->iSize) > bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->iSize)
{
sliceBuf = (uint8_t*)MOS_AllocAndZeroMemory(buf->iSize);
if(sliceBuf == nullptr)
{
DDI_ASSERTMESSAGE("DDI:AllocAndZeroMem return failure.")
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
bufMgr->bIsSliceOverSize = true;
}
else
{
bufMgr->bIsSliceOverSize = false;
}
}
else
{
bufMgr->bIsSliceOverSize = false;
for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
{
if (bufMgr->pBitStreamBuffObject[i]->bo != nullptr)
{
if (!mos_bo_busy(bufMgr->pBitStreamBuffObject[i]->bo))
{
//find a bitstream buffer whoes graphic memory is allocated but not used by HW now.
break;
}
}
else
{
//find a new bitstream buffer whoes graphic memory is not allocated yet
break;
}
}
if (i == DDI_CODEC_MAX_BITSTREAM_BUFFER)
{
//find the oldest bistream buffer which is the most possible one to become free in the shortest time.
bufMgr->dwBitstreamIndex = (bufMgr->ui64BitstreamOrder >> (DDI_CODEC_BITSTREAM_BUFFER_INDEX_BITS * DDI_CODEC_MAX_BITSTREAM_BUFFER_MINUS1)) & DDI_CODEC_MAX_BITSTREAM_BUFFER_INDEX;
// wait until decode complete
mos_bo_wait_rendering(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->bo);
}
else
{
bufMgr->dwBitstreamIndex = i;
}
bufMgr->ui64BitstreamOrder = (bufMgr->ui64BitstreamOrder << 4) + bufMgr->dwBitstreamIndex;
bsBufObj = bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex];
bsBufObj ->pMediaCtx = m_ddiDecodeCtx->pMediaCtx;
bsBufBaseAddr = bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex];
if(bsBufBaseAddr == nullptr)
{
createBsBuffer = true;
if (buf->iSize > bsBufObj->iSize)
{
bsBufObj->iSize = buf->iSize;
}
}
else if(buf->iSize > bsBufObj->iSize)
{
//free bo
DdiMediaUtil_UnlockBuffer(bsBufObj);
DdiMediaUtil_FreeBuffer(bsBufObj);
bsBufBaseAddr = nullptr;
createBsBuffer = true;
bsBufObj->iSize = buf->iSize;
}
if (createBsBuffer)
{
if(VA_STATUS_SUCCESS != DdiMediaUtil_CreateBuffer(bsBufObj, m_ddiDecodeCtx->pMediaCtx->pDrmBufMgr))
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
bsBufBaseAddr = (uint8_t*)DdiMediaUtil_LockBuffer(bsBufObj, MOS_LOCKFLAG_WRITEONLY);
if(bsBufBaseAddr == nullptr)
{
DdiMediaUtil_FreeBuffer(bsBufObj);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = bsBufBaseAddr;
}
}
if(bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] == nullptr)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
bufMgr->pSliceData[index].uiLength = buf->iSize;
bufMgr->pSliceData[index].uiOffset = buf->uiOffset;
if(bufMgr->bIsSliceOverSize == true)
{
buf->pData = sliceBuf;
buf->uiOffset = 0;
bufMgr->pSliceData[index].bIsUseExtBuf = true;
bufMgr->pSliceData[index].pSliceBuf = sliceBuf;
buf->bCFlushReq = false;
}
else
{
buf->pData = (uint8_t*)(bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex]);
bufMgr->pSliceData[index].bIsUseExtBuf = false;
bufMgr->pSliceData[index].pSliceBuf = nullptr;
buf->bCFlushReq = true;
}
bufMgr->dwNumSliceData ++;
buf->bo = bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->bo;
return VA_STATUS_SUCCESS;
}
MOS_FORMAT DdiMediaDecode::GetFormat()
{
return Format_NV12;
}
VAStatus DdiMediaDecode::InitDecodeParams(
VADriverContextP ctx,
VAContextID context)
{
/* skip the mediaCtx check as it is checked in caller */
PDDI_MEDIA_CONTEXT mediaCtx;
mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_RET(DecodeCombineBitstream(mediaCtx),"DecodeCombineBitstream failed!");
DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
bufMgr->dwNumSliceData = 0;
bufMgr->dwNumSliceControl = 0;
memset(&m_destSurface, 0, sizeof(MOS_SURFACE));
m_destSurface.dwOffset = 0;
DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_ddiDecodeCtx->RTtbl);
if ((rtTbl == nullptr) || (rtTbl->pCurrentRT == nullptr))
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::SetDecodeParams()
{
DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
if ((&m_ddiDecodeCtx->DecodeParams)->m_numSlices == 0)
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
MOS_FORMAT expectedFormat = GetFormat();
m_destSurface.Format = expectedFormat;
DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pCurrentRT, &(m_destSurface.OsResource));
if (m_destSurface.OsResource.Format != expectedFormat)
{
DDI_NORMALMESSAGE("Surface fomrat of decoded surface is inconsistent with Codec bitstream\n");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
m_ddiDecodeCtx->DecodeParams.m_destSurface = &m_destSurface;
m_ddiDecodeCtx->DecodeParams.m_deblockSurface = nullptr;
m_ddiDecodeCtx->DecodeParams.m_dataBuffer = &bufMgr->resBitstreamBuffer;
m_ddiDecodeCtx->DecodeParams.m_bitStreamBufData = bufMgr->pBitstreamBuffer;
m_ddiDecodeCtx->DecodeParams.m_bitplaneBuffer = nullptr;
if (m_streamOutEnabled)
{
m_ddiDecodeCtx->DecodeParams.m_streamOutEnabled = true;
m_ddiDecodeCtx->DecodeParams.m_externalStreamOutBuffer = &bufMgr->resExternalStreamOutBuffer;
}
else
{
m_ddiDecodeCtx->DecodeParams.m_streamOutEnabled = false;
m_ddiDecodeCtx->DecodeParams.m_externalStreamOutBuffer = nullptr;
}
if (m_ddiDecodeCtx->pCpDdiInterface)
{
DDI_CHK_RET(m_ddiDecodeCtx->pCpDdiInterface->SetDecodeParams(m_ddiDecodeCtx, m_codechalSettings),"SetDecodeParams failed!");
}
Mos_Solo_OverrideBufferSize(m_ddiDecodeCtx->DecodeParams.m_dataSize, m_ddiDecodeCtx->DecodeParams.m_dataBuffer);
return VA_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::ExtraDownScaling(
VADriverContextP ctx,
VAContextID context)
{
#ifdef _DECODE_PROCESSING_SUPPORTED
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
VAStatus vaStatus = MOS_STATUS_SUCCESS;
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(m_ddiDecodeCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
bool isDecodeDownScalingSupported = false;
if (m_ddiDecodeCtx->pCodecHal->IsApogeiosEnabled())
{
DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(m_ddiDecodeCtx->pCodecHal);
DDI_CHK_NULL(decoder, "nullptr decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
isDecodeDownScalingSupported = decoder->IsDownSamplingSupported();
}
else
{
CodechalDecode *decoder = dynamic_cast<CodechalDecode *>(m_ddiDecodeCtx->pCodecHal);
DDI_CHK_NULL(decoder, "nullptr decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
isDecodeDownScalingSupported = decoder->IsVdSfcSupported();
}
if(m_ddiDecodeCtx->DecodeParams.m_procParams != nullptr &&
m_procBuf &&
!isDecodeDownScalingSupported)
{
//check vp context
VAContextID vpCtxID = VA_INVALID_ID;
if (mediaCtx->pVpCtxHeap != nullptr && mediaCtx->pVpCtxHeap->pHeapBase != nullptr)
{
//Get VP Context from heap.
vpCtxID = (VAContextID)(0 + DDI_MEDIA_VACONTEXTID_OFFSET_VP);
}
else
{
//Create VP Context.
vaStatus = DdiVp_CreateContext(ctx, 0, 0, 0, 0, 0, 0, &vpCtxID);
DDI_CHK_RET(vaStatus, "Create VP Context failed.");
}
uint32_t ctxType;
PDDI_VP_CONTEXT pVpCtx = (PDDI_VP_CONTEXT)DdiMedia_GetContextFromContextID(ctx, vpCtxID, &ctxType);
DDI_CHK_NULL(pVpCtx, "nullptr pVpCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
//Set parameters
VAProcPipelineParameterBuffer* pInputPipelineParam = m_procBuf;
DDI_CHK_NULL(pInputPipelineParam, "nullptr pInputPipelineParam", VA_STATUS_ERROR_ALLOCATION_FAILED);
vaStatus = DdiVp_BeginPicture(ctx, vpCtxID, pInputPipelineParam->additional_outputs[0]);
DDI_CHK_RET(vaStatus, "VP BeginPicture failed");
vaStatus = DdiVp_SetProcPipelineParams(ctx, pVpCtx, pInputPipelineParam);
DDI_CHK_RET(vaStatus, "VP SetProcPipelineParams failed.");
vaStatus = DdiVp_EndPicture(ctx, vpCtxID);
DDI_CHK_RET(vaStatus, "VP EndPicture failed.");
}
#endif
return MOS_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::InitDummyReference(CodechalDecode& decoder)
{
PMOS_SURFACE dummyReference = decoder.GetDummyReference();
// If dummy reference is from decode output surface, need to update frame by frame
if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_DEST_SURFACE)
{
MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
}
if (!Mos_ResourceIsNull(&dummyReference->OsResource))
{
Mos_Specific_GetResourceInfo(decoder.GetOsInterface(), &dummyReference->OsResource, dummyReference);
// Check if need to re-get dummy reference from DPB or re-allocated
if (dummyReference->dwWidth < m_ddiDecodeCtx->DecodeParams.m_destSurface->dwWidth ||
dummyReference->dwHeight < m_ddiDecodeCtx->DecodeParams.m_destSurface->dwHeight)
{
// Check if the dummy reference needs to be re-allocated
if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_ALLOCATED)
{
decoder.GetOsInterface()->pfnFreeResource(decoder.GetOsInterface(), &dummyReference->OsResource);
}
// Reset dummy reference
MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
// Considering potential risk, disable the dummy reference from DPB path temporarily
//GetDummyReferenceFromDPB(m_ddiDecodeCtx);
//if (!Mos_ResourceIsNull(&dummyReference->OsResource))
//{
// decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
//}
}
}
else
{
// Init dummy reference
MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
// Considering potential risk, disable the dummy reference from DPB path temporarily
//GetDummyReferenceFromDPB(m_ddiDecodeCtx);
//if (!Mos_ResourceIsNull(&dummyReference->OsResource))
//{
// decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
//}
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::InitDummyReference(DecodePipelineAdapter& decoder)
{
PMOS_SURFACE dummyReference = decoder.GetDummyReference();
// If dummy reference is from decode output surface, need to update frame by frame
if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_DEST_SURFACE)
{
MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
}
if (!Mos_ResourceIsNull(&dummyReference->OsResource))
{
Mos_Specific_GetResourceInfo(decoder.GetOsInterface(), &dummyReference->OsResource, dummyReference);
// Check if need to re-get dummy reference from DPB or re-allocated
if (dummyReference->dwWidth < m_ddiDecodeCtx->DecodeParams.m_destSurface->dwWidth ||
dummyReference->dwHeight < m_ddiDecodeCtx->DecodeParams.m_destSurface->dwHeight)
{
// Check if the dummy reference needs to be re-allocated
if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_ALLOCATED)
{
decoder.GetOsInterface()->pfnFreeResource(decoder.GetOsInterface(), &dummyReference->OsResource);
}
// Reset dummy reference
MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
// Considering potential risk, disable the dummy reference from DPB path temporarily
//GetDummyReferenceFromDPB(m_ddiDecodeCtx);
//if (!Mos_ResourceIsNull(&dummyReference->OsResource))
//{
// decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
//}
}
}
else
{
// Init dummy reference
MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
// Considering potential risk, disable the dummy reference from DPB path temporarily
//GetDummyReferenceFromDPB(m_ddiDecodeCtx);
//if (!Mos_ResourceIsNull(&dummyReference->OsResource))
//{
// decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
//}
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::EndPicture(
VADriverContextP ctx,
VAContextID context)
{
DDI_FUNCTION_ENTER();
if (m_ddiDecodeCtx->bDecodeModeReported == false)
{
ReportDecodeMode(m_ddiDecodeCtx->wMode);
m_ddiDecodeCtx->bDecodeModeReported = true;
}
DDI_CHK_RET(InitDecodeParams(ctx,context),"InitDecodeParams failed!");
DDI_CHK_RET(SetDecodeParams(), "SetDecodeParams failed!");
DDI_CHK_RET(ClearRefList(&(m_ddiDecodeCtx->RTtbl), m_withDpb), "ClearRefList failed!");
if (m_ddiDecodeCtx->pCodecHal == nullptr)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
if (MEDIA_IS_WA(&m_ddiDecodeCtx->pMediaCtx->WaTable, WaDummyReference))
{
Mos_Specific_GetResourceInfo(
m_ddiDecodeCtx->pCodecHal->GetOsInterface(),
&m_ddiDecodeCtx->DecodeParams.m_destSurface->OsResource,
m_ddiDecodeCtx->DecodeParams.m_destSurface);
if(m_ddiDecodeCtx->pCodecHal->IsApogeiosEnabled())
{
DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(m_ddiDecodeCtx->pCodecHal);
DDI_CHK_NULL(decoder, "Null decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_RET(InitDummyReference(*decoder), "InitDummyReference failed!");
}
else
{
CodechalDecode *decoder = dynamic_cast<CodechalDecode *>(m_ddiDecodeCtx->pCodecHal);
DDI_CHK_NULL(decoder, "Null decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_RET(InitDummyReference(*decoder), "InitDummyReference failed!");
}
}
MOS_STATUS status = m_ddiDecodeCtx->pCodecHal->Execute((void *)(&m_ddiDecodeCtx->DecodeParams));
if (status != MOS_STATUS_SUCCESS)
{
DDI_ASSERTMESSAGE("DDI:DdiDecode_DecodeInCodecHal return failure.");
return VA_STATUS_ERROR_DECODING_ERROR;
}
m_ddiDecodeCtx->DecodeParams.m_executeCallIndex++;
(&(m_ddiDecodeCtx->RTtbl))->pCurrentRT = nullptr;
status = m_ddiDecodeCtx->pCodecHal->EndFrame();
if (status != MOS_STATUS_SUCCESS)
{
return VA_STATUS_ERROR_DECODING_ERROR;
}
#ifdef _DECODE_PROCESSING_SUPPORTED
if (ExtraDownScaling(ctx,context) != VA_STATUS_SUCCESS)
{
return VA_STATUS_ERROR_DECODING_ERROR;
}
#endif
DDI_FUNCTION_EXIT(VA_STATUS_SUCCESS);
return VA_STATUS_SUCCESS;
}
VAStatus DdiMediaDecode::CreateBuffer(
VABufferType type,
uint32_t size,
uint32_t numElements,
void *data,
VABufferID *bufId)
{
DDI_MEDIA_BUFFER *buf;
PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufferHeapElement;
uint16_t segMapWidth, segMapHeight;
MOS_STATUS status = MOS_STATUS_SUCCESS;
VAStatus va = VA_STATUS_SUCCESS;
segMapWidth = m_picWidthInMB;
segMapHeight= m_picHeightInMB;
// only for VASliceParameterBufferType of buffer, the number of elements can be greater than 1
if(type != VASliceParameterBufferType && numElements > 1)
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
buf = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
if (buf == nullptr)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
buf->iSize = size * numElements;
buf->uiNumElements = numElements;
buf->uiType = type;
buf->format = Media_Format_Buffer;
buf->uiOffset = 0;
buf->bCFlushReq = false;
buf->pMediaCtx = m_ddiDecodeCtx->pMediaCtx;
switch ((int32_t)type)
{
case VABitPlaneBufferType:
buf->pData = (uint8_t*)((m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pBitPlaneBuffer));
break;
case VASliceDataBufferType:
case VAProtectedSliceDataBufferType:
va = AllocBsBuffer(&(m_ddiDecodeCtx->BufMgr), buf);
if(va != VA_STATUS_SUCCESS)
{
goto CleanUpandReturn;
}
break;
case VASliceParameterBufferType:
va = AllocSliceControlBuffer(buf);
if(va != VA_STATUS_SUCCESS)
{
goto CleanUpandReturn;
}
buf->format = Media_Format_CPU;
break;
case VAPictureParameterBufferType:
buf->pData = GetPicParamBuf(&(m_ddiDecodeCtx->BufMgr));
buf->format = Media_Format_CPU;
break;
case VASubsetsParameterBufferType:
//maximum entry point supported should not be more than 440
if(numElements > 440)
{
va = VA_STATUS_ERROR_INVALID_PARAMETER;
goto CleanUpandReturn;
}
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
buf->format = Media_Format_CPU;
break;
case VAIQMatrixBufferType:
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
buf->format = Media_Format_CPU;
break;
case VAProbabilityBufferType:
buf->pData = (uint8_t*)(&(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.ProbabilityDataVP8));
break;
case VAProcFilterParameterBufferType:
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineCaps));
buf->format = Media_Format_CPU;
break;
case VAProcPipelineParameterBufferType:
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineParameterBuffer));
buf->format = Media_Format_CPU;
break;
case VADecodeStreamoutBufferType:
{
segMapHeight = ((segMapHeight + 1) >> 1); //uiSize must be equal and bigger than size for interlaced case
if (size < MOS_ALIGN_CEIL(segMapHeight * segMapWidth * CODEC_SIZE_MFX_STREAMOUT_DATA, 64))
{
va = VA_STATUS_ERROR_INVALID_PARAMETER;
goto CleanUpandReturn;
}
buf->iSize = size * numElements;
buf->format = Media_Format_Buffer;
va = DdiMediaUtil_CreateBuffer(buf, m_ddiDecodeCtx->pMediaCtx->pDrmBufMgr);
if(va != VA_STATUS_SUCCESS)
{
goto CleanUpandReturn;
}
break;
}
case VAHuffmanTableBufferType:
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
buf->format = Media_Format_CPU;
break;
#if VA_CHECK_VERSION(1, 10, 0)
case VAContextParameterUpdateBufferType:
{
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
buf->format = Media_Format_CPU;
break;
}
#endif
default:
va = m_ddiDecodeCtx->pCpDdiInterface->CreateBuffer(type, buf, size, numElements);
if (va == VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE)
{
DDI_ASSERTMESSAGE("DDI:Decode CreateBuffer unsuppoted buffer type.");
buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
buf->format = Media_Format_CPU;
if(buf->pData != NULL)
{
va = VA_STATUS_SUCCESS;
}
}
break;
}
bufferHeapElement = DdiMediaUtil_AllocPMediaBufferFromHeap(m_ddiDecodeCtx->pMediaCtx->pBufferHeap);
if (nullptr == bufferHeapElement)
{
va = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
goto CleanUpandReturn;
}
bufferHeapElement->pBuffer = buf;
bufferHeapElement->pCtx = (void*)m_ddiDecodeCtx;
bufferHeapElement->uiCtxType = DDI_MEDIA_CONTEXT_TYPE_DECODER;
*bufId = bufferHeapElement->uiVaBufferID;
// Keep record the VaBufferID of JPEG slice data buffer we allocated, in order to do buffer mapping when render this buffer. otherwise we
// can not get correct buffer address when application create them disordered.
if (type == VASliceDataBufferType && m_ddiDecodeCtx->wMode == CODECHAL_DECODE_MODE_JPEG)
{
// since the dwNumSliceData already +1 when allocate buffer, but here we need to track the VaBufferID before dwSliceData increased.
m_ddiDecodeCtx->BufMgr.pSliceData[m_ddiDecodeCtx->BufMgr.dwNumSliceData - 1].vaBufferId = *bufId;
}
m_ddiDecodeCtx->pMediaCtx->uiNumBufs++;
if(data == nullptr)
{
return va;
}
if( true == buf->bCFlushReq )
{
mos_bo_subdata(buf->bo, buf->uiOffset, size * numElements, data);
}
else
{
status = MOS_SecureMemcpy((void *)(buf->pData + buf->uiOffset), size * numElements, data, size * numElements);
DDI_CHK_CONDITION((status != MOS_STATUS_SUCCESS), "DDI:Failed to copy buffer data!", VA_STATUS_ERROR_OPERATION_FAILED);
}
return va;
CleanUpandReturn:
if(buf)
{
MOS_FreeMemory(buf->pData);
MOS_FreeMemory(buf);
}
return va;
}
void DdiMediaDecode::ContextInit(
int32_t picWidth,
int32_t picHeight)
{
m_width = picWidth;
m_height = picHeight;
m_picWidthInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_WIDTH(picWidth));
m_picHeightInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_HEIGHT(picHeight));
m_ddiDecodeCtx->wMode = CODECHAL_DECODE_MODE_AVCVLD;
m_ddiDecodeCtx->bShortFormatInUse = false;
#ifdef _DECODE_PROCESSING_SUPPORTED
if (m_ddiDecodeAttr->uiDecProcessingType == VA_DEC_PROCESSING)
{
DDI_NORMALMESSAGE("Decoding context has scaling/format conversion capabilities");
m_decProcessingType = VA_DEC_PROCESSING;
}
else
#endif
{
DDI_NORMALMESSAGE("Decoding context DOESN'T have scaling/format conversion capabilities");
m_decProcessingType = VA_DEC_PROCESSING_NONE;
}
m_streamOutEnabled = false;
m_ddiDecodeCtx->DecodeParams.m_picIdRemappingInUse = true;
}
VAStatus DdiMediaDecode::CreateCodecHal(
DDI_MEDIA_CONTEXT *mediaCtx,
void *ptr,
_CODECHAL_STANDARD_INFO *standardInfo)
{
if ((mediaCtx == nullptr) ||
(ptr == nullptr) ||
(m_codechalSettings == nullptr) ||
(standardInfo == nullptr))
{
DDI_ASSERTMESSAGE("NULL pointer is passed for CreateCodecHal.\n");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr;
VAStatus vaStatus = VA_STATUS_SUCCESS;
Codechal *codecHal = CodechalDevice::CreateFactory(
nullptr,
mosCtx,
standardInfo,
m_codechalSettings);
if (nullptr == codecHal)
{
DDI_ASSERTMESSAGE("Failure in CodecHal create.\n");
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
if (codecHal->IsApogeiosEnabled())
{
DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(codecHal);
if (nullptr == decoder)
{
DDI_ASSERTMESSAGE("Failure in CodecHal create.\n");
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
}
else
{
CodechalDecode *decoder = dynamic_cast<CodechalDecode *>(codecHal);
if (nullptr == decoder)
{
DDI_ASSERTMESSAGE("Failure in CodecHal create.\n");
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
}
m_ddiDecodeCtx->pCodecHal = codecHal;
m_codechalSettings->sfcInUseHinted = true;
if (m_ddiDecodeAttr && m_ddiDecodeAttr->uiEncryptionType)
{
m_codechalSettings->secureMode = true;
}
if (codecHal->Allocate(m_codechalSettings) != MOS_STATUS_SUCCESS)
{
DDI_ASSERTMESSAGE("Failure in decode allocate.\n");
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
PMOS_INTERFACE osInterface = codecHal->GetOsInterface();
if (osInterface == nullptr)
{
DDI_ASSERTMESSAGE("Failure in decode allocate.\n");
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
#ifdef _MMC_SUPPORTED
if (!osInterface->apoMosEnabled &&
MEDIA_IS_SKU(osInterface->pfnGetSkuTable(osInterface), FtrMemoryCompression) &&
!mediaCtx->pMediaMemDecompState)
{
mediaCtx->pMediaMemDecompState =
static_cast<MediaMemDecompState *>(MmdDevice::CreateFactory(mosCtx));
}
#endif
m_ddiDecodeCtx->pCpDdiInterface->CreateCencDecode(codecHal->GetDebugInterface(), mosCtx, m_codechalSettings);
return vaStatus;
}
void DdiMediaDecode::GetDummyReferenceFromDPB(
DDI_DECODE_CONTEXT *decodeCtx)
{
MOS_SURFACE *destSurface = decodeCtx->DecodeParams.m_destSurface;
MOS_SURFACE dummyReference;
MOS_STATUS eStatus;
uint32_t i;
if (destSurface == nullptr)
{
DDI_ASSERTMESSAGE("Decode output surface is NULL.\n");
return;
}
for (i = 0; i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT; i++)
{
if (decodeCtx->RTtbl.pRT[i] != nullptr &&
decodeCtx->RTtbl.pRT[i] != decodeCtx->RTtbl.pCurrentRT)
{
MOS_ZeroMemory(&dummyReference, sizeof(MOS_SURFACE));
DdiMedia_MediaSurfaceToMosResource(decodeCtx->RTtbl.pRT[i], &(dummyReference.OsResource));
if (!Mos_ResourceIsNull(&dummyReference.OsResource))
{
eStatus = MOS_STATUS_SUCCESS;
dummyReference.Format = Format_Invalid;
eStatus = Mos_Specific_GetResourceInfo(decodeCtx->pCodecHal->GetOsInterface(), &dummyReference.OsResource, &dummyReference);
if (eStatus != MOS_STATUS_SUCCESS)
{
continue;
}
if (dummyReference.Type == destSurface->Type &&
dummyReference.Format == destSurface->Format &&
dummyReference.bIsCompressed == destSurface->bIsCompressed &&
dummyReference.CompressionMode == destSurface->CompressionMode &&
dummyReference.TileType == destSurface->TileType &&
dummyReference.dwPitch >= destSurface->dwPitch &&
dummyReference.dwWidth >= destSurface->dwWidth &&
dummyReference.dwHeight >= destSurface->dwHeight)
{
break;
}
}
}
}
if (i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT)
{
if (decodeCtx->pCodecHal->IsApogeiosEnabled())
{
DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(decodeCtx->pCodecHal);
if (decoder == nullptr)
{
DDI_ASSERTMESSAGE("Codechal decode context is NULL.\n");
return;
}
decoder->GetDummyReference()->OsResource = dummyReference.OsResource;
}
else
{
CodechalDecode *decoder = dynamic_cast<CodechalDecode *>(decodeCtx->pCodecHal);
if (decoder == nullptr)
{
DDI_ASSERTMESSAGE("Codechal decode context is NULL.\n");
return;
}
decoder->GetDummyReference()->OsResource = dummyReference.OsResource;
}
}
}
void DdiMediaDecode::ReportDecodeMode(
uint16_t wMode)
{
MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
userFeatureWriteData.Value.i32Data = wMode;
switch (wMode)
{
case CODECHAL_DECODE_MODE_MPEG2IDCT:
case CODECHAL_DECODE_MODE_MPEG2VLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_MPEG2_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_VC1IT:
case CODECHAL_DECODE_MODE_VC1VLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VC1_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_AVCVLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_AVC_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_JPEG:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_JPEG_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_VP8VLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VP8_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_HEVCVLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_HEVC_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_VP9VLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VP9_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
case CODECHAL_DECODE_MODE_AV1VLD:
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_AV1_MODE_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, nullptr);
break;
default:
break;
}
}