blob: 02c677ae2add92280d42591fc6a2e36f56d3751f [file] [log] [blame]
/*
* Copyright (c) 2015-2017, 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_vp8.cpp
//! \brief The class implementation of DdiDecodeVP8 for VP8 decode
//!
#include "media_libva_decoder.h"
#include "media_libva_util.h"
#include "media_ddi_decode_vp8.h"
#include "mos_solo_generic.h"
#include "codechal_memdecomp.h"
#include "media_ddi_decode_const.h"
#include "media_ddi_factory.h"
#define DDI_DECODE_VP8_QINDEX_RANGE 128
// Tables from the VP8 reference decoder
static const int32_t Vp8DcQlookup[DDI_DECODE_VP8_QINDEX_RANGE] =
{
4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15,
16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23,
24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46,
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
73, 74, 75, 76, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 91, 93, 95, 96, 98, 100, 101, 102,
104, 106, 108, 110, 112, 114, 116, 118, 122, 124, 126, 128, 130,
132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157,
};
static const int32_t Vp8AcQlookup[DDI_DECODE_VP8_QINDEX_RANGE] =
{
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78,
80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104,
106, 108, 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, 137,
140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 177,
181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229,
234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284,
};
// Load VP8 Slice Parameters from the libva buffer into the Codec Hal Picture Parameters buffer.
// 2 libva buffers (VASliceParameterBufferVP8 & VAPictureParameterBufferVP8) get merged into one CodecHal buffer (CODEC_VP8_PIC_PARAMS)
// Only one sliceParameterBuffer is enough for VP8.
VAStatus DdiDecodeVP8::ParseSliceParams(
DDI_MEDIA_CONTEXT *mediaCtx,
VASliceParameterBufferVP8 *slcParam)
{
PCODEC_VP8_PIC_PARAMS picParams = (PCODEC_VP8_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
if ((slcParam == nullptr) || (picParams == nullptr))
{
DDI_ASSERTMESSAGE("Invalid Parameter for Parsing VP8 Slice parameter\n");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
// num_of_partitions = (1 << CodedCoeffTokenPartition)+1, count both control partition(frame header) and token partition.
uint8_t num_token_partitions;
num_token_partitions = slcParam->num_of_partitions - 1;
picParams->CodedCoeffTokenPartition = (num_token_partitions != 8) ? (num_token_partitions >> 1) : 3;
//macroblock_offset is in unit of bit.it should be always the next byte, the byte is divided to two parts
//used bits and remaining bits, if used bits == 8, uiFirstMbByteOffset should add 1, so use 8 to do the ceil operator
picParams->uiFirstMbByteOffset = slcParam->slice_data_offset + ((slcParam->macroblock_offset + 8) >> 3);
MOS_SecureMemcpy(picParams->uiPartitionSize, sizeof(picParams->uiPartitionSize), slcParam->partition_size, sizeof(picParams->uiPartitionSize));
//partition 0 size in command buffer includes the one byte in bool decoder if remaining bits of bool decoder is zero.
picParams->uiPartitionSize[0] -= (slcParam->macroblock_offset & 0x7) ? 0 : 1;
return VA_STATUS_SUCCESS;
}
static uint16_t Vp8QuantIdx(int16_t index)
{
if (index > 127)
index = 127;
if (index < 0)
index = 0;
return index;
}
static uint16_t Vp8AcQuant(uint16_t index)
{
return Vp8AcQlookup[Vp8QuantIdx(index)];
}
static uint16_t Vp8DcQuant(uint16_t index)
{
return Vp8DcQlookup[Vp8QuantIdx(index)];
}
// Copy VP8 IQ Matrix from the libva buffer into the Codec Hal buffer. A memcpy can be used, as the buffers have the same structure.
VAStatus DdiDecodeVP8::ParseIQMatrix(
DDI_MEDIA_CONTEXT * mediaCtx,
VAIQMatrixBufferVP8 *matrix)
{
CODEC_VP8_IQ_MATRIX_PARAMS *iqParams = (CODEC_VP8_IQ_MATRIX_PARAMS *)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
if ((matrix == nullptr) || (iqParams == nullptr))
{
DDI_ASSERTMESSAGE("Invalid Parameter for Parsing VP8 IQMatrix parameter\n");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
uint32_t i;
for (i = 0; i < 4; i++)
{
iqParams->quantization_values[i][0] = Vp8DcQuant(matrix->quantization_index[i][1]);
iqParams->quantization_values[i][1] = Vp8AcQuant(matrix->quantization_index[i][0]);
iqParams->quantization_values[i][2] = Vp8DcQuant(matrix->quantization_index[i][4]);
iqParams->quantization_values[i][3] = Vp8AcQuant(matrix->quantization_index[i][5]);
iqParams->quantization_values[i][4] = 2 * Vp8DcQuant(matrix->quantization_index[i][2]);
iqParams->quantization_values[i][5] = 155 * Vp8AcQuant(matrix->quantization_index[i][3]) / 100;
if (iqParams->quantization_values[i][5] < 8)
iqParams->quantization_values[i][5] = 8;
if (iqParams->quantization_values[i][2] > 132)
iqParams->quantization_values[i][2] = 132;
}
return VA_STATUS_SUCCESS;
}
// Load VP8 Picture Parameters from the libva buffer into the Codec Hal buffer.
VAStatus DdiDecodeVP8::ParsePicParams(
DDI_MEDIA_CONTEXT *mediaCtx,
VAPictureParameterBufferVP8 *picParam)
{
PDDI_MEDIA_SURFACE lastRefSurface = nullptr;
PDDI_MEDIA_SURFACE goldenRefSurface = nullptr;
PDDI_MEDIA_SURFACE altRefSurface = nullptr;
PCODEC_VP8_PIC_PARAMS codecPicParams = (PCODEC_VP8_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
PDDI_MEDIA_SURFACE *vp8Surfaces = m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.pReferenceFrames;
PDDI_MEDIA_SURFACE currentSurface = m_ddiDecodeCtx->RTtbl.pCurrentRT;
// only no-keyframe have last/gold/alt reference frame
if (picParam->pic_fields.bits.key_frame)
{
lastRefSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->last_ref_frame);
if(lastRefSurface)
{
DdiMedia_MediaSurfaceToMosResource(lastRefSurface, &m_resNoneRegLastRefFrame);
m_ddiDecodeCtx->DecodeParams.m_presNoneRegLastRefFrame = &m_resNoneRegLastRefFrame;
}
goldenRefSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->golden_ref_frame);
if(goldenRefSurface)
{
DdiMedia_MediaSurfaceToMosResource(goldenRefSurface, &m_resNoneRegGoldenRefFrame);
m_ddiDecodeCtx->DecodeParams.m_presNoneRegGoldenRefFrame = &m_resNoneRegGoldenRefFrame;
}
altRefSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->alt_ref_frame);
if(altRefSurface)
{
DdiMedia_MediaSurfaceToMosResource(altRefSurface, &m_resNoneRegAltRefFrame);
m_ddiDecodeCtx->DecodeParams.m_presNoneRegAltRefFrame = &m_resNoneRegAltRefFrame;
}
}
int32_t frameIdx;
frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, currentSurface);
if (frameIdx == (int32_t)DDI_CODEC_INVALID_FRAME_INDEX)
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
codecPicParams->ucCurrPicIndex = frameIdx;
frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, lastRefSurface);
codecPicParams->ucLastRefPicIndex = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8 - 1) : frameIdx;
frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, goldenRefSurface);
codecPicParams->ucGoldenRefPicIndex = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8 - 1) : frameIdx;
frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, altRefSurface);
codecPicParams->ucAltRefPicIndex = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8 - 1) : frameIdx;
codecPicParams->CurrPic.FrameIdx = codecPicParams->ucCurrPicIndex;
codecPicParams->wFrameWidthInMbsMinus1 = ((picParam->frame_width + 15) / 16) - 1;
codecPicParams->wFrameHeightInMbsMinus1 = ((picParam->frame_height + 15) / 16) - 1;
codecPicParams->ucDeblockedPicIndex = codecPicParams->ucCurrPicIndex;
codecPicParams->ucReserved8Bits = 0;
codecPicParams->key_frame = (picParam->pic_fields.bits.key_frame == 0); // Yes, really.
codecPicParams->version = picParam->pic_fields.bits.version;
codecPicParams->segmentation_enabled = picParam->pic_fields.bits.segmentation_enabled;
codecPicParams->update_mb_segmentation_map = picParam->pic_fields.bits.update_mb_segmentation_map;
codecPicParams->update_segment_feature_data = picParam->pic_fields.bits.update_segment_feature_data;
codecPicParams->filter_type = picParam->pic_fields.bits.filter_type;
codecPicParams->sign_bias_golden = picParam->pic_fields.bits.sign_bias_golden;
codecPicParams->sign_bias_alternate = picParam->pic_fields.bits.sign_bias_alternate;
codecPicParams->mb_no_coeff_skip = picParam->pic_fields.bits.mb_no_coeff_skip;
codecPicParams->mode_ref_lf_delta_update = picParam->pic_fields.bits.mode_ref_lf_delta_update;
// Loop filter settings
codecPicParams->LoopFilterDisable = picParam->pic_fields.bits.loop_filter_disable;
codecPicParams->loop_filter_adj_enable = picParam->pic_fields.bits.loop_filter_adj_enable;
*((uint32_t *)codecPicParams->ucLoopFilterLevel) = *((uint32_t *)picParam->loop_filter_level);
*((uint32_t *)codecPicParams->cRefLfDelta) = *((uint32_t *)picParam->loop_filter_deltas_ref_frame);
*((uint32_t *)codecPicParams->cModeLfDelta) = *((uint32_t *)picParam->loop_filter_deltas_mode);
codecPicParams->ucSharpnessLevel = picParam->pic_fields.bits.sharpness_level;
// Probability settings
codecPicParams->cMbSegmentTreeProbs[0] = picParam->mb_segment_tree_probs[0];
codecPicParams->cMbSegmentTreeProbs[1] = picParam->mb_segment_tree_probs[1];
codecPicParams->cMbSegmentTreeProbs[2] = picParam->mb_segment_tree_probs[2];
codecPicParams->ucProbSkipFalse = picParam->prob_skip_false;
codecPicParams->ucProbIntra = picParam->prob_intra;
codecPicParams->ucProbLast = picParam->prob_last;
codecPicParams->ucProbGolden = picParam->prob_gf;
*((uint32_t *)codecPicParams->ucYModeProbs) = *((uint32_t *)picParam->y_mode_probs);
codecPicParams->ucUvModeProbs[0] = picParam->uv_mode_probs[0];
codecPicParams->ucUvModeProbs[1] = picParam->uv_mode_probs[1];
codecPicParams->ucUvModeProbs[2] = picParam->uv_mode_probs[2];
if (codecPicParams->ucMvUpdateProb[0] && picParam->mv_probs[0])
{
MOS_SecureMemcpy(codecPicParams->ucMvUpdateProb[0],
sizeof(codecPicParams->ucMvUpdateProb[0]),
picParam->mv_probs[0],
sizeof(codecPicParams->ucMvUpdateProb[0]));
}
if (codecPicParams->ucMvUpdateProb[1] && picParam->mv_probs[1])
{
MOS_SecureMemcpy(codecPicParams->ucMvUpdateProb[1],
sizeof(codecPicParams->ucMvUpdateProb[1]),
picParam->mv_probs[1],
sizeof(codecPicParams->ucMvUpdateProb[1]));
}
codecPicParams->ucP0EntropyCount = (8 - picParam->bool_coder_ctx.count) & 0x7; //hardware needs used bits not remaining bits in bool decoder
codecPicParams->ucP0EntropyValue = picParam->bool_coder_ctx.value;
codecPicParams->uiP0EntropyRange = picParam->bool_coder_ctx.range;
codecPicParams->uiStatusReportFeedbackNumber = 0;
return VA_STATUS_SUCCESS;
}
// Copy VP8ProbabilityData from the libva buffer (pBuf) into the Codec Hal buffer. A memcpy can be used, as the buffers have the same structure.
VAStatus DdiDecodeVP8::ParseProbabilityData(
struct _DDI_MEDIA_BUFFER * vp8ProbDataBuff,
VAProbabilityDataBufferVP8 *probInputBuf)
{
if (vp8ProbDataBuff->pData && probInputBuf)
{
MOS_LINUX_BO *boDes = nullptr;
boDes = vp8ProbDataBuff->bo;
mos_bo_wait_rendering(boDes);
if (0 == mos_bo_subdata(boDes,
0,
sizeof(CODECHAL_VP8_COEFFPROB_DATA),
probInputBuf))
{
return VA_STATUS_SUCCESS;
}
else
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
else
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
VAStatus DdiDecodeVP8::RenderPicture(
VADriverContextP ctx,
VAContextID context,
VABufferID *buffers,
int32_t numBuffers)
{
VAStatus va = VA_STATUS_SUCCESS;
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_FUNCTION_ENTER();
void * data = nullptr;
for (int32_t i = 0; i < numBuffers; i++)
{
if (!buffers || (buffers[i] == VA_INVALID_ID))
{
return VA_STATUS_ERROR_INVALID_BUFFER;
}
DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
if (nullptr == buf)
{
return VA_STATUS_ERROR_INVALID_BUFFER;
}
uint32_t dataSize = buf->iSize;
DdiMedia_MapBuffer(ctx, buffers[i], &data);
if (data == nullptr)
{
return VA_STATUS_ERROR_INVALID_BUFFER;
}
switch ((int32_t)buf->uiType)
{
case VASliceDataBufferType:
{
int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf);
if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
{
return VA_STATUS_ERROR_INVALID_BUFFER;
}
DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
break;
}
case VASliceParameterBufferType:
{
if (m_ddiDecodeCtx->DecodeParams.m_numSlices)
{
// VP8 only supports only one slice. If it is passed, another slice_param
// buffer will be ignored.
DDI_NORMALMESSAGE("SliceParamBufferVP8 is already rendered\n");
break;
}
if (buf->uiNumElements == 0)
{
return VA_STATUS_ERROR_INVALID_BUFFER;
}
uint32_t numSlices = buf->uiNumElements;
VASliceParameterBufferVP8 *slcInfoVP8 = (VASliceParameterBufferVP8 *)data;
for(uint32_t j = 0; j < numSlices; j++)
{
slcInfoVP8[j].slice_data_offset += GetBsBufOffset(m_groupIndex);
}
DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfoVP8),"ParseSliceParams failed!");
m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices;
m_groupIndex++;
break;
}
case VAPictureParameterBufferType:
{
VAPictureParameterBufferVP8 *picParam = (VAPictureParameterBufferVP8 *)data;
DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
break;
}
case VAProbabilityBufferType:
{
VAProbabilityDataBufferVP8 *probInput = (VAProbabilityDataBufferVP8 *)data;
DDI_CHK_RET(ParseProbabilityData(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject, probInput),"ParseProbabilityData failed!");
DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject,
&m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.resProbabilityDataBuffer);
m_ddiDecodeCtx->DecodeParams.m_coefProbSize = dataSize;
break;
}
case VAIQMatrixBufferType:
{
VAIQMatrixBufferVP8 *imxBuf = (VAIQMatrixBufferVP8 *)data;
DDI_CHK_RET(ParseIQMatrix(mediaCtx, imxBuf),"ParseIQMatrix failed!");
break;
}
case VADecodeStreamoutBufferType:
{
DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
m_streamOutEnabled = true;
break;
}
default:
va = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
break;
}
DdiMedia_UnmapBuffer(ctx, buffers[i]);
}
DDI_FUNCTION_EXIT(va);
return va;
}
VAStatus DdiDecodeVP8::InitResourceBuffer(DDI_MEDIA_CONTEXT *mediaCtx)
{
VAStatus vaStatus = VA_STATUS_SUCCESS;
DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
bufMgr->pSliceData = nullptr;
bufMgr->ui64BitstreamOrder = 0;
bufMgr->dwMaxBsSize = m_width *
m_height * 3 / 2;
// minimal 10k bytes for some special case. Will refractor this later
if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE)
{
bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE;
}
int32_t i;
// init decode bitstream buffer object
for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
{
bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
if (bufMgr->pBitStreamBuffObject[i] == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto finish;
}
bufMgr->pBitStreamBuffObject[i]->iSize = bufMgr->dwMaxBsSize;
bufMgr->pBitStreamBuffObject[i]->uiType = VASliceDataBufferType;
bufMgr->pBitStreamBuffObject[i]->format = Media_Format_Buffer;
bufMgr->pBitStreamBuffObject[i]->uiOffset = 0;
bufMgr->pBitStreamBuffObject[i]->bo = nullptr;
bufMgr->pBitStreamBase[i] = nullptr;
}
// VP8 can support up to eight token partitions. So the max number of sliceData is 8 + 1.
// 10 is allocated for the safety.
bufMgr->m_maxNumSliceData = 10;
bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) * 10);
if (bufMgr->pSliceData == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto finish;
}
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
if (bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto finish;
}
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->iSize = sizeof(CODECHAL_VP8_COEFFPROB_DATA);
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->uiType = VAProbabilityBufferType;
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->format = Media_Format_Buffer;
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->uiOffset = 0;
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->pMediaCtx = mediaCtx;
// Create a buffer of size iSize
vaStatus = DdiMediaUtil_CreateBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject, mediaCtx->pDrmBufMgr);
if (vaStatus != VA_STATUS_SUCCESS)
{
goto finish;
}
bufMgr->Codec_Param.Codec_Param_VP8.pProbabilityDataBase = (uint8_t *)DdiMediaUtil_LockBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject, MOS_LOCKFLAG_WRITEONLY);
if (bufMgr->Codec_Param.Codec_Param_VP8.pProbabilityDataBase == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto finish;
}
bufMgr->dwNumSliceData = 0;
bufMgr->dwNumSliceControl = 0;
// Max 4 slices/segments in VP8
bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 = (VASliceParameterBufferVP8 *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferVP8) * 4);
if (bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto finish;
}
return VA_STATUS_SUCCESS;
finish:
FreeResourceBuffer();
return vaStatus;
}
void DdiDecodeVP8::FreeResourceBuffer()
{
DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
int32_t i;
for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
{
if (bufMgr->pBitStreamBase[i])
{
DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]);
bufMgr->pBitStreamBase[i] = nullptr;
}
if (bufMgr->pBitStreamBuffObject[i])
{
DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]);
MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]);
bufMgr->pBitStreamBuffObject[i] = nullptr;
}
}
if (bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8)
{
MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8);
bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 = nullptr;
}
if (bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject)
{
DdiMediaUtil_UnlockBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject);
DdiMediaUtil_FreeBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject);
MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject);
bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject = nullptr;
}
// free decode bitstream buffer object
MOS_FreeMemory(bufMgr->pSliceData);
bufMgr->pSliceData = nullptr;
}
uint8_t* DdiDecodeVP8::GetPicParamBuf(
DDI_CODEC_COM_BUFFER_MGR *bufMgr)
{
return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_VP8.PicParamVP8));
}
VAStatus DdiDecodeVP8::AllocSliceControlBuffer(
DDI_MEDIA_BUFFER *buf)
{
DDI_CODEC_COM_BUFFER_MGR *bufMgr;
bufMgr = &(m_ddiDecodeCtx->BufMgr);
if(bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 == nullptr)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8;
buf->uiOffset = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferVP8);
bufMgr->dwNumSliceControl += buf->uiNumElements;
return VA_STATUS_SUCCESS;
}
VAStatus DdiDecodeVP8::CodecHalInit(
DDI_MEDIA_CONTEXT *mediaCtx,
void *ptr)
{
VAStatus vaStatus = VA_STATUS_SUCCESS;
MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr;
CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
CODECHAL_STANDARD_INFO standardInfo;
memset(&standardInfo, 0, sizeof(standardInfo));
standardInfo.CodecFunction = codecFunction;
standardInfo.Mode = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
m_codechalSettings->codecFunction = codecFunction;
m_codechalSettings->width = m_width;
m_codechalSettings->height = m_height;
m_codechalSettings->intelEntrypointInUse = false;
m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
m_codechalSettings->mode = CODECHAL_DECODE_MODE_VP8VLD;
m_codechalSettings->standard = CODECHAL_VP8;
m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = MOS_AllocAndZeroMemory(sizeof(CODEC_VP8_IQ_MATRIX_PARAMS));
if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto CleanUpandReturn;
}
m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CODEC_VP8_PIC_PARAMS));
if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto CleanUpandReturn;
}
vaStatus = CreateCodecHal(mediaCtx,
ptr,
&standardInfo);
if (vaStatus != VA_STATUS_SUCCESS)
{
goto CleanUpandReturn;
}
if (InitResourceBuffer(mediaCtx) != VA_STATUS_SUCCESS)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto CleanUpandReturn;
}
return vaStatus;
CleanUpandReturn:
FreeResourceBuffer();
if (m_ddiDecodeCtx->pCodecHal)
{
m_ddiDecodeCtx->pCodecHal->Destroy();
MOS_Delete(m_ddiDecodeCtx->pCodecHal);
m_ddiDecodeCtx->pCodecHal = nullptr;
}
MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = 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;
return vaStatus;
}
VAStatus DdiDecodeVP8::SetDecodeParams()
{
DDI_CHK_RET(DdiMediaDecode::SetDecodeParams(),"SetDecodeParams failed!");
DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
(&m_ddiDecodeCtx->DecodeParams)->m_coefProbBuffer = &(bufMgr->Codec_Param.Codec_Param_VP8.resProbabilityDataBuffer);
return VA_STATUS_SUCCESS;
}
void DdiDecodeVP8::DestroyContext(
VADriverContextP ctx)
{
FreeResourceBuffer();
// explicitly call the base function to do the further clean-up
DdiMediaDecode::DestroyContext(ctx);
}
void DdiDecodeVP8::ContextInit(
int32_t picWidth,
int32_t picHeight)
{
// call the function in base class to initialize it.
DdiMediaDecode::ContextInit(picWidth, picHeight);
m_ddiDecodeCtx->wMode = CODECHAL_DECODE_MODE_VP8VLD;
}
extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
static bool vp8Registered =
MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeVP8>(DECODE_ID_VP8);