1233 lines
36 KiB
C
Executable File
1233 lines
36 KiB
C
Executable File
/*
|
|
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
|
|
* All rights reserved.
|
|
*
|
|
* File : layerControl_de.cpp
|
|
* Description : Display2
|
|
* History :
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <string.h>
|
|
#include "cdx_config.h"
|
|
#include <cdx_log.h>
|
|
#include "layerControl.h"
|
|
#include <ion_mem_alloc.h>
|
|
#include <videoOutPort.h>
|
|
#include "iniparserapi.h"
|
|
#include "tdisp_ctrl.h"
|
|
#include "sunxi_tr.h"
|
|
#define SAVE_PIC (0)
|
|
|
|
#define GPU_BUFFER_NUM 32
|
|
|
|
static VideoPicture* gLastPicture = NULL;
|
|
|
|
#define BUF_MANAGE (0)
|
|
|
|
#define NUM_OF_PICTURES_KEEP_IN_NODE (GetConfigParamterInt("pic_4list_num", 3)+1)
|
|
|
|
//#define ROTATE_BUFFER_NUM GetConfigParamterInt("pic_4rotate_num", 3)
|
|
#define ROTATE_BUFFER_NUM 3
|
|
#define TRANSFORM_DEV_TIMEOUT 200
|
|
#define ALIGN_32B(x) (((x) + (31)) & ~(31))
|
|
#define ALIGN_16B(x) (((x) + (15)) & ~(15))
|
|
|
|
|
|
int LayerCtrlHideVideo(LayerCtrl* l);
|
|
|
|
typedef struct VPictureNode_t VPictureNode;
|
|
struct VPictureNode_t
|
|
{
|
|
VideoPicture* pPicture;
|
|
VPictureNode* pNext;
|
|
int bUsed;
|
|
};
|
|
|
|
typedef struct BufferInfoS
|
|
{
|
|
VideoPicture pPicture;
|
|
int nUsedFlag;
|
|
}BufferInfoT;
|
|
|
|
typedef enum {
|
|
NORMAL_PICTURE_BUF = 0x00,
|
|
LAST_PICTURE_BUF = 0x01,
|
|
} LayerBufMode;
|
|
|
|
typedef struct LayerContext
|
|
{
|
|
LayerCtrl base;
|
|
dispOutPort *mDispOutPort;
|
|
enum EPIXELFORMAT eDisplayPixelFormat;
|
|
int nWidth;
|
|
int nHeight;
|
|
int nLeftOff;
|
|
int nTopOff;
|
|
int nDisplayWidth;
|
|
int nDisplayHeight;
|
|
int bHoldLastPictureFlag;
|
|
int bVideoWithTwoStreamFlag;
|
|
int bIsSoftDecoderFlag;
|
|
int bLayerInitialized;
|
|
int bProtectFlag;
|
|
int setSrcRectFlag;
|
|
int setDstRectFlag;
|
|
VoutRect src_rect;
|
|
VoutRect dst_rect;
|
|
struct SunxiMemOpsS *pMemops;
|
|
|
|
//* use when render derect to hardware layer.
|
|
VPictureNode* pPictureListHeader;
|
|
VPictureNode picNodes[16];
|
|
|
|
int nGpuBufferCount;
|
|
BufferInfoT mBufferInfo[GPU_BUFFER_NUM];
|
|
int bLayerShowed;
|
|
|
|
int fdDisplay;
|
|
int nScreenWidth;
|
|
int nScreenHeight;
|
|
VideoFrameCallback mVideoframeCallback;
|
|
void* pUserData;
|
|
|
|
BufferInfoT mRotateBufInfo[ROTATE_BUFFER_NUM];
|
|
int mTransformFd;
|
|
int mInitedTransformFlag;
|
|
unsigned long mTransformChannel;
|
|
int mCreateRotateBufFlag;
|
|
|
|
|
|
VideoPicture mTmpCurPicture;
|
|
VideoPicture mCurPicture;
|
|
int mHoldLastPictureFlag;
|
|
}LayerContext;
|
|
|
|
/* set usage, scaling_mode, pixelFormat, buffers_geometry, buffers_count, crop */
|
|
static int setLayerBuffer(LayerContext* lc,LayerBufMode mode)
|
|
{
|
|
int pixelFormat;
|
|
unsigned int nGpuBufWidth;
|
|
unsigned int nGpuBufHeight;
|
|
unsigned int nGpuBufWidthAlign32;
|
|
unsigned int nGpuBufHeightAlign64;
|
|
int i = 0;
|
|
char* pVirBuf;
|
|
char* pPhyBuf;
|
|
uintptr_t ve_offset;
|
|
const char *vd_platform;
|
|
int nBufferFd = 0;
|
|
printf("%s:Fmt(%d),(%d %d, %d x %d)",
|
|
__FUNCTION__, lc->eDisplayPixelFormat, lc->nWidth,
|
|
lc->nHeight, lc->nLeftOff, lc->nTopOff);
|
|
printf("Disp(%dx%d)buf_cnt(%d),ProFlag(%d),SoftDecFlag(%d)",
|
|
lc->nDisplayWidth, lc->nDisplayHeight, lc->nGpuBufferCount,
|
|
lc->bProtectFlag, lc->bIsSoftDecoderFlag);
|
|
nGpuBufWidth = lc->nWidth;
|
|
nGpuBufHeight = lc->nHeight;
|
|
nGpuBufWidthAlign32 = ((nGpuBufWidth + 31) & ~31);
|
|
nGpuBufHeightAlign64 = ((nGpuBufHeight + 63) & ~63);
|
|
|
|
/* We should double the height if the video with two stream,
|
|
* so the nativeWindow will malloc double buffer
|
|
*/
|
|
if(lc->bVideoWithTwoStreamFlag == 1)
|
|
{
|
|
nGpuBufHeight = 2*nGpuBufHeight;
|
|
}
|
|
|
|
if(lc->nGpuBufferCount <= 0)
|
|
{
|
|
printf("error: the lc->nGpuBufferCount[%d] is invalid!",lc->nGpuBufferCount);
|
|
return -1;
|
|
}
|
|
|
|
vd_platform = GetConfigParamterString("platform", NULL);
|
|
logv("platform NULL, pls check your config.");
|
|
if (strcmp(vd_platform, "azalea") == 0) {
|
|
ve_offset = 0x40000000;
|
|
}
|
|
else if (strcmp(vd_platform, "astar") == 0) {
|
|
ve_offset = 0;
|
|
}
|
|
else if (strcmp(vd_platform, "banjo") == 0) {
|
|
ve_offset = 0;
|
|
}
|
|
else if (strcmp(vd_platform, "bassoon") == 0) {
|
|
ve_offset = 0;
|
|
}
|
|
else if (strcmp(vd_platform, "boobam") == 0) {
|
|
ve_offset = 0;
|
|
}
|
|
else if (strcmp(vd_platform, "cello") == 0) {
|
|
ve_offset = 0;
|
|
}
|
|
else if (strcmp(vd_platform, "octopus") == 0) {
|
|
ve_offset = 0;
|
|
}
|
|
else if (strcmp(vd_platform, "sitar") == 0) {
|
|
ve_offset = 0;
|
|
}else if (strcmp(vd_platform, "violin") == 0) {
|
|
ve_offset = 0;
|
|
}else if (strcmp(vd_platform, "koto") == 0) {
|
|
ve_offset = 0;
|
|
}else if (strcmp(vd_platform, "tulip") == 0) {
|
|
ve_offset = 0x40000000;
|
|
}else if (strcmp(vd_platform, "mandolin") == 0) {
|
|
ve_offset = 0;
|
|
}else {
|
|
loge("invalid config '%s', pls check your cedarx.conf.",
|
|
vd_platform);
|
|
}
|
|
if(mode == NORMAL_PICTURE_BUF){
|
|
//logd("setLayerBuffer:lc->eDisplayPixelFormat = %d,nGpuBufferCount = %d",lc->eDisplayPixelFormat,lc->nGpuBufferCount);
|
|
for(i=0; i<lc->nGpuBufferCount; i++)
|
|
{
|
|
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
pVirBuf = (char*)SunxiMemPalloc(lc->pMemops, nGpuBufWidthAlign32 * nGpuBufHeight + nGpuBufWidth*nGpuBufHeightAlign64/2);
|
|
else
|
|
pVirBuf = (char*)SunxiMemPalloc(lc->pMemops, nGpuBufWidth * nGpuBufHeight * 3/2);
|
|
#ifdef CONF_KERNEL_IOMMU
|
|
nBufferFd = SunxiMemGetBufferFd(lc->pMemops,pVirBuf);
|
|
#else
|
|
pPhyBuf = (char*)SunxiMemGetPhysicAddressCpu(lc->pMemops, pVirBuf) + ve_offset;
|
|
#endif
|
|
lc->mBufferInfo[i].nUsedFlag = 0;
|
|
|
|
lc->mBufferInfo[i].pPicture.nWidth = lc->nWidth;
|
|
lc->mBufferInfo[i].pPicture.nHeight = lc->nHeight;
|
|
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
lc->mBufferInfo[i].pPicture.nLineStride = nGpuBufWidthAlign32;
|
|
else
|
|
lc->mBufferInfo[i].pPicture.nLineStride = lc->nWidth;
|
|
lc->mBufferInfo[i].pPicture.pData0 = pVirBuf;
|
|
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
{
|
|
lc->mBufferInfo[i].pPicture.pData1 = pVirBuf + (nGpuBufWidthAlign32 * nGpuBufHeight);
|
|
lc->mBufferInfo[i].pPicture.pData2 = NULL;
|
|
}
|
|
else
|
|
{
|
|
lc->mBufferInfo[i].pPicture.pData1 = pVirBuf + (lc->nHeight * lc->nWidth);
|
|
lc->mBufferInfo[i].pPicture.pData2 =
|
|
lc->mBufferInfo[i].pPicture.pData1 + (lc->nHeight * lc->nWidth)/4;
|
|
}
|
|
#ifdef CONF_KERNEL_IOMMU
|
|
lc->mBufferInfo[i].pPicture.nBufFd = nBufferFd;
|
|
#else
|
|
lc->mBufferInfo[i].pPicture.phyYBufAddr = (uintptr_t)pPhyBuf;
|
|
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
{
|
|
lc->mBufferInfo[i].pPicture.phyCBufAddr =
|
|
lc->mBufferInfo[i].pPicture.phyYBufAddr + (nGpuBufWidthAlign32 * nGpuBufHeight);
|
|
}
|
|
else
|
|
{
|
|
lc->mBufferInfo[i].pPicture.phyCBufAddr =
|
|
lc->mBufferInfo[i].pPicture.phyYBufAddr + (lc->nHeight * lc->nWidth);
|
|
}
|
|
#endif
|
|
lc->mBufferInfo[i].pPicture.nBufId = i;
|
|
lc->mBufferInfo[i].pPicture.ePixelFormat = lc->eDisplayPixelFormat;
|
|
}
|
|
}else if(mode == LAST_PICTURE_BUF){
|
|
nGpuBufWidth = lc->mTmpCurPicture.nWidth;
|
|
nGpuBufHeight = lc->mTmpCurPicture.nHeight;
|
|
nGpuBufWidthAlign32 = ((nGpuBufWidth + 31) & ~31);
|
|
nGpuBufHeightAlign64 = ((nGpuBufHeight + 63) & ~63);
|
|
memcpy(&lc->mCurPicture,&lc->mTmpCurPicture,sizeof(VideoPicture));
|
|
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YUV_MB32_420){
|
|
pVirBuf = (char*)SunxiMemPalloc(lc->pMemops, nGpuBufWidthAlign32 * nGpuBufHeight + nGpuBufWidth*nGpuBufHeightAlign64/2);
|
|
if(pVirBuf && lc->mTmpCurPicture.pData0){
|
|
memcpy(pVirBuf,lc->mTmpCurPicture.pData0,nGpuBufWidthAlign32 * nGpuBufHeight + nGpuBufWidth*nGpuBufHeightAlign64/2);
|
|
SunxiMemFlushCache(lc->pMemops, pVirBuf, nGpuBufWidthAlign32 * nGpuBufHeight + nGpuBufWidth*nGpuBufHeightAlign64/2);
|
|
}
|
|
}else{
|
|
pVirBuf = (char*)SunxiMemPalloc(lc->pMemops, nGpuBufWidth * nGpuBufHeight * 3/2);
|
|
if(pVirBuf && lc->mTmpCurPicture.pData0){
|
|
memcpy(pVirBuf,lc->mTmpCurPicture.pData0,nGpuBufWidth * nGpuBufHeight * 3/2);
|
|
SunxiMemFlushCache(lc->pMemops, pVirBuf, nGpuBufWidth * nGpuBufHeight * 3/2);
|
|
}
|
|
}
|
|
lc->mCurPicture.pData0 = pVirBuf;
|
|
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
{
|
|
lc->mCurPicture.pData1 = pVirBuf + (nGpuBufWidthAlign32 * nGpuBufHeight);
|
|
lc->mCurPicture.pData2 = NULL;
|
|
}
|
|
else
|
|
{
|
|
lc->mCurPicture.pData1 = pVirBuf + (lc->nHeight * lc->nWidth);
|
|
lc->mCurPicture.pData2 =
|
|
lc->mCurPicture.pData1 + (lc->nHeight * lc->nWidth)/4;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int SetLayerParam(LayerContext* lc, VideoPicture* pPicture,LayerBufMode mode)
|
|
{
|
|
unsigned int args[4];
|
|
unsigned int fbAddr[3];
|
|
videoParam vparam;
|
|
renderBuf rBuf;
|
|
int ret = 0;
|
|
//* close the layer first, otherwise, in case when last frame is kept showing,
|
|
//* the picture showed will not valid because parameters changed.
|
|
if(lc->bLayerShowed == 1)
|
|
{
|
|
lc->bLayerShowed = 0;
|
|
}
|
|
memcpy(&lc->mTmpCurPicture,pPicture,sizeof(VideoPicture));//store the current picture info
|
|
fbAddr[0] = (unsigned long)SunxiMemGetPhysicAddressCpu(lc->pMemops,
|
|
pPicture->pData0);
|
|
fbAddr[1] = (unsigned long)SunxiMemGetPhysicAddressCpu(lc->pMemops,
|
|
pPicture->pData1);
|
|
fbAddr[2] = (unsigned long)SunxiMemGetPhysicAddressCpu(lc->pMemops,
|
|
pPicture->pData2);
|
|
|
|
vparam.srcInfo.crop_x = pPicture->nLeftOffset;
|
|
vparam.srcInfo.crop_y = pPicture->nTopOffset;
|
|
vparam.srcInfo.crop_w = pPicture->nRightOffset - pPicture->nLeftOffset;
|
|
vparam.srcInfo.crop_h = pPicture->nBottomOffset - pPicture->nTopOffset;
|
|
|
|
vparam.srcInfo.w = pPicture->nWidth;
|
|
vparam.srcInfo.h = pPicture->nHeight;
|
|
vparam.srcInfo.format = pPicture->ePixelFormat;
|
|
vparam.srcInfo.color_space = VIDEO_BT601;
|
|
rBuf.y_phaddr = fbAddr[0];
|
|
rBuf.u_phaddr = fbAddr[1];
|
|
rBuf.v_phaddr = fbAddr[2];
|
|
rBuf.isExtPhy = VIDEO_USE_EXTERN_ION_BUF;
|
|
lc->mDispOutPort->queueToDisplay(lc->mDispOutPort,vparam.srcInfo.w*vparam.srcInfo.h*3/2, &vparam, &rBuf);
|
|
lc->mDispOutPort->SetZorder(lc->mDispOutPort, VIDEO_ZORDER_BOTTOM);
|
|
lc->mDispOutPort->setEnable(lc->mDispOutPort, 1);
|
|
|
|
/*free the last frame in last video*/
|
|
if(mode == NORMAL_PICTURE_BUF){
|
|
if(lc->mCurPicture.pData0){
|
|
SunxiMemPfree(lc->pMemops, lc->mCurPicture.pData0);
|
|
lc->mCurPicture.pData0 = NULL;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerReset(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
int i;
|
|
|
|
logd("__LayerReset.");
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
for(i=0; i<lc->nGpuBufferCount; i++)
|
|
{
|
|
SunxiMemPfree(lc->pMemops, lc->mBufferInfo[i].pPicture.pData0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __LayerRelease(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
int i;
|
|
int j;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
logd("__LayerRelease,lc->mHoldLastPictureFlag = %d",lc->mHoldLastPictureFlag);
|
|
if(lc->mHoldLastPictureFlag){
|
|
setLayerBuffer(lc,LAST_PICTURE_BUF);
|
|
SetLayerParam(lc, &lc->mCurPicture,LAST_PICTURE_BUF);
|
|
}
|
|
for(i=0; i<lc->nGpuBufferCount; i++)
|
|
{
|
|
SunxiMemPfree(lc->pMemops, lc->mBufferInfo[i].pPicture.pData0);
|
|
}
|
|
if(GetConfigParamterInt("tr_rotate_flag",0) == 1){
|
|
for(j = 0 ; j < ROTATE_BUFFER_NUM;j++){
|
|
if(lc->mRotateBufInfo[j].pPicture.pData0){
|
|
SunxiMemPfree(lc->pMemops, lc->mRotateBufInfo[j].pPicture.pData0);
|
|
lc->mRotateBufInfo[j].pPicture.pData0 = NULL;
|
|
}
|
|
}
|
|
lc->mCreateRotateBufFlag = 0;
|
|
}
|
|
}
|
|
|
|
static void __LayerDestroy(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
int i;
|
|
logd("__LayerDestroy");
|
|
lc = (LayerContext*)l;
|
|
if(lc->mCurPicture.pData0){
|
|
SunxiMemPfree(lc->pMemops, lc->mCurPicture.pData0);
|
|
lc->mCurPicture.pData0 = NULL;
|
|
}
|
|
lc->mDispOutPort->deinit(lc->mDispOutPort);
|
|
SunxiMemClose(lc->pMemops);
|
|
|
|
free(lc);
|
|
}
|
|
|
|
static int __LayerSetDisplayBufferSize(LayerCtrl* l, int nWidth, int nHeight)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
lc->nWidth = nWidth;
|
|
lc->nHeight = nHeight;
|
|
lc->nDisplayWidth = nWidth;
|
|
lc->nDisplayHeight = nHeight;
|
|
lc->nLeftOff = 0;
|
|
lc->nTopOff = 0;
|
|
lc->bLayerInitialized = 0;
|
|
logd("__LayerSetDisplayBufferSize:width = %d,height = %d",nWidth,nHeight);
|
|
if(lc->bVideoWithTwoStreamFlag == 1)
|
|
{
|
|
/* display the whole buffer region when 3D
|
|
* as we had init align-edge-region to black. so it will be look ok.
|
|
*/
|
|
int nScaler = 2;
|
|
lc->nDisplayHeight = lc->nDisplayHeight*nScaler;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Description: set initial param -- display region */
|
|
static int __LayerSetDisplayRegion(LayerCtrl* l, int nLeftOff, int nTopOff,
|
|
int nDisplayWidth, int nDisplayHeight)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
logv("Layer set display region,(%d %d, %dx%d)\n",
|
|
nLeftOff, nTopOff, nDisplayWidth, nDisplayHeight);
|
|
|
|
if(nDisplayWidth == 0 && nDisplayHeight == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
lc->nDisplayWidth = nDisplayWidth;
|
|
lc->nDisplayHeight = nDisplayHeight;
|
|
lc->nLeftOff = nLeftOff;
|
|
lc->nTopOff = nTopOff;
|
|
|
|
if(lc->bVideoWithTwoStreamFlag == 1)
|
|
{
|
|
int nScaler = 2;
|
|
lc->nDisplayHeight = lc->nHeight*nScaler;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Description: set initial param -- display pixelFormat */
|
|
static int __LayerSetDisplayPixelFormat(LayerCtrl* l, enum EPIXELFORMAT ePixelFormat)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
logd("Layer set expected pixel format, format = %d", (int)ePixelFormat);
|
|
|
|
if(ePixelFormat == PIXEL_FORMAT_NV12 ||
|
|
ePixelFormat == PIXEL_FORMAT_NV21 ||
|
|
ePixelFormat == PIXEL_FORMAT_YV12 ||
|
|
ePixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
{
|
|
lc->eDisplayPixelFormat = ePixelFormat;
|
|
}
|
|
else
|
|
{
|
|
logv("receive pixel format is %d, not match.", lc->eDisplayPixelFormat);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//* Description: set initial param -- deinterlace flag
|
|
static int __LayerSetDeinterlaceFlag(LayerCtrl* l,int bFlag)
|
|
{
|
|
LayerContext* lc;
|
|
(void)bFlag;
|
|
lc = (LayerContext*)l;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//* Description: set buffer timestamp -- set this param every frame
|
|
static int __LayerSetBufferTimeStamp(LayerCtrl* l, int64_t nPtsAbs)
|
|
{
|
|
LayerContext* lc;
|
|
(void)nPtsAbs;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerGetRotationAngle(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
int nRotationAngle = 0;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerCtrlShowVideo(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
int i;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
lc->bLayerShowed = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerCtrlHideVideo(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
int i;
|
|
|
|
lc = (LayerContext*)l;
|
|
logd("__LayerCtrlHideVideo");
|
|
lc->bLayerShowed = 0;
|
|
lc->mDispOutPort->setEnable(lc->mDispOutPort, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerCtrlIsVideoShow(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
logd("__LayerCtrlIsVideoShow");
|
|
return lc->bLayerShowed;
|
|
}
|
|
|
|
static int __LayerCtrlHoldLastPicture(LayerCtrl* l, int bHold)
|
|
{
|
|
logd("LayerCtrlHoldLastPicture, bHold = %d", bHold);
|
|
|
|
LayerContext* lc;
|
|
lc = (LayerContext*)l;
|
|
lc->mHoldLastPictureFlag = bHold;
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerDequeueBuffer(LayerCtrl* l, VideoPicture** ppVideoPicture, int bInitFlag)
|
|
{
|
|
LayerContext* lc;
|
|
int i = 0;
|
|
VPictureNode* nodePtr;
|
|
BufferInfoT bufInfo;
|
|
VideoPicture* pPicture = NULL;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
if(lc->bLayerInitialized == 0)
|
|
{
|
|
if(setLayerBuffer(lc,NORMAL_PICTURE_BUF) != 0)
|
|
{
|
|
loge("can not initialize layer.");
|
|
return -1;
|
|
}
|
|
|
|
lc->bLayerInitialized = 1;
|
|
}
|
|
|
|
if(bInitFlag == 1)
|
|
{
|
|
for(i = 0; i < lc->nGpuBufferCount; i++)
|
|
{
|
|
if(lc->mBufferInfo[i].nUsedFlag == 0)
|
|
{
|
|
//* set the buffer address
|
|
pPicture = *ppVideoPicture;
|
|
pPicture = &lc->mBufferInfo[i].pPicture;
|
|
|
|
lc->mBufferInfo[i].nUsedFlag = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(lc->pPictureListHeader != NULL)
|
|
{
|
|
nodePtr = lc->pPictureListHeader;
|
|
i=1;
|
|
while(nodePtr->pNext != NULL)
|
|
{
|
|
i++;
|
|
nodePtr = nodePtr->pNext;
|
|
}
|
|
|
|
unsigned int args[3];
|
|
//* return one picture.
|
|
if(i > GetConfigParamterInt("pic_4list_num", 3))
|
|
{
|
|
nodePtr = lc->pPictureListHeader;
|
|
lc->pPictureListHeader = lc->pPictureListHeader->pNext;
|
|
pPicture = nodePtr->pPicture;
|
|
nodePtr->bUsed = 0;
|
|
i--;
|
|
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
logd("llh>>> dequeue pPicture(%p)",pPicture);
|
|
if(pPicture != NULL){
|
|
logd("llh>>> dequeue pPicture(%p),pPicture->nStreamIndex = %d,pPicture->nID = %d,pPicture->nBufId = %d",
|
|
pPicture,pPicture->nStreamIndex,pPicture->nID,pPicture->nBufId);
|
|
}
|
|
*/
|
|
*ppVideoPicture = pPicture;
|
|
if(pPicture == NULL)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
// this method should block here,
|
|
static int __LayerQueueBuffer(LayerCtrl* l, VideoPicture* pBuf, int bValid)
|
|
{
|
|
LayerContext* lc = NULL;
|
|
|
|
int i;
|
|
VPictureNode* newNode;
|
|
VPictureNode* nodePtr;
|
|
BufferInfoT bufInfo;
|
|
|
|
lc = (LayerContext*)l;
|
|
/*
|
|
logd("llh>>>queue , pPicture(%p)", pBuf);
|
|
if(pBuf != NULL){
|
|
logd("llh>>>queue , pPicture(%p),pBuf->nStreamIndex = %d ,pBuf->nID = %d ,pBuf->nBufId = %d",
|
|
pBuf,pBuf->nStreamIndex,pBuf->nID,pBuf->nBufId);
|
|
}
|
|
*/
|
|
int index = 0;
|
|
int rotateDegree = 0;
|
|
|
|
if(bValid == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
lc->mVideoframeCallback(lc->pUserData,pBuf);
|
|
if(lc->bLayerInitialized == 0)
|
|
{
|
|
if(setLayerBuffer(lc,NORMAL_PICTURE_BUF) != 0)
|
|
{
|
|
loge("can not initialize layer.");
|
|
return -1;
|
|
}
|
|
|
|
lc->bLayerInitialized = 1;
|
|
}
|
|
if(GetConfigParamterInt("tr_rotate_flag",0) == 1){
|
|
rotateDegree = GetConfigParamterInt("tr_rotate_degree",0);
|
|
if(lc->mCreateRotateBufFlag == 0){
|
|
|
|
if(rotateDegree == 90 || rotateDegree == 270){
|
|
createRotateBuf( l,pBuf->nHeight,pBuf->nWidth);
|
|
lc->base.ops->setDisplayRegion(l,0,0,pBuf->nHeight,pBuf->nWidth);
|
|
}else if(rotateDegree == 0 || rotateDegree == 180){
|
|
createRotateBuf( l,pBuf->nWidth,pBuf->nHeight);
|
|
lc->base.ops->setDisplayRegion(l,0,0,pBuf->nWidth,pBuf->nHeight);
|
|
}else{
|
|
logw("the rotateDegree = %d,which is not support,set it to 90",rotateDegree);
|
|
createRotateBuf( l,pBuf->nHeight,pBuf->nWidth);
|
|
lc->base.ops->setDisplayRegion(l,0,0,pBuf->nHeight,pBuf->nWidth);
|
|
}
|
|
lc->mCreateRotateBufFlag = 1;
|
|
|
|
}
|
|
static long long count = 0;
|
|
index = count % ROTATE_BUFFER_NUM;
|
|
hwRotateVideoPicture(l,pBuf,&lc->mRotateBufInfo[index].pPicture,rotateDegree);
|
|
count++;
|
|
|
|
if(SetLayerParam(lc, &lc->mRotateBufInfo[index].pPicture,NORMAL_PICTURE_BUF) != 0)
|
|
{
|
|
loge("can not initialize layer.");
|
|
return -1;
|
|
}
|
|
}else{
|
|
lc->base.ops->setDisplayRegion(l,0,0,pBuf->nWidth,pBuf->nHeight);
|
|
if(SetLayerParam(lc, pBuf,NORMAL_PICTURE_BUF) != 0)
|
|
{
|
|
loge("can not initialize layer.");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// *****************************************
|
|
// *****************************************
|
|
// TODO: Display this video picture here () blocking
|
|
//
|
|
// *****************************************
|
|
|
|
newNode = NULL;
|
|
for(i = 0; i < NUM_OF_PICTURES_KEEP_IN_NODE; i++)
|
|
{
|
|
if(lc->picNodes[i].bUsed == 0)
|
|
{
|
|
newNode = &lc->picNodes[i];
|
|
newNode->pNext = NULL;
|
|
newNode->bUsed = 1;
|
|
newNode->pPicture = pBuf;
|
|
break;
|
|
}
|
|
}
|
|
if(i == NUM_OF_PICTURES_KEEP_IN_NODE)
|
|
{
|
|
loge("*** picNode is full when queue buffer");
|
|
return -1;
|
|
}
|
|
|
|
if(lc->pPictureListHeader != NULL)
|
|
{
|
|
nodePtr = lc->pPictureListHeader;
|
|
while(nodePtr->pNext != NULL)
|
|
{
|
|
nodePtr = nodePtr->pNext;
|
|
}
|
|
nodePtr->pNext = newNode;
|
|
}
|
|
else
|
|
{
|
|
lc->pPictureListHeader = newNode;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerSetDisplayBufferCount(LayerCtrl* l, int nBufferCount)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
logd("LayerSetBufferCount: count = %d",nBufferCount);
|
|
|
|
lc->nGpuBufferCount = nBufferCount;
|
|
|
|
if(lc->nGpuBufferCount > GPU_BUFFER_NUM)
|
|
lc->nGpuBufferCount = GPU_BUFFER_NUM;
|
|
|
|
return lc->nGpuBufferCount;
|
|
}
|
|
|
|
static int __LayerGetBufferNumHoldByGpu(LayerCtrl* l)
|
|
{
|
|
(void)l;
|
|
return GetConfigParamterInt("pic_4list_num", 3);
|
|
}
|
|
|
|
static int __LayerGetDisplayFPS(LayerCtrl* l)
|
|
{
|
|
(void)l;
|
|
return 60;
|
|
}
|
|
|
|
static void __LayerResetNativeWindow(LayerCtrl* l,void* pNativeWindow)
|
|
{
|
|
logd("LayerResetNativeWindow : %p ",pNativeWindow);
|
|
|
|
LayerContext* lc;
|
|
VideoPicture mPicBufInfo;
|
|
|
|
lc = (LayerContext*)l;
|
|
lc->bLayerInitialized = 0;
|
|
|
|
return ;
|
|
}
|
|
|
|
static VideoPicture* __LayerGetBufferOwnedByGpu(LayerCtrl* l)
|
|
{
|
|
LayerContext* lc;
|
|
VideoPicture* pPicture = NULL;
|
|
BufferInfoT bufInfo;
|
|
|
|
lc = (LayerContext*)l;
|
|
int i;
|
|
VPictureNode* nodePtr;
|
|
if(lc->pPictureListHeader != NULL)
|
|
{
|
|
nodePtr = lc->pPictureListHeader;
|
|
lc->pPictureListHeader = lc->pPictureListHeader->pNext;
|
|
pPicture = nodePtr->pPicture;
|
|
nodePtr->bUsed = 0;
|
|
}
|
|
return pPicture;
|
|
}
|
|
|
|
static int __LayerSetVideoWithTwoStreamFlag(LayerCtrl* l, int bVideoWithTwoStreamFlag)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
logv("LayerSetIsTwoVideoStreamFlag, flag = %d",bVideoWithTwoStreamFlag);
|
|
lc->bVideoWithTwoStreamFlag = bVideoWithTwoStreamFlag;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerSetIsSoftDecoderFlag(LayerCtrl* l, int bIsSoftDecoderFlag)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
logv("LayerSetIsSoftDecoderFlag, flag = %d",bIsSoftDecoderFlag);
|
|
lc->bIsSoftDecoderFlag = bIsSoftDecoderFlag;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//* Description: the picture buf is secure
|
|
static int __LayerSetSecure(LayerCtrl* l, int bSecure)
|
|
{
|
|
logv("__LayerSetSecure, bSecure = %d", bSecure);
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
lc->bProtectFlag = bSecure;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerReleaseBuffer(LayerCtrl* l, VideoPicture* pPicture)
|
|
{
|
|
logd("LayerReleaseBuffer,pPicture = %p",pPicture);
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
SunxiMemPfree(lc->pMemops, pPicture->pData0);
|
|
return 0;
|
|
}
|
|
|
|
static int __LayerControl(LayerCtrl* l, int cmd, void *para)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
|
|
logd("layer control cmd = %d",cmd);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static LayerControlOpsT mLayerControlOps =
|
|
{
|
|
release: __LayerRelease ,
|
|
|
|
setSecureFlag: __LayerSetSecure ,
|
|
setDisplayBufferSize: __LayerSetDisplayBufferSize ,
|
|
setDisplayBufferCount: __LayerSetDisplayBufferCount ,
|
|
setDisplayRegion: __LayerSetDisplayRegion ,
|
|
setDisplayPixelFormat: __LayerSetDisplayPixelFormat ,
|
|
setVideoWithTwoStreamFlag: __LayerSetVideoWithTwoStreamFlag ,
|
|
setIsSoftDecoderFlag: __LayerSetIsSoftDecoderFlag ,
|
|
setBufferTimeStamp: __LayerSetBufferTimeStamp ,
|
|
|
|
resetNativeWindow : __LayerResetNativeWindow ,
|
|
getBufferOwnedByGpu: __LayerGetBufferOwnedByGpu ,
|
|
getDisplayFPS: __LayerGetDisplayFPS ,
|
|
getBufferNumHoldByGpu: __LayerGetBufferNumHoldByGpu ,
|
|
|
|
ctrlShowVideo : __LayerCtrlShowVideo ,
|
|
ctrlHideVideo: __LayerCtrlHideVideo ,
|
|
ctrlIsVideoShow: __LayerCtrlIsVideoShow ,
|
|
ctrlHoldLastPicture : __LayerCtrlHoldLastPicture ,
|
|
|
|
dequeueBuffer: __LayerDequeueBuffer ,
|
|
queueBuffer: __LayerQueueBuffer ,
|
|
releaseBuffer: __LayerReleaseBuffer ,
|
|
reset: __LayerReset ,
|
|
destroy: __LayerDestroy,
|
|
control: __LayerControl,
|
|
};
|
|
|
|
LayerCtrl* LayerCreate(VideoFrameCallback callback,void* pUser)
|
|
{
|
|
LayerContext* lc;
|
|
unsigned int args[4];
|
|
int screen_id;
|
|
int enable = 0;
|
|
int rotate = 0;
|
|
VoutRect rect;
|
|
logd("LayerCreate.");
|
|
|
|
lc = (LayerContext*)malloc(sizeof(LayerContext));
|
|
if(lc == NULL)
|
|
{
|
|
loge("malloc memory fail.");
|
|
return NULL;
|
|
}
|
|
memset(lc, 0, sizeof(LayerContext));
|
|
lc->mDispOutPort = CreateVideoOutport(0);
|
|
rect.x = 0;
|
|
rect.y = 0;
|
|
rect.width = 320;
|
|
rect.height = 240;
|
|
lc->mDispOutPort->init(lc->mDispOutPort, enable, rotate, &rect);
|
|
lc->base.ops = &mLayerControlOps;
|
|
lc->eDisplayPixelFormat = PIXEL_FORMAT_NV21;
|
|
|
|
lc->mVideoframeCallback = callback;
|
|
lc->pUserData = pUser;
|
|
logd("==== callback: %p, pUser: %p", callback, pUser);
|
|
|
|
|
|
/* get screen size. */
|
|
lc->nScreenWidth = lc->mDispOutPort->getScreenWidth(lc->mDispOutPort);
|
|
lc->nScreenHeight = lc->mDispOutPort->getScreenHeight(lc->mDispOutPort);
|
|
rect.x = 0;
|
|
rect.y = 0;
|
|
rect.width = lc->nScreenWidth;
|
|
rect.height = lc->nScreenHeight;
|
|
lc->mDispOutPort->setRect(lc->mDispOutPort,&rect);
|
|
logd("screen:w %d, screen:h %d", lc->nScreenWidth, lc->nScreenHeight);
|
|
|
|
lc->pMemops = GetMemAdapterOpsS();
|
|
SunxiMemOpen(lc->pMemops);
|
|
|
|
return &lc->base;
|
|
}
|
|
|
|
void LayerSetControl(LayerCtrl* l, LAYER_CMD_TYPE cmd, int grade)
|
|
{
|
|
LayerContext* lc;
|
|
int i;
|
|
|
|
lc = (LayerContext*)l;
|
|
switch(cmd){
|
|
case VIDEO_CMD_SET_BRIGHTNESS:
|
|
case VIDEO_CMD_SET_CONTRAST:
|
|
case VIDEO_CMD_SET_HUE:
|
|
case VIDEO_CMD_SET_SATURATION:
|
|
case VIDEO_CMD_SET_VEDIO_ENHANCE_DEFAULT:
|
|
lc->mDispOutPort->setIoctl(lc->mDispOutPort, cmd, grade);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int LayerSetSrcRect(LayerCtrl* l, int x, int y, unsigned int width, unsigned int height)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
logd("Layer set src rect,(%d %d, %dx%d)\n",
|
|
x, y, width, height);
|
|
|
|
if(width == 0 && height == 0)
|
|
return -1;
|
|
|
|
lc->src_rect.x = x;
|
|
lc->src_rect.x = y;
|
|
lc->src_rect.width = width;
|
|
lc->src_rect.height = height;
|
|
lc->setSrcRectFlag = 1;
|
|
lc->mDispOutPort->setSrcRect(lc->mDispOutPort, &lc->src_rect);
|
|
|
|
return 0;
|
|
}
|
|
int LayerSetDisplayRect(LayerCtrl* l, int x, int y, unsigned int width, unsigned int height)
|
|
{
|
|
LayerContext* lc;
|
|
lc = (LayerContext*)l;
|
|
logd("Layer set display rect,(%d %d, %dx%d)\n",
|
|
x, y, width, height);
|
|
if(width == 0 && height == 0)
|
|
return -1;
|
|
lc->dst_rect.x = x;
|
|
lc->dst_rect.x = y;
|
|
lc->dst_rect.width = width;
|
|
lc->dst_rect.height = height;
|
|
lc->setDstRectFlag = 1;
|
|
lc->mDispOutPort->setRect(lc->mDispOutPort, &lc->dst_rect);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int LayerDisplayOnoff(LayerCtrl* l, int onoff)
|
|
{
|
|
LayerContext* lc;
|
|
|
|
lc = (LayerContext*)l;
|
|
if(onoff)
|
|
lc->bLayerShowed = 1;
|
|
else
|
|
lc->bLayerShowed = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int createRotateBuf(LayerCtrl* l,int width,int height){
|
|
int ret = 0;
|
|
LayerContext* lc;
|
|
lc = (LayerContext*)l;
|
|
int i = 0;
|
|
char* pVirBuf;
|
|
char* pPhyBuf;
|
|
int nBufferFd = 0;
|
|
logd("before align:width = %d,height = %d",width,height);
|
|
width = ALIGN_32B(width);
|
|
height = ALIGN_32B(height);
|
|
logd("after align:width = %d,height = %d",width,height);
|
|
for(i=0; i<ROTATE_BUFFER_NUM; i++)
|
|
{
|
|
pVirBuf = (char*)SunxiMemPalloc(lc->pMemops, width * height * 3/2);
|
|
if(pVirBuf == NULL){
|
|
loge("SunxiMemPalloc err");
|
|
ret = -1;
|
|
break;
|
|
}
|
|
#ifdef CONF_KERNEL_IOMMU
|
|
nBufferFd = SunxiMemGetBufferFd(lc->pMemops,pVirBuf);
|
|
#else
|
|
pPhyBuf = (char*)SunxiMemGetPhysicAddressCpu(lc->pMemops, pVirBuf);
|
|
#endif
|
|
lc->mRotateBufInfo[i].nUsedFlag = 0;
|
|
|
|
lc->mRotateBufInfo[i].pPicture.nWidth = width;
|
|
lc->mRotateBufInfo[i].pPicture.nHeight = height;
|
|
lc->mRotateBufInfo[i].pPicture.nLineStride = width;
|
|
lc->mRotateBufInfo[i].pPicture.pData0 = pVirBuf;
|
|
lc->mRotateBufInfo[i].pPicture.pData1 = pVirBuf + (width * height);
|
|
lc->mRotateBufInfo[i].pPicture.pData2 = lc->mRotateBufInfo[i].pPicture.pData1 + (width * height)/4;
|
|
#ifdef CONF_KERNEL_IOMMU
|
|
lc->mRotateBufInfo[i].pPicture.nBufFd = nBufferFd;
|
|
#else
|
|
lc->mRotateBufInfo[i].pPicture.phyYBufAddr = (uintptr_t)pPhyBuf;
|
|
lc->mRotateBufInfo[i].pPicture.phyCBufAddr =
|
|
lc->mRotateBufInfo[i].pPicture.phyYBufAddr + (width * height);
|
|
#endif
|
|
lc->mRotateBufInfo[i].pPicture.nBufId = i;
|
|
lc->mRotateBufInfo[i].pPicture.ePixelFormat = lc->eDisplayPixelFormat;
|
|
}
|
|
/*if has err,we should free the palloced buf*/
|
|
if(ret == -1){
|
|
int j = 0;
|
|
for(j = 0;j < i;j++){
|
|
SunxiMemPfree(lc->pMemops, lc->mRotateBufInfo[j].pPicture.pData0);
|
|
lc->mRotateBufInfo[j].pPicture.pData0 = NULL;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int hwRotateVideoPicture(LayerCtrl* l,VideoPicture* pPictureIn,VideoPicture* pPictureOut,int nRotateDegree){
|
|
int ret = 0;
|
|
LayerContext* lc;
|
|
lc = (LayerContext*)l;
|
|
unsigned long arg[4] = {0};
|
|
tr_info tTrInfo;
|
|
int inCroppedLeft = pPictureIn->nLeftOffset;
|
|
int inCroppedRight = pPictureIn->nWidth - pPictureIn->nRightOffset;
|
|
int inCroppedTop = pPictureIn->nTopOffset;
|
|
int inCroppedBottom = pPictureIn->nHeight - pPictureIn->nBottomOffset;
|
|
int outCroppedLeft = 0;
|
|
int outCroppedRitht = 0;
|
|
int outCroppedTop = 0;
|
|
int outCroppedBottom = 0;
|
|
setup_tr:
|
|
|
|
if(lc->mInitedTransformFlag == 0)
|
|
{
|
|
//* open the tr driver
|
|
lc->mTransformFd= open("/dev/transform",O_RDWR);
|
|
logv("open transform drive ret = %d",lc->mTransformFd);
|
|
|
|
if(lc->mTransformFd < 0)
|
|
{
|
|
loge("*****open tr driver fail!");
|
|
return -1;
|
|
}
|
|
|
|
//* request tr channel
|
|
arg[0] = (unsigned long)&(lc->mTransformChannel);
|
|
if(ioctl(lc->mTransformFd,TR_REQUEST,(void*)arg)<0){
|
|
loge("#######error: tr_request failed!");
|
|
return -1;
|
|
}
|
|
logd("request tr channel = 0x%x",lc->mTransformChannel);
|
|
|
|
//* set tr timeout
|
|
arg[0] = lc->mTransformChannel;
|
|
arg[1] = TRANSFORM_DEV_TIMEOUT;
|
|
if(ioctl(lc->mTransformFd,TR_SET_TIMEOUT,(void*)arg) != 0)
|
|
{
|
|
loge("#######error: tr_set_timeout failed!");
|
|
return -1;
|
|
}
|
|
|
|
lc->mInitedTransformFlag = 1;
|
|
}
|
|
|
|
if(lc->mTransformFd < 0)
|
|
{
|
|
loge("the lc->mTransformFd is invalid : %d",lc->mTransformFd);
|
|
return -1;
|
|
}
|
|
|
|
pPictureOut->nPts = pPictureIn->nPts;
|
|
|
|
//* set rotation angle and the cropped of output picture
|
|
if(nRotateDegree == 0){
|
|
tTrInfo.mode = TR_ROT_0;
|
|
outCroppedLeft = inCroppedLeft;
|
|
outCroppedRitht = inCroppedRight;
|
|
outCroppedTop = inCroppedTop;
|
|
outCroppedBottom = inCroppedBottom;
|
|
}else if(nRotateDegree == 90){
|
|
tTrInfo.mode = TR_ROT_90;
|
|
outCroppedLeft = inCroppedBottom;
|
|
outCroppedRitht = inCroppedTop;
|
|
outCroppedTop = inCroppedLeft;
|
|
outCroppedBottom = inCroppedRight;
|
|
}else if(nRotateDegree == 180){
|
|
tTrInfo.mode = TR_ROT_180;
|
|
outCroppedLeft = inCroppedRight;
|
|
outCroppedRitht = inCroppedLeft;
|
|
outCroppedTop = inCroppedBottom;
|
|
outCroppedBottom = inCroppedTop;
|
|
}else if(nRotateDegree == 270){
|
|
tTrInfo.mode = TR_ROT_270;
|
|
outCroppedLeft = inCroppedTop;
|
|
outCroppedRitht = inCroppedBottom;
|
|
outCroppedTop = inCroppedRight;
|
|
outCroppedBottom = inCroppedLeft;
|
|
}else{
|
|
tTrInfo.mode = TR_ROT_0;
|
|
outCroppedLeft = inCroppedLeft;
|
|
outCroppedRitht = inCroppedRight;
|
|
outCroppedTop = inCroppedTop;
|
|
outCroppedBottom = inCroppedBottom;
|
|
}
|
|
pPictureOut->nLeftOffset = outCroppedLeft;
|
|
pPictureOut->nRightOffset = pPictureOut->nWidth - outCroppedRitht;
|
|
pPictureOut->nTopOffset = outCroppedTop;
|
|
pPictureOut->nBottomOffset = pPictureOut->nHeight - outCroppedBottom;
|
|
/*
|
|
logd("outCroppedLeft = %d,outCroppedRitht = %d,outCroppedTop = %d,outCroppedBottom = %d",
|
|
outCroppedLeft,outCroppedRitht,outCroppedTop,outCroppedBottom);
|
|
logd("pPictureOut->nLeftOffset = %d,nRightOffset = %d,nTopOffset = %d,nBottomOffset = %d",
|
|
pPictureOut->nLeftOffset,pPictureOut->nRightOffset,pPictureOut->nTopOffset,pPictureOut->nBottomOffset);
|
|
*/
|
|
|
|
//* set in picture
|
|
if(pPictureIn->ePixelFormat == PIXEL_FORMAT_YV12){
|
|
tTrInfo.src_frame.fmt = TR_FORMAT_YUV420_P;
|
|
}
|
|
else if(pPictureIn->ePixelFormat == PIXEL_FORMAT_NV21){
|
|
tTrInfo.src_frame.fmt = TR_FORMAT_YUV420_SP_UVUV;
|
|
}
|
|
else
|
|
{
|
|
loge("***the ePixelFormat[0x%x] is not support by tr driver",pPictureIn->ePixelFormat);
|
|
return -1;
|
|
}
|
|
|
|
tTrInfo.src_frame.laddr[0] = (size_addr)SunxiMemGetPhysicAddressCpu(lc->pMemops,(void*)pPictureIn->pData0);
|
|
tTrInfo.src_frame.laddr[1] = (size_addr)SunxiMemGetPhysicAddressCpu(lc->pMemops,(void*)pPictureIn->pData1);
|
|
tTrInfo.src_frame.laddr[2] = (size_addr)SunxiMemGetPhysicAddressCpu(lc->pMemops, (void*)pPictureIn->pData2);
|
|
|
|
tTrInfo.src_frame.pitch[0] = ALIGN_32B(pPictureIn->nLineStride);
|
|
tTrInfo.src_frame.pitch[1] = ALIGN_32B(pPictureIn->nLineStride)/2;
|
|
tTrInfo.src_frame.pitch[2] = ALIGN_32B(pPictureIn->nLineStride)/2;
|
|
|
|
tTrInfo.src_frame.height[0] = ALIGN_32B(pPictureIn->nHeight);
|
|
tTrInfo.src_frame.height[1] = ALIGN_32B(pPictureIn->nHeight)/2;
|
|
tTrInfo.src_frame.height[2] = ALIGN_32B(pPictureIn->nHeight)/2;
|
|
|
|
tTrInfo.src_rect.x = 0;
|
|
tTrInfo.src_rect.y = 0;
|
|
tTrInfo.src_rect.w = pPictureIn->nWidth;
|
|
tTrInfo.src_rect.h = pPictureIn->nHeight;
|
|
|
|
/*because the transform only support yv12,so we should set the format of rotated picture yv12*/
|
|
pPictureOut->ePixelFormat = PIXEL_FORMAT_YV12;
|
|
/*the output format only support yuv420P*/
|
|
tTrInfo.dst_frame.fmt = TR_FORMAT_YUV420_P;
|
|
tTrInfo.dst_frame.laddr[0] = (size_addr)SunxiMemGetPhysicAddressCpu(lc->pMemops, (void*)pPictureOut->pData0);
|
|
tTrInfo.dst_frame.laddr[1] = (size_addr)SunxiMemGetPhysicAddressCpu(lc->pMemops,(void*)pPictureOut->pData1);
|
|
tTrInfo.dst_frame.laddr[2] = (size_addr)SunxiMemGetPhysicAddressCpu(lc->pMemops, (void*)pPictureOut->pData2);
|
|
|
|
tTrInfo.dst_frame.pitch[0] = ALIGN_32B(pPictureOut->nLineStride);
|
|
tTrInfo.dst_frame.pitch[1] = ALIGN_32B(pPictureOut->nLineStride)/2;
|
|
tTrInfo.dst_frame.pitch[2] = ALIGN_32B(pPictureOut->nLineStride)/2;
|
|
|
|
tTrInfo.dst_frame.height[0] = ALIGN_32B(pPictureOut->nHeight);
|
|
tTrInfo.dst_frame.height[1] = ALIGN_32B(pPictureOut->nHeight)/2;
|
|
tTrInfo.dst_frame.height[2] = ALIGN_32B(pPictureOut->nHeight)/2;
|
|
|
|
tTrInfo.dst_rect.x = 0;
|
|
tTrInfo.dst_rect.y = 0;
|
|
tTrInfo.dst_rect.w = pPictureOut->nWidth;
|
|
tTrInfo.dst_rect.h = pPictureOut->nHeight;
|
|
|
|
|
|
//* setup rotate
|
|
arg[0] = lc->mTransformChannel;
|
|
arg[1] = (size_addr)&tTrInfo;
|
|
arg[2] = 0;
|
|
arg[3] = 0;
|
|
|
|
logv("***setup rotate start!: arg: 0x%x, 0x%x",arg[0],arg[1]);
|
|
if(ioctl(lc->mTransformFd,TR_COMMIT,(void*)arg) != 0)
|
|
{
|
|
loge("######error: setup rotate failed!");
|
|
return -1;
|
|
}
|
|
logv("***setup rotate finish!");
|
|
|
|
//* wait
|
|
arg[0] = lc->mTransformChannel;
|
|
arg[1] = 0;
|
|
arg[2] = 0;
|
|
arg[3] = 0;
|
|
|
|
logv("***tr query start!");
|
|
int nTimeOut = 0;
|
|
ret = ioctl(lc->mTransformFd,TR_QUERY,(void*)arg);
|
|
|
|
while(ret == 1)// 0 : suceef; 1:busy ; -1:timeOut
|
|
{
|
|
logv("***tr sleep!");
|
|
usleep(1*1000);
|
|
ret = ioctl(lc->mTransformFd,TR_QUERY,(void*)arg);
|
|
}
|
|
|
|
//* if the tr is timeout ,we should setup tr again
|
|
if(ret == -1)
|
|
goto setup_tr;
|
|
|
|
logv("***tr query finish!");
|
|
return ret;
|
|
}
|