/* * 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> 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= 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 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); size_dpb_lum_4k = ((size_dpb_lum+(16384-1))/16384)*16384; size_dpb_lum = size_dpb_lum_4k<>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<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))/(chr_hscale*chr_vscale)); size_dpb_chr_4k = ((size_dpb_chr+(16384-1))/16384)*16384; size_dpb_chr = size_dpb_chr_4k<>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< #include 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 *)®SwUartTxData; 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