Files
BPI-CM9-Linux/aml-comp/hardware/amlogic/libencoder/multiEnc/vpuapi/vpuapifunc.c
T
2026-08-24 10:03:24 +08:00

1712 lines
53 KiB
C

/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in below
* which is part of this source code package.
*
* Description:
*/
// Copyright (C) 2019 Amlogic, Inc. All rights reserved.
//
// All information contained herein is Amlogic confidential.
//
// This software is provided to you pursuant to Software License
// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
// used only in accordance with the terms of this agreement.
//
// Redistribution and use in source and binary forms, with or without
// modification is strictly prohibited without prior written permission
// from Amlogic.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vpuapifunc.h"
#include "product.h"
#include "vdi_osal.h"
#include "enc_regdefine.h"
#include "debug.h"
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#define MAX_LAVEL_IDX 16
static const int g_anLevel[MAX_LAVEL_IDX] =
{
10, 11, 11, 12, 13,
//10, 16, 11, 12, 13,
20, 21, 22,
30, 31, 32,
40, 41, 42,
50, 51
};
static const int g_anLevelMaxMBPS[MAX_LAVEL_IDX] =
{
1485, 1485, 3000, 6000, 11880,
11880, 19800, 20250,
40500, 108000, 216000,
245760, 245760, 522240,
589824, 983040
};
static const int g_anLevelMaxFS[MAX_LAVEL_IDX] =
{
99, 99, 396, 396, 396,
396, 792, 1620,
1620, 3600, 5120,
8192, 8192, 8704,
22080, 36864
};
static const int g_anLevelMaxBR[MAX_LAVEL_IDX] =
{
64, 64, 192, 384, 768,
2000, 4000, 4000,
10000, 14000, 20000,
20000, 50000, 50000,
135000, 240000
};
static const int g_anLevelSliceRate[MAX_LAVEL_IDX] =
{
0, 0, 0, 0, 0,
0, 0, 0,
22, 60, 60,
60, 24, 24,
24, 24
};
static const int g_anLevelMaxMbs[MAX_LAVEL_IDX] =
{
28, 28, 56, 56, 56,
56, 79, 113,
113, 169, 202,
256, 256, 263,
420, 543
};
/******************************************************************************
define value
******************************************************************************/
/******************************************************************************
Codec Instance Slot Management
******************************************************************************/
RetCode InitCodecInstancePool(Uint32 coreIdx)
{
int i;
CodecInst * pCodecInst;
vpu_instance_pool_t *vip;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip)
return RETCODE_INSUFFICIENT_RESOURCE;
if (vip->instance_pool_inited==0)
{
for( i = 0; i < MAX_NUM_INSTANCE; i++)
{
pCodecInst = (CodecInst *)vip->codecInstPool[i];
pCodecInst->instIndex = i;
pCodecInst->inUse = 0;
}
vip->instance_pool_inited = 1;
}
return RETCODE_SUCCESS;
}
/*
* GetCodecInstance() obtains a instance.
* It stores a pointer to the allocated instance in *ppInst
* and returns RETCODE_SUCCESS on success.
* Failure results in 0(null pointer) in *ppInst and RETCODE_FAILURE.
*/
RetCode GetCodecInstance(Uint32 coreIdx, CodecInst ** ppInst)
{
int i;
CodecInst* pCodecInst = 0;
vpu_instance_pool_t* vip;
Uint32 handleSize;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip)
return RETCODE_INSUFFICIENT_RESOURCE;
for (i = 0; i < MAX_NUM_INSTANCE; i++) {
pCodecInst = (CodecInst *)vip->codecInstPool[i];
if (!pCodecInst) {
return RETCODE_FAILURE;
}
if (!pCodecInst->inUse) {
break;
}
}
if (i == MAX_NUM_INSTANCE) {
*ppInst = 0;
return RETCODE_FAILURE;
}
pCodecInst->inUse = 1;
pCodecInst->coreIdx = coreIdx;
pCodecInst->codecMode = -1;
pCodecInst->codecModeAux = -1;
pCodecInst->loggingEnable = 0;
pCodecInst->isDecoder = TRUE;
pCodecInst->productId = ProductVpuGetId(coreIdx);
osal_memset((void*)&pCodecInst->CodecInfo, 0x00, sizeof(pCodecInst->CodecInfo));
handleSize = sizeof(DecInfo);
if (handleSize < sizeof(EncInfo)) {
handleSize = sizeof(EncInfo);
}
if ((pCodecInst->CodecInfo=(void*)osal_malloc(handleSize)) == NULL) {
return RETCODE_INSUFFICIENT_RESOURCE;
}
osal_memset(pCodecInst->CodecInfo, 0x00, sizeof(handleSize));
*ppInst = pCodecInst;
if (vdi_open_instance(pCodecInst->coreIdx, pCodecInst->instIndex) < 0) {
return RETCODE_FAILURE;
}
return RETCODE_SUCCESS;
}
void FreeCodecInstance(CodecInst * pCodecInst)
{
pCodecInst->codecMode = -1;
pCodecInst->codecModeAux = -1;
vdi_close_instance(pCodecInst->coreIdx, pCodecInst->instIndex);
osal_free(pCodecInst->CodecInfo);
pCodecInst->CodecInfo = NULL;
pCodecInst->inUse = 0;
}
RetCode CheckInstanceValidity(CodecInst * pCodecInst)
{
int i;
vpu_instance_pool_t *vip;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(pCodecInst->coreIdx);
if (!vip)
return RETCODE_INSUFFICIENT_RESOURCE;
for (i = 0; i < MAX_NUM_INSTANCE; i++) {
if ((CodecInst *)vip->codecInstPool[i] == pCodecInst)
return RETCODE_SUCCESS;
}
return RETCODE_INVALID_HANDLE;
}
/******************************************************************************
API Subroutines
******************************************************************************/
Uint64 GetTimestamp(
EncHandle handle
)
{
CodecInst* pCodecInst = (CodecInst*)handle;
EncInfo* pEncInfo = NULL;
Uint64 pts;
Uint32 fps;
if (pCodecInst == NULL) {
return 0;
}
pEncInfo = &pCodecInst->CodecInfo->encInfo;
fps = pEncInfo->openParam.frameRateInfo;
if (fps == 0) {
fps = 30; /* 30 fps */
}
pts = pEncInfo->curPTS;
pEncInfo->curPTS += 90000/fps; /* 90KHz/fps */
return pts;
}
RetCode CalcEncCropInfo(CodecInst* instance, EncVpParam* param, int rotMode, int srcWidth, int srcHeight)
{
int alignedWidth, alignedHeight, pad_right, pad_bot;
int crop_right, crop_left, crop_top, crop_bot;
int prp_mode = rotMode>>1; // remove prp_enable bit
if (instance->codecMode == W_AVC_ENC) {
alignedWidth = (srcWidth + 15)&~15;
alignedHeight= (srcHeight+ 15)&~15;
}
else {
alignedWidth = (srcWidth + 31)&~31;
alignedHeight= (srcHeight+ 31)&~31;
}
pad_right = alignedWidth - srcWidth;
pad_bot = alignedHeight - srcHeight;
if (param->confWinRight > 0)
crop_right = param->confWinRight + pad_right;
else
crop_right = pad_right;
if (param->confWinBot > 0)
crop_bot = param->confWinBot + pad_bot;
else
crop_bot = pad_bot;
crop_top = param->confWinTop;
crop_left = param->confWinLeft;
param->confWinTop = crop_top;
param->confWinLeft = crop_left;
param->confWinBot = crop_bot;
param->confWinRight = crop_right;
/* prp_mode :
* | hor_mir | ver_mir | rot_angle
* [3] [2] [1:0] = {0= NONE, 1:90, 2:180, 3:270}
*/
if(prp_mode == 1 || prp_mode ==15)
{
param->confWinTop = crop_right;
param->confWinLeft = crop_top;
param->confWinBot = crop_left;
param->confWinRight = crop_bot;
}
else if(prp_mode == 2 || prp_mode ==12)
{
param->confWinTop = crop_bot;
param->confWinLeft = crop_right;
param->confWinBot = crop_top;
param->confWinRight = crop_left;
}
else if(prp_mode == 3 || prp_mode ==13)
{
param->confWinTop = crop_left;
param->confWinLeft = crop_bot;
param->confWinBot = crop_right;
param->confWinRight = crop_top;
}
else if(prp_mode == 4 || prp_mode ==10)
{
param->confWinTop = crop_bot;
param->confWinBot = crop_top;
}
else if(prp_mode == 8 || prp_mode ==6)
{
param->confWinLeft = crop_right;
param->confWinRight = crop_left;
}
else if(prp_mode == 5 || prp_mode ==11)
{
param->confWinTop = crop_left;
param->confWinLeft = crop_top;
param->confWinBot = crop_right;
param->confWinRight = crop_bot;
}
else if(prp_mode == 7 || prp_mode ==9)
{
param->confWinTop = crop_right;
param->confWinLeft = crop_bot;
param->confWinBot = crop_left;
param->confWinRight = crop_top;
}
return RETCODE_SUCCESS;
}
RetCode CheckEncInstanceValidity(EncHandle handle)
{
CodecInst * pCodecInst;
RetCode ret;
if (handle == NULL)
return RETCODE_INVALID_HANDLE;
pCodecInst = handle;
ret = CheckInstanceValidity(pCodecInst);
if (ret != RETCODE_SUCCESS) {
return RETCODE_INVALID_HANDLE;
}
if (!pCodecInst->inUse) {
return RETCODE_INVALID_HANDLE;
}
if (pCodecInst->codecMode != MP4_ENC &&
pCodecInst->codecMode != W_HEVC_ENC &&
pCodecInst->codecMode != W_SVAC_ENC &&
pCodecInst->codecMode != W_AVC_ENC &&
pCodecInst->codecMode != AVC_ENC) {
return RETCODE_INVALID_HANDLE;
}
return RETCODE_SUCCESS;
}
RetCode CheckEncParam(EncHandle handle, EncParam * param)
{
CodecInst *pCodecInst;
EncInfo *pEncInfo;
pCodecInst = handle;
pEncInfo = &pCodecInst->CodecInfo->encInfo;
if (param == 0) {
return RETCODE_INVALID_PARAM;
}
if (param->skipPicture != 0 && param->skipPicture != 1) {
return RETCODE_INVALID_PARAM;
}
if (param->skipPicture == 0) {
if (param->sourceFrame == 0) {
return RETCODE_INVALID_FRAME_BUFFER;
}
if (param->forceIPicture != 0 && param->forceIPicture != 1) {
return RETCODE_INVALID_PARAM;
}
}
if (pEncInfo->openParam.bitRate == 0) { // no rate control
if (pCodecInst->codecMode == MP4_ENC) {
if (param->quantParam < 1 || param->quantParam > 31) {
return RETCODE_INVALID_PARAM;
}
}
else if (pCodecInst->codecMode == W_HEVC_ENC || pCodecInst->codecMode == W_SVAC_ENC) {
if (param->forcePicQpEnable == 1) {
if (param->forcePicQpI < 0 || param->forcePicQpI > 63)
return RETCODE_INVALID_PARAM;
if (param->forcePicQpP < 0 || param->forcePicQpP > 63)
return RETCODE_INVALID_PARAM;
if (param->forcePicQpB < 0 || param->forcePicQpB > 63)
return RETCODE_INVALID_PARAM;
}
if (pEncInfo->ringBufferEnable == 0) {
if (param->picStreamBufferAddr % 16 || param->picStreamBufferSize == 0)
return RETCODE_INVALID_PARAM;
}
}
else { // AVC_ENC
if (param->quantParam < 0 || param->quantParam > 51) {
return RETCODE_INVALID_PARAM;
}
}
}
if (pEncInfo->ringBufferEnable == 0) {
if (param->picStreamBufferAddr % 8 || param->picStreamBufferSize == 0) {
return RETCODE_INVALID_PARAM;
}
}
return RETCODE_SUCCESS;
}
RetCode EnterLock(Uint32 coreIdx)
{
if (vdi_lock(coreIdx) != 0)
return RETCODE_FAILURE;
SetClockGate(coreIdx, 1);
return RETCODE_SUCCESS;
}
RetCode LeaveLock(Uint32 coreIdx)
{
SetClockGate(coreIdx, 0);
vdi_unlock(coreIdx);
return RETCODE_SUCCESS;
}
RetCode EnterLock_noclk(Uint32 coreIdx)
{
if (vdi_lock(coreIdx) != 0)
return RETCODE_FAILURE;
return RETCODE_SUCCESS;
}
RetCode LeaveLock_noclk(Uint32 coreIdx)
{
vdi_unlock(coreIdx);
return RETCODE_SUCCESS;
}
RetCode SetClockGate(Uint32 coreIdx, Uint32 on)
{
vpu_instance_pool_t *vip;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip) {
VLOG(ERR, "SetClockGate: RETCODE_INSUFFICIENT_RESOURCE\n");
return RETCODE_INSUFFICIENT_RESOURCE;
}
vdi_set_clock_gate(coreIdx, on);
return RETCODE_SUCCESS;
}
void SetPendingInst(Uint32 coreIdx, CodecInst *inst)
{
vpu_instance_pool_t *vip;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip)
return;
vip->pendingInst = inst;
if (inst)
vip->pendingInstIdxPlus1 = (inst->instIndex+1);
else
vip->pendingInstIdxPlus1 = 0;
}
void ClearPendingInst(Uint32 coreIdx)
{
vpu_instance_pool_t *vip;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip)
return;
if(vip->pendingInst) {
vip->pendingInst = 0;
vip->pendingInstIdxPlus1 = 0;
}
}
CodecInst *GetPendingInst(Uint32 coreIdx)
{
vpu_instance_pool_t *vip;
int pendingInstIdx;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip)
return NULL;
if (!vip->pendingInst)
return NULL;
pendingInstIdx = vip->pendingInstIdxPlus1-1;
if (pendingInstIdx < 0 || pendingInstIdx >= MAX_NUM_INSTANCE)
return NULL;
return (CodecInst *)vip->codecInstPool[pendingInstIdx];
}
int GetPendingInstIdx(Uint32 coreIdx)
{
vpu_instance_pool_t *vip;
vip = (vpu_instance_pool_t *)vdi_get_instance_pool(coreIdx);
if (!vip)
return -1;
return (vip->pendingInstIdxPlus1-1);
}
RetCode UpdateFrameBufferAddr(
TiledMapType mapType,
FrameBuffer* fbArr,
Uint32 numOfFrameBuffers,
Uint32 sizeLuma,
Uint32 sizeChroma
)
{
Uint32 i;
BOOL yuv422Interleave = FALSE;
BOOL fieldFrame = (BOOL)(mapType == LINEAR_FIELD_MAP);
BOOL cbcrInterleave = (BOOL)(mapType >= COMPRESSED_FRAME_MAP || fbArr[0].cbcrInterleave == TRUE);
BOOL reuseFb = FALSE;
if (mapType < COMPRESSED_FRAME_MAP) {
switch (fbArr[0].format) {
case FORMAT_YUYV:
case FORMAT_YUYV_P10_16BIT_MSB:
case FORMAT_YUYV_P10_16BIT_LSB:
case FORMAT_YUYV_P10_32BIT_MSB:
case FORMAT_YUYV_P10_32BIT_LSB:
case FORMAT_YVYU:
case FORMAT_YVYU_P10_16BIT_MSB:
case FORMAT_YVYU_P10_16BIT_LSB:
case FORMAT_YVYU_P10_32BIT_MSB:
case FORMAT_YVYU_P10_32BIT_LSB:
case FORMAT_UYVY:
case FORMAT_UYVY_P10_16BIT_MSB:
case FORMAT_UYVY_P10_16BIT_LSB:
case FORMAT_UYVY_P10_32BIT_MSB:
case FORMAT_UYVY_P10_32BIT_LSB:
case FORMAT_VYUY:
case FORMAT_VYUY_P10_16BIT_MSB:
case FORMAT_VYUY_P10_16BIT_LSB:
case FORMAT_VYUY_P10_32BIT_MSB:
case FORMAT_VYUY_P10_32BIT_LSB:
yuv422Interleave = TRUE;
break;
default:
yuv422Interleave = FALSE;
break;
}
}
for (i=0; i<numOfFrameBuffers; i++) {
reuseFb = (fbArr[i].bufY != (PhysicalAddress)-1 && fbArr[i].bufCb != (PhysicalAddress)-1 && fbArr[i].bufCr != (PhysicalAddress)-1);
if (reuseFb == FALSE) {
if (yuv422Interleave == TRUE) {
fbArr[i].bufCb = (PhysicalAddress)-1;
fbArr[i].bufCr = (PhysicalAddress)-1;
}
else {
if (fbArr[i].bufCb == (PhysicalAddress)-1) {
fbArr[i].bufCb = fbArr[i].bufY + (sizeLuma >> fieldFrame);
}
if (fbArr[i].bufCr == (PhysicalAddress)-1) {
if (cbcrInterleave == TRUE) {
fbArr[i].bufCr = (PhysicalAddress)-1;
}
else {
fbArr[i].bufCr = fbArr[i].bufCb + (sizeChroma >> fieldFrame);
}
}
}
}
}
return RETCODE_SUCCESS;
}
Int32 ConfigSecAXIVp(Uint32 coreIdx, Int32 codecMode, SecAxiInfo *sa, Uint32 width, Uint32 height, Uint32 profile, Uint32 levelIdc)
{
vpu_buffer_t vb;
int offset;
Uint32 size = 0;
Uint32 lumaSize = 0;
Uint32 chromaSize = 0;
Uint32 productId;
UNREFERENCED_PARAMETER(codecMode);
UNREFERENCED_PARAMETER(height);
if (vdi_get_sram_memory(coreIdx, &vb) < 0)
return 0;
productId = ProductVpuGetId(coreIdx);
if (!vb.size) {
sa->bufSize = 0;
sa->u.vp.useIpEnable = 0;
sa->u.vp.useLfRowEnable = 0;
sa->u.vp.useBitEnable = 0;
sa->u.vp.useEncImdEnable = 0;
sa->u.vp.useEncLfEnable = 0;
sa->u.vp.useEncRdoEnable = 0;
return 0;
}
sa->bufBase = vb.phys_addr;
offset = 0;
/* Intra Prediction */
if (sa->u.vp.useIpEnable == TRUE) {
sa->u.vp.bufIp = sa->bufBase + offset;
switch (productId) {
case PRODUCT_ID_512:
case PRODUCT_ID_515:
if ( codecMode == W_VP9_DEC ) {
lumaSize = VPU_ALIGN128(width) * 10/8;
chromaSize = VPU_ALIGN128(width) * 10/8;
}
else if (codecMode == W_HEVC_DEC) {
if (profile == HEVC_PROFILE_MAIN) {
lumaSize = VPU_ALIGN32(width);
chromaSize = VPU_ALIGN32(width);
}
else {
lumaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8;
chromaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8;
}
}
else if (codecMode == W_AVS2_DEC) {
if (profile == AVS2_PROFILE_MAIN10) {
lumaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8;
chromaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8;
}
else {
lumaSize = VPU_ALIGN16(width);
chromaSize = VPU_ALIGN16(width);
}
}
else if (codecMode == W_SVAC_DEC) {
int bitDepth = (profile == SVAC_PROFILE_BASE ? 8 : 10);
lumaSize = VPU_ALIGN128(width)*bitDepth/8;
chromaSize = VPU_ALIGN128(width/2)*2*bitDepth/8;
}
else if (codecMode == W_AVC_DEC) {
if (profile == 110) { // High 10
lumaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8;
chromaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8;
}
else {
lumaSize = VPU_ALIGN32(width);
chromaSize = VPU_ALIGN32(width);
}
}
break;
case PRODUCT_ID_521:
case PRODUCT_ID_511:
if (profile == HEVC_PROFILE_MAIN10) {
lumaSize = VPU_ALIGN128(VPU_ALIGN16(width)*10)/8*2;
chromaSize = 0;
}
else {
lumaSize = VPU_ALIGN16(width)*2;
chromaSize = 0;
}
break;
default:
return 0;
}
offset = lumaSize + chromaSize;
if (offset > vb.size) {
sa->bufSize = 0;
return 0;
}
}
/* Loopfilter row */
if (sa->u.vp.useLfRowEnable == TRUE) {
sa->u.vp.bufLfRow = sa->bufBase + offset;
if ( codecMode == W_VP9_DEC ) {
if ( profile == VP9_PROFILE_2)
{
lumaSize = VPU_ALIGN64(width) * 8 * 10/8; /* lumaLIne : 8 */
chromaSize = VPU_ALIGN64(width) * 8 * 10/8; /* chromaLine : 8 */
}
else
{
lumaSize = VPU_ALIGN64(width) * 8; /* lumaLIne : 8 */
chromaSize = VPU_ALIGN64(width) * 8; /* chromaLine : 8 */
}
}
else if (codecMode == W_HEVC_DEC) {
if (profile == HEVC_PROFILE_MAIN) {
size = VPU_ALIGN32(width)*8;
}
else {
Uint32 level = levelIdc/30;
if (level >= 5) {
size = VPU_ALIGN32(width)/2 * 13 + VPU_ALIGN64(width)*4;
}
else {
size = VPU_ALIGN64(width)*13;
}
}
lumaSize = size;
chromaSize = 0;
}
else if (codecMode == W_AVC_DEC) {
if (profile == 110) {
Uint32 level = levelIdc/30;
if (level >= 5) {
size = VPU_ALIGN32(width)/2 * 13 + VPU_ALIGN64(width)*4;
}
else {
size = VPU_ALIGN64(width)*13;
}
}
else {
size = VPU_ALIGN32(width)*8;
}
lumaSize = size;
chromaSize = 0;
}
else if (codecMode == W_AVS2_DEC) {
// AVS2
if (profile == AVS2_PROFILE_MAIN10) {
lumaSize = VPU_ALIGN16(width)*5*2;
chromaSize = VPU_ALIGN16(width)*5*2;
}
else {
lumaSize = VPU_ALIGN16(width)*5;
chromaSize = VPU_ALIGN16(width)*5;
}
}
else if (codecMode == W_SVAC_DEC) {
int bitDepth = (profile == SVAC_PROFILE_BASE ? 8 : 10);
lumaSize = VPU_ALIGN128(width)*bitDepth/8*5;
chromaSize = VPU_ALIGN128(width/2)*2*bitDepth/8*5;
}
if (productId == PRODUCT_ID_511 || productId == PRODUCT_ID_521) {
Uint32 luma = 0, chroma = 0;
if (codecMode == W_HEVC_DEC) {
luma = (profile == HEVC_PROFILE_MAIN10) ? 7 : 5;
chroma = (profile == HEVC_PROFILE_MAIN10) ? 4 : 3;
}
else if (codecMode == W_AVC_DEC) {
luma = (profile == HEVC_PROFILE_MAIN10) ? 5 : 4;
chroma = 3;//(profile == HEVC_PROFILE_MAIN10) ? 3 : 3;
}
lumaSize = VPU_ALIGN32(width)*luma;
chromaSize = VPU_ALIGN32(width)*chroma;
}
offset += (lumaSize + chromaSize);
if (offset > vb.size) {
sa->bufSize = 0;
return 0;
}
}
if (sa->u.vp.useBitEnable == TRUE) {
sa->u.vp.bufBit = sa->bufBase + offset;
if (codecMode == W_VP9_DEC) {
size = VPU_ALIGN64(width)/64 * (70*8);
}
else if (codecMode == W_HEVC_DEC) {
size = VPU_ALIGN128(VPU_ALIGN32(width)/32*9*8);
}
else if (codecMode == W_AVS2_DEC) {
size = VPU_ALIGN16(width/16)*40;
}
else if (codecMode == W_SVAC_DEC) {
size = 0;
}
if (productId == PRODUCT_ID_511 || productId == PRODUCT_ID_521)
size = VPU_ALIGN64(width)*4;
offset += size;
if (offset > vb.size) {
sa->bufSize = 0;
return 0;
}
}
if (sa->u.vp.useEncImdEnable == TRUE) {
/* Main profile(8bit) : Align32(picWidth)
* Main10 profile(10bit): Align32(picWidth)
*/
sa->u.vp.bufImd = sa->bufBase + offset;
offset += VPU_ALIGN32(width);
if (offset > vb.size) {
sa->bufSize = 0;
return 0;
}
}
if (sa->u.vp.useEncLfEnable == TRUE) {
Uint32 luma, chroma;
sa->u.vp.bufLf = sa->bufBase + offset;
if (codecMode == W_AVC_ENC) {
luma = (profile == HEVC_PROFILE_MAIN10 ? 5 : 4);
chroma = 3;
lumaSize = VPU_ALIGN16(width) * luma;
chromaSize = VPU_ALIGN16(width) * chroma;
}
else {
luma = (profile == HEVC_PROFILE_MAIN10 ? 7 : 5);
if (productId == PRODUCT_ID_521)
chroma = (profile == HEVC_PROFILE_MAIN10 ? 4 : 3);
else
chroma = (profile == HEVC_PROFILE_MAIN10 ? 5 : 3);
lumaSize = VPU_ALIGN64(width) * luma;
chromaSize = VPU_ALIGN64(width) * chroma;
}
offset += lumaSize + chromaSize;
if (offset > vb.size) {
sa->bufSize = 0;
return 0;
}
}
if (sa->u.vp.useEncRdoEnable == TRUE) {
switch (productId) {
case PRODUCT_ID_521:
sa->u.vp.bufRdo = sa->bufBase + offset;
if (codecMode == W_AVC_ENC) {
offset += (VPU_ALIGN64(width)>>6)*384;
}
else { // HEVC ENC
offset += (VPU_ALIGN64(width)>>6)*288;
}
break;
default:
/* Main profile(8bit) : (Align64(picWidth)/64) * 336
* Main10 profile(10bit): (Align64(picWidth)/64) * 336
*/
sa->u.vp.bufRdo = sa->bufBase + offset;
offset += (VPU_ALIGN64(width)/64) * 336;
break;
}
if (offset > vb.size) {
sa->bufSize = 0;
return 0;
}
}
sa->bufSize = offset;
return 1;
}
Int32 CalcStride(
Uint32 width,
Uint32 height,
FrameBufferFormat format,
BOOL cbcrInterleave,
TiledMapType mapType,
BOOL isVP9
)
{
Uint32 lumaStride = 0;
Uint32 chromaStride = 0;
lumaStride = VPU_ALIGN32(width);
if (height > width) {
if ((mapType >= TILED_FRAME_V_MAP && mapType <= TILED_MIXED_V_MAP) ||
mapType == TILED_FRAME_NO_BANK_MAP ||
mapType == TILED_FIELD_NO_BANK_MAP)
width = VPU_ALIGN16(height); // TiledMap constraints
}
if (mapType == LINEAR_FRAME_MAP || mapType == LINEAR_FIELD_MAP) {
Uint32 twice = 0;
twice = cbcrInterleave == TRUE ? 2 : 1;
switch (format) {
case FORMAT_420:
/* nothing to do */
break;
case FORMAT_420_P10_16BIT_LSB:
case FORMAT_420_P10_16BIT_MSB:
case FORMAT_422_P10_16BIT_MSB:
case FORMAT_422_P10_16BIT_LSB:
lumaStride = VPU_ALIGN32(width)*2;
break;
case FORMAT_420_P10_32BIT_LSB:
case FORMAT_420_P10_32BIT_MSB:
case FORMAT_422_P10_32BIT_MSB:
case FORMAT_422_P10_32BIT_LSB:
if ( isVP9 == TRUE ) {
lumaStride = VPU_ALIGN32(((width+11)/12)*16);
chromaStride = (((width/2)+11)*twice/12)*16;
}
else {
width = VPU_ALIGN32(width);
lumaStride = ((VPU_ALIGN16(width)+11)/12)*16;
chromaStride = ((VPU_ALIGN16(width/2)+11)*twice/12)*16;
if ( (chromaStride*2) > lumaStride)
{
lumaStride = chromaStride * 2;
VLOG(ERR, "double chromaStride size is bigger than lumaStride\n");
}
}
if (cbcrInterleave == TRUE) {
lumaStride = MAX(lumaStride, chromaStride);
}
break;
case FORMAT_422:
/* nothing to do */
break;
case FORMAT_YUYV: // 4:2:2 8bit packed
case FORMAT_YVYU:
case FORMAT_UYVY:
case FORMAT_VYUY:
lumaStride = VPU_ALIGN32(width) * 2;
break;
case FORMAT_YUYV_P10_16BIT_MSB: // 4:2:2 10bit packed
case FORMAT_YUYV_P10_16BIT_LSB:
case FORMAT_YVYU_P10_16BIT_MSB:
case FORMAT_YVYU_P10_16BIT_LSB:
case FORMAT_UYVY_P10_16BIT_MSB:
case FORMAT_UYVY_P10_16BIT_LSB:
case FORMAT_VYUY_P10_16BIT_MSB:
case FORMAT_VYUY_P10_16BIT_LSB:
lumaStride = VPU_ALIGN32(width) * 4;
break;
case FORMAT_YUYV_P10_32BIT_MSB:
case FORMAT_YUYV_P10_32BIT_LSB:
case FORMAT_YVYU_P10_32BIT_MSB:
case FORMAT_YVYU_P10_32BIT_LSB:
case FORMAT_UYVY_P10_32BIT_MSB:
case FORMAT_UYVY_P10_32BIT_LSB:
case FORMAT_VYUY_P10_32BIT_MSB:
case FORMAT_VYUY_P10_32BIT_LSB:
lumaStride = VPU_ALIGN32(width*2)*2;
break;
default:
break;
}
}
else if (mapType == COMPRESSED_FRAME_MAP) {
switch (format) {
case FORMAT_420:
case FORMAT_422:
case FORMAT_YUYV:
case FORMAT_YVYU:
case FORMAT_UYVY:
case FORMAT_VYUY:
break;
case FORMAT_420_P10_16BIT_LSB:
case FORMAT_420_P10_16BIT_MSB:
case FORMAT_420_P10_32BIT_LSB:
case FORMAT_420_P10_32BIT_MSB:
case FORMAT_422_P10_16BIT_MSB:
case FORMAT_422_P10_16BIT_LSB:
case FORMAT_422_P10_32BIT_MSB:
case FORMAT_422_P10_32BIT_LSB:
case FORMAT_YUYV_P10_16BIT_MSB:
case FORMAT_YUYV_P10_16BIT_LSB:
case FORMAT_YVYU_P10_16BIT_MSB:
case FORMAT_YVYU_P10_16BIT_LSB:
case FORMAT_YVYU_P10_32BIT_MSB:
case FORMAT_YVYU_P10_32BIT_LSB:
case FORMAT_UYVY_P10_16BIT_MSB:
case FORMAT_UYVY_P10_16BIT_LSB:
case FORMAT_VYUY_P10_16BIT_MSB:
case FORMAT_VYUY_P10_16BIT_LSB:
case FORMAT_YUYV_P10_32BIT_MSB:
case FORMAT_YUYV_P10_32BIT_LSB:
case FORMAT_UYVY_P10_32BIT_MSB:
case FORMAT_UYVY_P10_32BIT_LSB:
case FORMAT_VYUY_P10_32BIT_MSB:
case FORMAT_VYUY_P10_32BIT_LSB:
lumaStride = VPU_ALIGN32(VPU_ALIGN16(width)*5)/4;
lumaStride = VPU_ALIGN32(lumaStride);
break;
default:
return -1;
}
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_8BIT || mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_10BIT || mapType == COMPRESSED_FRAME_MAP_V50_LOSSY) {
lumaStride = VPU_ALIGN32(width);
}
else if (mapType == TILED_FRAME_NO_BANK_MAP || mapType == TILED_FIELD_NO_BANK_MAP) {
lumaStride = (width > 4096) ? 8192 :
(width > 2048) ? 4096 :
(width > 1024) ? 2048 :
(width > 512) ? 1024 : 512;
}
else if (mapType == TILED_FRAME_MB_RASTER_MAP || mapType == TILED_FIELD_MB_RASTER_MAP) {
lumaStride = VPU_ALIGN32(width);
}
else {
width = (width < height) ? height : width;
lumaStride = (width > 4096) ? 8192 :
(width > 2048) ? 4096 :
(width > 1024) ? 2048 :
(width > 512) ? 1024 : 512;
}
return lumaStride;
}
// 32 bit / 16 bit ==> 32-n bit remainder, n bit quotient
static int fixDivRq(int a, int b, int n)
{
Int64 c;
Int64 a_36bit;
Int64 mask, signBit;/*, signExt;*/
Uint64 signExt;
int i;
// DIVS emulation for BPU accumulator size
// For SunOS build
mask = 0x0F; mask <<= 32; mask |= 0x00FFFFFFFF; // mask = 0x0FFFFFFFFF;
signBit = 0x08; signBit <<= 32; // signBit = 0x0800000000;
signExt = 0xFFFFFFF0; signExt <<= 32; // signExt = 0xFFFFFFF000000000;
a_36bit = (Int64) a;
for (i=0; i<n; i++) {
c = a_36bit - (b << 15);
if (c >= 0)
a_36bit = (c << 1) + 1;
else
a_36bit = a_36bit << 1;
a_36bit = a_36bit & mask;
if (a_36bit & signBit)
a_36bit |= signExt;
}
a = (int) a_36bit;
return a; // R = [31:n], Q = [n-1:0]
}
static int math_div(int number, int denom)
{
int c;
c = fixDivRq(number, denom, 17); // R = [31:17], Q = [16:0]
c = c & 0xFFFF;
c = (c + 1) >> 1; // round
return (c & 0xFFFF);
}
int LevelCalculation(int MbNumX, int MbNumY, int frameRateInfo, int interlaceFlag, int BitRate, int SliceNum)
{
int mbps;
int frameRateDiv, frameRateRes, frameRate;
int mbPicNum = (MbNumX*MbNumY);
int mbFrmNum;
int MaxSliceNum;
int LevelIdc = 0;
int i, maxMbs;
if (interlaceFlag) {
mbFrmNum = mbPicNum*2;
MbNumY *=2;
}
else mbFrmNum = mbPicNum;
frameRateDiv = (frameRateInfo >> 16) + 1;
frameRateRes = frameRateInfo & 0xFFFF;
frameRate = math_div(frameRateRes, frameRateDiv);
mbps = mbFrmNum*frameRate;
for(i=0; i<MAX_LAVEL_IDX; i++)
{
maxMbs = g_anLevelMaxMbs[i];
if ( mbps <= g_anLevelMaxMBPS[i]
&& mbFrmNum <= g_anLevelMaxFS[i]
&& MbNumX <= maxMbs
&& MbNumY <= maxMbs
&& BitRate <= g_anLevelMaxBR[i] )
{
LevelIdc = g_anLevel[i];
break;
}
}
if (i==MAX_LAVEL_IDX)
i = MAX_LAVEL_IDX-1;
if (SliceNum)
{
SliceNum = math_div(mbPicNum, SliceNum);
if (g_anLevelSliceRate[i])
{
MaxSliceNum = math_div( MAX( mbPicNum, g_anLevelMaxMBPS[i]/( 172/( 1+interlaceFlag ) )), g_anLevelSliceRate[i] );
if ( SliceNum> MaxSliceNum)
return -1;
}
}
return LevelIdc;
}
Int32 CalcLumaSize(
CodecInst* inst,
Int32 productId,
Int32 stride,
Int32 height,
FrameBufferFormat format,
BOOL cbcrIntl,
TiledMapType mapType,
DRAMConfig *pDramCfg
)
{
Int32 unit_size_hor_lum, unit_size_ver_lum, size_dpb_lum, field_map, size_dpb_lum_4k;
UNREFERENCED_PARAMETER(cbcrIntl);
VLOG(INFO, "CalcLumaSize stride %d height %d, mapType %d format %d\n",
stride, height, mapType, format);
if (mapType == TILED_FIELD_V_MAP || mapType == TILED_FIELD_NO_BANK_MAP || mapType == LINEAR_FIELD_MAP) {
field_map = 1;
}
else {
field_map = 0;
}
if (mapType == LINEAR_FRAME_MAP || mapType == LINEAR_FIELD_MAP) {
size_dpb_lum = stride * height;
}
else if (mapType == COMPRESSED_FRAME_MAP) {
size_dpb_lum = stride * height;
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_10BIT || mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_422_10BIT) {
size_dpb_lum = VP5_ENC_FBC50_LOSSLESS_LUMA_10BIT_FRAME_SIZE(stride, height);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_8BIT || mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_422_8BIT) {
size_dpb_lum = VP5_ENC_FBC50_LOSSLESS_LUMA_8BIT_FRAME_SIZE(stride, height);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSY || mapType == COMPRESSED_FRAME_MAP_V50_LOSSY_422) {
if (pDramCfg == NULL)
return 0;
size_dpb_lum = VP5_ENC_FBC50_LOSSY_LUMA_FRAME_SIZE(stride, height, pDramCfg->tx16y);
}
else if (mapType == TILED_FRAME_NO_BANK_MAP || mapType == TILED_FIELD_NO_BANK_MAP) {
unit_size_hor_lum = stride;
unit_size_ver_lum = (((height>>field_map)+127)/128) * 128; // unit vertical size is 128 pixel (8MB)
size_dpb_lum = unit_size_hor_lum * (unit_size_ver_lum<<field_map);
}
else if (mapType == TILED_FRAME_MB_RASTER_MAP || mapType == TILED_FIELD_MB_RASTER_MAP) {
if (productId == PRODUCT_ID_960) {
size_dpb_lum = stride * height;
// aligned to 8192*2 (0x4000) for top/bot field
// use upper 20bit address only
size_dpb_lum_4k = ((size_dpb_lum + 16383)/16384)*16384;
if (mapType == TILED_FIELD_MB_RASTER_MAP) {
size_dpb_lum_4k = ((size_dpb_lum_4k+(0x8000-1))&~(0x8000-1));
}
size_dpb_lum = size_dpb_lum_4k;
}
else {
size_dpb_lum = stride * (height>>field_map);
size_dpb_lum_4k = ((size_dpb_lum+(16384-1))/16384)*16384;
size_dpb_lum = size_dpb_lum_4k<<field_map;
}
}
else {
if (productId == PRODUCT_ID_960) {
Int32 VerSizePerRas,Ras1DBit;
Int32 ChrSizeYField;
Int32 ChrFieldRasSize,ChrFrameRasSize,LumFieldRasSize,LumFrameRasSize;
ChrSizeYField = ((height/2)+1)>>1;
if (pDramCfg == NULL)
return 0;
if (mapType == TILED_FRAME_V_MAP) {
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 16) { // BITMAIN setting
VerSizePerRas = 64; // Tile (16x2)*(4*2)
Ras1DBit = 1;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 4 && pDramCfg->rasBit == 15) { // BITMAIN setting
VerSizePerRas = 128; // Tile (8x4)*(8x2)
Ras1DBit = 1;
}
else
return 0;
}
else if (mapType == TILED_FRAME_H_MAP) {
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else
return 0;
}
else if (mapType == TILED_FIELD_V_MAP) {
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 16) { // BITMAIN setting
VerSizePerRas = 64; // Tile (16x2)*(4*2)
Ras1DBit = 1;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 4 && pDramCfg->rasBit == 15) { // BITMAIN setting
VerSizePerRas = 128; // Tile (8x4)*(8x2)
Ras1DBit = 1;
}
else
return 0;
}
else { // TILED_FIELD_H_MAP
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else
return 0;
}
ChrFieldRasSize = ((ChrSizeYField + (VerSizePerRas-1))/VerSizePerRas) << Ras1DBit;
ChrFrameRasSize = ChrFieldRasSize *2;
LumFieldRasSize = ChrFrameRasSize;
LumFrameRasSize = LumFieldRasSize *2;
size_dpb_lum = LumFrameRasSize << (pDramCfg->bankBit+pDramCfg->casBit+pDramCfg->busBit);
}
else { // productId != 960
unit_size_hor_lum = stride;
unit_size_ver_lum = (((height>>field_map)+63)/64) * 64; // unit vertical size is 64 pixel (4MB)
size_dpb_lum = unit_size_hor_lum * (unit_size_ver_lum<<field_map);
}
}
VLOG(INFO, "CalcLumaSize size %d \n", size_dpb_lum);
return size_dpb_lum;
}
Int32 CalcChromaSize(
CodecInst* inst,
Int32 productId,
Int32 stride,
Int32 height,
FrameBufferFormat format,
BOOL cbcrIntl,
TiledMapType mapType,
DRAMConfig* pDramCfg
)
{
Int32 chr_size_y, chr_size_x;
Int32 chr_vscale, chr_hscale;
Int32 unit_size_hor_chr, unit_size_ver_chr;
Int32 size_dpb_chr, size_dpb_chr_4k;
Int32 field_map;
unit_size_hor_chr = 0;
unit_size_ver_chr = 0;
chr_hscale = 1;
chr_vscale = 1;
VLOG(INFO, "CalcChromaSize stride %d height %d, mapType %d format %d\n",
stride, height, mapType, format);
switch (format) {
case FORMAT_420_P10_16BIT_LSB:
case FORMAT_420_P10_16BIT_MSB:
case FORMAT_420_P10_32BIT_LSB:
case FORMAT_420_P10_32BIT_MSB:
case FORMAT_420:
chr_hscale = 2;
chr_vscale = 2;
break;
case FORMAT_224:
chr_vscale = 2;
break;
case FORMAT_422:
case FORMAT_422_P10_16BIT_LSB:
case FORMAT_422_P10_16BIT_MSB:
case FORMAT_422_P10_32BIT_LSB:
case FORMAT_422_P10_32BIT_MSB:
chr_hscale = 2;
break;
case FORMAT_444:
case FORMAT_400:
case FORMAT_YUYV:
case FORMAT_YVYU:
case FORMAT_UYVY:
case FORMAT_VYUY:
case FORMAT_YUYV_P10_16BIT_MSB: // 4:2:2 10bit packed
case FORMAT_YUYV_P10_16BIT_LSB:
case FORMAT_YVYU_P10_16BIT_MSB:
case FORMAT_YVYU_P10_16BIT_LSB:
case FORMAT_UYVY_P10_16BIT_MSB:
case FORMAT_UYVY_P10_16BIT_LSB:
case FORMAT_VYUY_P10_16BIT_MSB:
case FORMAT_VYUY_P10_16BIT_LSB:
case FORMAT_YUYV_P10_32BIT_MSB:
case FORMAT_YUYV_P10_32BIT_LSB:
case FORMAT_YVYU_P10_32BIT_MSB:
case FORMAT_YVYU_P10_32BIT_LSB:
case FORMAT_UYVY_P10_32BIT_MSB:
case FORMAT_UYVY_P10_32BIT_LSB:
case FORMAT_VYUY_P10_32BIT_MSB:
case FORMAT_VYUY_P10_32BIT_LSB:
break;
default:
return 0;
}
if (mapType == TILED_FIELD_V_MAP || mapType == TILED_FIELD_NO_BANK_MAP || mapType == LINEAR_FIELD_MAP) {
field_map = 1;
}
else {
field_map = 0;
}
if (mapType == LINEAR_FRAME_MAP || mapType == LINEAR_FIELD_MAP) {
switch (format) {
case FORMAT_420:
unit_size_hor_chr = stride/2;
unit_size_ver_chr = height/2;
break;
case FORMAT_420_P10_16BIT_LSB:
case FORMAT_420_P10_16BIT_MSB:
unit_size_hor_chr = stride/2;
unit_size_ver_chr = height/2;
break;
case FORMAT_420_P10_32BIT_LSB:
case FORMAT_420_P10_32BIT_MSB:
unit_size_hor_chr = VPU_ALIGN16(stride/2);
unit_size_ver_chr = height/2;
break;
case FORMAT_422:
case FORMAT_422_P10_16BIT_LSB:
case FORMAT_422_P10_16BIT_MSB:
case FORMAT_422_P10_32BIT_LSB:
case FORMAT_422_P10_32BIT_MSB:
unit_size_hor_chr = VPU_ALIGN32(stride/2);
unit_size_ver_chr = height;
break;
case FORMAT_YUYV:
case FORMAT_YVYU:
case FORMAT_UYVY:
case FORMAT_VYUY:
case FORMAT_YUYV_P10_16BIT_MSB: // 4:2:2 10bit packed
case FORMAT_YUYV_P10_16BIT_LSB:
case FORMAT_YVYU_P10_16BIT_MSB:
case FORMAT_YVYU_P10_16BIT_LSB:
case FORMAT_UYVY_P10_16BIT_MSB:
case FORMAT_UYVY_P10_16BIT_LSB:
case FORMAT_VYUY_P10_16BIT_MSB:
case FORMAT_VYUY_P10_16BIT_LSB:
case FORMAT_YUYV_P10_32BIT_MSB:
case FORMAT_YUYV_P10_32BIT_LSB:
case FORMAT_YVYU_P10_32BIT_MSB:
case FORMAT_YVYU_P10_32BIT_LSB:
case FORMAT_UYVY_P10_32BIT_MSB:
case FORMAT_UYVY_P10_32BIT_LSB:
case FORMAT_VYUY_P10_32BIT_MSB:
case FORMAT_VYUY_P10_32BIT_LSB:
unit_size_hor_chr = 0;
unit_size_ver_chr = 0;
break;
default:
break;
}
size_dpb_chr = (format == FORMAT_400) ? 0 : unit_size_ver_chr * unit_size_hor_chr;
}
else if (mapType == COMPRESSED_FRAME_MAP) {
switch (format) {
case FORMAT_420:
case FORMAT_YUYV: // 4:2:2 8bit packed
case FORMAT_YVYU:
case FORMAT_UYVY:
case FORMAT_VYUY:
size_dpb_chr = VPU_ALIGN16(stride/2)*height;
break;
default:
/* 10bit */
stride = VPU_ALIGN64(stride/2)+12; /* FIXME: need width information */
size_dpb_chr = VPU_ALIGN32(stride)*VPU_ALIGN4(height);
break;
}
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_10BIT) {
size_dpb_chr = VP5_ENC_FBC50_LOSSLESS_CHROMA_10BIT_FRAME_SIZE(stride, height);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_8BIT) {
size_dpb_chr = VP5_ENC_FBC50_LOSSLESS_CHROMA_8BIT_FRAME_SIZE(stride, height);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSY) {
if (pDramCfg == NULL)
return 0;
size_dpb_chr = VP5_ENC_FBC50_LOSSY_CHROMA_FRAME_SIZE(stride, height, pDramCfg->tx16c);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_422_10BIT) {
size_dpb_chr = VP5_ENC_FBC50_LOSSLESS_422_CHROMA_10BIT_FRAME_SIZE(stride, height);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSLESS_422_8BIT) {
size_dpb_chr = VP5_ENC_FBC50_LOSSLESS_422_CHROMA_8BIT_FRAME_SIZE(stride, height);
}
else if (mapType == COMPRESSED_FRAME_MAP_V50_LOSSY_422) {
if (pDramCfg == NULL)
return 0;
size_dpb_chr = VP5_ENC_FBC50_LOSSY_422_CHROMA_FRAME_SIZE(stride, height, pDramCfg->tx16c);
}
else if (mapType == TILED_FRAME_NO_BANK_MAP || mapType == TILED_FIELD_NO_BANK_MAP) {
chr_size_y = (height>>field_map)/chr_hscale;
chr_size_x = stride/chr_vscale;
unit_size_hor_chr = (chr_size_x > 4096) ? 8192:
(chr_size_x > 2048) ? 4096 :
(chr_size_x > 1024) ? 2048 :
(chr_size_x > 512) ? 1024 : 512;
unit_size_ver_chr = ((chr_size_y+127)/128) * 128; // unit vertical size is 128 pixel (8MB)
size_dpb_chr = (format==FORMAT_400) ? 0 : (unit_size_hor_chr * (unit_size_ver_chr<<field_map));
}
else if (mapType == TILED_FRAME_MB_RASTER_MAP || mapType == TILED_FIELD_MB_RASTER_MAP) {
if (productId == PRODUCT_ID_960) {
chr_size_x = stride/chr_hscale;
chr_size_y = height/chr_hscale;
size_dpb_chr = chr_size_y * chr_size_x;
// aligned to 8192*2 (0x4000) for top/bot field
// use upper 20bit address only
size_dpb_chr_4k = ((size_dpb_chr + 16383)/16384)*16384;
if (mapType == TILED_FIELD_MB_RASTER_MAP) {
size_dpb_chr_4k = ((size_dpb_chr_4k+(0x8000-1))&~(0x8000-1));
}
size_dpb_chr = size_dpb_chr_4k;
}
else {
size_dpb_chr = (format==FORMAT_400) ? 0 : ((stride * (height>>field_map))/(chr_hscale*chr_vscale));
size_dpb_chr_4k = ((size_dpb_chr+(16384-1))/16384)*16384;
size_dpb_chr = size_dpb_chr_4k<<field_map;
}
}
else {
if (productId == PRODUCT_ID_960) {
int VerSizePerRas,Ras1DBit;
int ChrSizeYField;
int divY;
int ChrFieldRasSize,ChrFrameRasSize;
divY = format == FORMAT_420 || format == FORMAT_224 ? 2 : 1;
ChrSizeYField = ((height/divY)+1)>>1;
if (pDramCfg == NULL)
return 0;
if (mapType == TILED_FRAME_V_MAP) {
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 16) { // BITMAIN setting
VerSizePerRas = 64; // Tile (16x2)*(4*2)
Ras1DBit = 1;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 4 && pDramCfg->rasBit == 15) { // BITMAIN setting
VerSizePerRas = 128; // Tile (8x4)*(8x2)
Ras1DBit = 1;
}
else
return 0;
}
else if (mapType == TILED_FRAME_H_MAP) {
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else
return 0;
}
else if (mapType == TILED_FIELD_V_MAP) {
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 16) { // BITMAIN setting
VerSizePerRas = 64; // Tile (16x2)*(4*2)
Ras1DBit = 1;
}
else if (pDramCfg->casBit == 10 && pDramCfg->bankBit == 4 && pDramCfg->rasBit == 15) { // BITMAIN setting
VerSizePerRas = 128; // Tile (8x4)*(8x2)
Ras1DBit = 1;
}
else
return 0;
} else { // TILED_FIELD_H_MAP
if (pDramCfg->casBit == 9 && pDramCfg->bankBit == 2 && pDramCfg->rasBit == 13) { // CNN setting
VerSizePerRas = 64;
Ras1DBit = 3;
}
else if(pDramCfg->casBit == 10 && pDramCfg->bankBit == 3 && pDramCfg->rasBit == 13) {
VerSizePerRas = 64;
Ras1DBit = 2;
}
else
return 0;
}
ChrFieldRasSize = ((ChrSizeYField + (VerSizePerRas-1))/VerSizePerRas) << Ras1DBit;
ChrFrameRasSize = ChrFieldRasSize *2;
size_dpb_chr = (ChrFrameRasSize << (pDramCfg->bankBit+pDramCfg->casBit+pDramCfg->busBit)) / 2; // divide 2 = to calucate one Cb(or Cr) size;
}
else { // productId != 960
chr_size_y = (height>>field_map)/chr_hscale;
chr_size_x = cbcrIntl == TRUE ? stride : stride/chr_vscale;
unit_size_hor_chr = (chr_size_x> 4096) ? 8192:
(chr_size_x> 2048) ? 4096 :
(chr_size_x > 1024) ? 2048 :
(chr_size_x > 512) ? 1024 : 512;
unit_size_ver_chr = ((chr_size_y+63)/64) * 64; // unit vertical size is 64 pixel (4MB)
size_dpb_chr = (format==FORMAT_400) ? 0 : unit_size_hor_chr * (unit_size_ver_chr<<field_map);
size_dpb_chr /= (cbcrIntl == TRUE ? 2 : 1);
}
}
VLOG(INFO, "CalcChromaSize size %d \n", size_dpb_chr);
return size_dpb_chr;
}
#if defined(SUPPORT_SW_UART) || defined(SUPPORT_SW_UART_V2)
#include <string.h>
#include <pthread.h>
typedef struct {
int core_idx;
pthread_t thread_id;
int sw_uart_thread_run;
} SwUartContext;
static SwUartContext s_SwUartContext;
void SwUartHandler(void *context)
{
unsigned int regSwUartStatus;
unsigned int regSwUartTxData;
unsigned char *strRegSwUartTxData;
int i = 0;
char uartTx[1024];
osal_memset(uartTx, 0, sizeof(char)*1024);
while(s_SwUartContext.sw_uart_thread_run == 1)
{
regSwUartStatus = vdi_read_register(s_SwUartContext.core_idx, VP5_SW_UART_STATUS);
if (regSwUartStatus == (unsigned int)-1)
{
continue;
}
if ((regSwUartStatus & (1<<1)))
{
regSwUartTxData = vdi_read_register(s_SwUartContext.core_idx, VP5_SW_UART_TX_DATA);
if (regSwUartTxData == (unsigned int)-1)
{
continue;
}
regSwUartStatus &= ~(1<<1);
vdi_write_register(s_SwUartContext.core_idx, VP5_SW_UART_STATUS, regSwUartStatus);
strRegSwUartTxData = (unsigned char *)&regSwUartTxData;
for (i=0; i < 4; i++)
{
if (strRegSwUartTxData[i] == '\n')
{
VLOG(TRACE, "%s \n", uartTx);
osal_memset(uartTx, 0, sizeof(unsigned char)*1024);
}
else
{
strncat((char *)uartTx, (const char *)(strRegSwUartTxData + i), 1);
}
}
}
}
VLOG(1, "exit SwUartHandler\n");
}
int create_sw_uart_thread(unsigned long coreIdx)
{
int ret;
if (s_SwUartContext.sw_uart_thread_run == 1)
return 1;
vdi_write_register(coreIdx, VP5_SW_UART_STATUS, (1<<0)); // enable SW UART. this will be checked by firmware to know SW UART enabled
s_SwUartContext.core_idx = coreIdx;
s_SwUartContext.sw_uart_thread_run = 1;
ret = pthread_create(&s_SwUartContext.thread_id, NULL, (void*)SwUartHandler, &s_SwUartContext);
if (ret != 0)
{
destory_sw_uart_thread();
return 0;
}
return 1;
}
void destory_sw_uart_thread(unsigned long coreIdx)
{
int inst_num;
int task_num;
int i;
inst_num = 0;
for (i=0; i < MAX_NUM_VPU_CORE; i++)
{
inst_num = inst_num + vdi_get_instance_num(i);
}
if (inst_num > 0)
return;
task_num = 0;
for (i=0; i < MAX_NUM_VPU_CORE; i++)
{
task_num = task_num + vdi_get_task_num(i);
}
if (task_num > 1)
return;
if (s_SwUartContext.sw_uart_thread_run == 1)
{
s_SwUartContext.sw_uart_thread_run = 0;
vdi_write_register(coreIdx, VP5_SW_UART_STATUS, 0); // disable SW UART. this will be checked by firmware to know SW UART enabled
if (s_SwUartContext.thread_id)
{
pthread_join(s_SwUartContext.thread_id, NULL);
s_SwUartContext.thread_id = 0;
}
}
return ;
}
#endif