SmartAudio/package/allwinner/tina_multimedia/libcedarx/android_adapter/output/layerControl.cpp

1492 lines
45 KiB
C++
Executable File

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : layerControl.cpp
* Description : surface display interface -- decoder and de share the buffer
* History :
*/
//#define CONFIG_LOG_LEVEL OPTION_LOG_LEVEL_DETAIL
//#define LOG_TAG "layerControl_android_newDisplay"
#include "cdx_config.h"
#include "layerControl.h"
#include "cdx_log.h"
#include "memoryAdapter.h"
#include "outputCtrl.h"
#include <iniparserapi.h>
#include "CdcUtil.h"
#if (((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
#include <gui/ISurfaceTexture.h>
#elif ((CONF_ANDROID_MAJOR_VER >= 4)||((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4)))
#include <gui/Surface.h>
#else
#error "invalid configuration of os version."
#endif
#include <ui/Rect.h>
#include <ui/GraphicBufferMapper.h>
#include <hardware/hwcomposer.h>
#if ((CONF_ANDROID_MAJOR_VER >= 4)||((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4)))
#include <hardware/hal_public.h>
#endif
#include <linux/ion.h>
#include <ion/ion.h>
/* only A33 here, hide it now. */
#if 0 //((CONF_ANDROID_MAJOR_VER >= 5) && GRALLOC_PRIV == 1)
#include <gralloc_priv.h>
#endif
#if (defined(CONF_PTS_TOSF) && (CONF_ANDROID_MAJOR_VER >= 5))
#include "VideoFrameSchedulerWrap.h"
#endif
using namespace android;
#if (CONF_KERNEL_VER == 304)
typedef struct ion_handle* ion_handle_abstract_t;
#define ION_NULL_VALUE (NULL)
#elif (CONF_KERNEL_VER == 310)
typedef ion_user_handle_t ion_handle_abstract_t;
#define ION_NULL_VALUE (0)
#else
#error: not define kernel version.
#endif
#define GPU_BUFFER_NUM 32
/* +1 allows queue after SetGpuBufferToDecoder */
#define NUM_OF_PICTURES_KEEP_IN_NODE (GetConfigParamterInt("pic_4list_num", 3) + 1)
typedef struct VPictureNode_t VPictureNode;
struct VPictureNode_t
{
int bUsed;
VideoPicture* pPicture;
ANativeWindowBuffer* pNodeWindowBuf;
};
typedef struct GpuBufferInfoS
{
ANativeWindowBuffer* pWindowBuf;
ion_handle_abstract_t handle_ion;
char* pBufPhyAddr;
char* pBufVirAddr;
int nUsedFlag;
int nDequeueFlag;
}GpuBufferInfoT;
typedef struct LayerCtrlContext
{
LayerCtrl base;
ANativeWindow* pNativeWindow;
enum EPIXELFORMAT eDisplayPixelFormat;
int nWidth;
int nHeight;
int nLeftOff;
int nTopOff;
int nDisplayWidth;
int nDisplayHeight;
int bLayerInitialized;
int bLayerShowed;
int bProtectFlag;
//* use when render derect to hardware layer.
VPictureNode picNodes[16];
GpuBufferInfoT mGpuBufferInfo[GPU_BUFFER_NUM];
int nGpuBufferCount;
int ionFd;
int b4KAlignFlag;
int bHoldLastPictureFlag;
int bVideoWithTwoStreamFlag;
int bIsSoftDecoderFlag;
unsigned int nUsage;
#if (defined(CONF_PTS_TOSF) && (CONF_ANDROID_MAJOR_VER >= 5))
CdxVideoScheduler *mVideoScheduler;
#endif
}LayerCtrlContext;
#if defined(CONF_SEND_BLACK_FRAME_TO_GPU)
static int sendThreeBlackFrameToGpu(LayerCtrlContext* lc)
{
logd("sendThreeBlackFrameToGpu()");
ANativeWindowBuffer* pWindowBuf;
void* pDataBuf;
int i;
int err;
int pic_4list = GetConfigParamterInt("pic_4list_num", 3);
if (lc->pNativeWindow == NULL || lc->bLayerInitialized == 0)
{
logv("skip %s", __func__);
return 0;
}
for(i = 0; i < pic_4list; i++)
{
err = lc->pNativeWindow->dequeueBuffer_DEPRECATED(lc->pNativeWindow, &pWindowBuf);
if(err != 0)
{
logw("dequeue buffer fail, return value from dequeueBuffer_DEPRECATED() method is %d.",
err);
return -1;
}
lc->pNativeWindow->lockBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
//* lock the data buffer.
{
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
Rect bounds(lc->nWidth, lc->nHeight);
graphicMapper.lock(pWindowBuf->handle, lc->nUsage, bounds, &pDataBuf);
logd("graphicMapper %p", pDataBuf);
}
if (pDataBuf) {
memset((char*)pDataBuf,0x10,(pWindowBuf->height * pWindowBuf->stride));
memset((char*)pDataBuf + pWindowBuf->height * pWindowBuf->stride,
0x80,(pWindowBuf->height * pWindowBuf->stride)/2);
}
int nBufAddr[7] = {0};
//nBufAddr[6] = HAL_PIXEL_FORMAT_AW_NV12;
nBufAddr[6] = HAL_PIXEL_FORMAT_AW_FORCE_GPU;
lc->pNativeWindow->perform(lc->pNativeWindow, NATIVE_WINDOW_SET_VIDEO_BUFFERS_INFO,
nBufAddr[0], nBufAddr[1], nBufAddr[2], nBufAddr[3],
nBufAddr[4], nBufAddr[5], nBufAddr[6]);
//* unlock the buffer.
{
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
}
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
}
return 0;
}
// dequeue all nativewindow buffer from BufferQueue, then cancle all.
// this can make sure all buffer queued by player to render by surfaceflinger.
static int makeSureBlackFrameToShow(LayerCtrlContext* lc)
{
logd("makeSureBlackFrameToShow()");
ANativeWindowBuffer* pWindowBuf[32];
void* pDataBuf;
int i;
int err;
int bufCnt = lc->nGpuBufferCount;
for(i = 0;i < bufCnt -1; i++)
{
err = lc->pNativeWindow->dequeueBuffer_DEPRECATED(lc->pNativeWindow, &pWindowBuf[i]);
if(err != 0)
{
logw("dequeue buffer fail, return value from dequeueBuffer_DEPRECATED() method is %d.",
err);
break;
}
logv("dequeue i = %d, handle: 0x%x", i, pWindowBuf[i]->handle);
}
for(i--; i >= 0; i--)
{
logv("cancel i = %d, handle: 0x%x", i, pWindowBuf[i]->handle);
lc->pNativeWindow->cancelBuffer(lc->pNativeWindow, pWindowBuf[i], -1);
}
return 0;
}
#endif
//* this function just for 3D case.
//* just init 32-line buffer to black color.
//* (when the two stream display to 2D, the 32-line buffer will cause "Green Screen" if not init,
//* as buffer have make 32-align)
//* if init the whole buffer, it would take too much time.
int initPartialGpuBuffer(char* pDataBuf, ANativeWindowBuffer* pWindowBuf, LayerCtrlContext* lc)
{
logv("initGpuBuffer, stride = %d, height = %d, ",pWindowBuf->stride,pWindowBuf->height);
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_NV21)
{
//* Y1
int nRealHeight = pWindowBuf->height/2;
int nInitHeight = 32;
int nSkipLen = pWindowBuf->stride*(nRealHeight - nInitHeight);
int nCpyLenY = pWindowBuf->stride*nInitHeight;
memset(pDataBuf+nSkipLen, 0x10, nCpyLenY);
//* Y2
nSkipLen += pWindowBuf->stride*nRealHeight;
memset(pDataBuf+nSkipLen, 0x10, nCpyLenY);
//*UV1
nSkipLen += nCpyLenY;
nSkipLen += (pWindowBuf->stride)*(nRealHeight/2 - nInitHeight/2);
int nCpyLenUV = (pWindowBuf->stride)*(nInitHeight/2);
memset(pDataBuf+nSkipLen, 0x80, nCpyLenUV);
//*UV2
nSkipLen += (pWindowBuf->stride)*(nRealHeight/2);
memset(pDataBuf+nSkipLen, 0x80, nCpyLenUV);
}
else
{
loge("the pixelFormat is not support when initPartialGpuBuffer, pixelFormat = %d",
lc->eDisplayPixelFormat);
return -1;
}
return 0;
}
//* copy from ACodec.cpp
static int pushBlankBuffersToNativeWindow(LayerCtrlContext* lc)
{
logd("pushBlankBuffersToNativeWindow: pNativeWindow = %p",lc->pNativeWindow);
if(lc->pNativeWindow == NULL)
{
logw(" the nativeWindow is null when call pushBlankBuffersToNativeWindow");
return 0;
}
status_t eErr = NO_ERROR;
ANativeWindowBuffer* pWindowBuffer = NULL;
int nNumBufs = 0;
int nMinUndequeuedBufs = 0;
ANativeWindowBuffer **pArrBuffer = NULL;
// We need to reconnect to the ANativeWindow as a CPU client to ensure that
// no frames get dropped by SurfaceFlinger assuming that these are video
// frames.
eErr = native_window_api_disconnect(lc->pNativeWindow,NATIVE_WINDOW_API_MEDIA);
if (eErr != NO_ERROR) {
loge("error push blank frames: native_window_api_disconnect failed: %s (%d)",
strerror(-eErr), -eErr);
return eErr;
}
eErr = native_window_api_connect(lc->pNativeWindow,NATIVE_WINDOW_API_CPU);
if (eErr != NO_ERROR) {
loge("error push blank frames: native_window_api_connect failed: %s (%d)",
strerror(-eErr), -eErr);
return eErr;
}
#if (CONF_ANDROID_MAJOR_VER >= 5)
eErr = lc->pNativeWindow->perform(lc->pNativeWindow,
NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
0,
0,
HAL_PIXEL_FORMAT_RGBX_8888);
#else
eErr = native_window_set_buffers_geometry(lc->pNativeWindow, 1, 1,
HAL_PIXEL_FORMAT_RGBX_8888);
#endif
if (eErr != NO_ERROR) {
loge("set buffers geometry of nativeWindow failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
eErr = native_window_set_scaling_mode(lc->pNativeWindow,
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
if (eErr != NO_ERROR) {
loge("error push blank_frames: native_window_set_scaling_mode failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
eErr = native_window_set_usage(lc->pNativeWindow,
GRALLOC_USAGE_SW_WRITE_OFTEN);
if (eErr != NO_ERROR) {
loge("error push blank frames: native_window_set_usage failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
eErr = lc->pNativeWindow->query(lc->pNativeWindow,
NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &nMinUndequeuedBufs);
if (eErr != NO_ERROR) {
loge("query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
nNumBufs = nMinUndequeuedBufs + 1;
if (nNumBufs < 3)
nNumBufs = 3;
eErr = native_window_set_buffer_count(lc->pNativeWindow, nNumBufs);
if (eErr != NO_ERROR) {
loge("set buffer count of nativeWindow failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
// We push nNumBufs + 1 buffers to ensure that we've drawn into the same
// buffer twice. This should guarantee that the buffer has been displayed
// on the screen and then been replaced, so an previous video frames are
// guaranteed NOT to be currently displayed.
logd("nNumBufs=%d", nNumBufs);
//* we just push nNumBufs.If push numBus+1,it will be problem in suspension window
for (int i = 0; i < nNumBufs; i++) {
int fenceFd = -1;
eErr = native_window_dequeue_buffer_and_wait(lc->pNativeWindow, &pWindowBuffer);
if (eErr != NO_ERROR) {
loge("error: native_window_dequeue_buffer_and_wait failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
sp<GraphicBuffer> mGraphicBuffer(new GraphicBuffer(pWindowBuffer, false));
// Fill the buffer with the a 1x1 checkerboard pattern ;)
uint32_t* pImg = NULL;
eErr = mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&pImg));
if (eErr != NO_ERROR) {
loge("error push blank frames: lock failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
*pImg = 0;
eErr = mGraphicBuffer->unlock();
if (eErr != NO_ERROR) {
loge("error push blank frames: unlock failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
eErr = lc->pNativeWindow->queueBuffer(lc->pNativeWindow,
mGraphicBuffer->getNativeBuffer(), -1);
if (eErr != NO_ERROR) {
loge("lc->pNativeWindow->queueBuffer failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
pWindowBuffer = NULL;
}
pArrBuffer = (ANativeWindowBuffer **)malloc((nNumBufs)*sizeof(ANativeWindowBuffer*));
for (int i = 0; i < nNumBufs-1; ++i) {
eErr = native_window_dequeue_buffer_and_wait(lc->pNativeWindow, &pArrBuffer[i]);
if (eErr != NO_ERROR) {
loge("native_window_dequeue_buffer_and_wait failed: %s (%d)",
strerror(-eErr), -eErr);
goto error;
}
}
for (int i = 0; i < nNumBufs-1; ++i) {
lc->pNativeWindow->cancelBuffer(lc->pNativeWindow, pArrBuffer[i], -1);
}
free(pArrBuffer);
pArrBuffer = NULL;
error:
if (eErr != NO_ERROR) {
// Clean up after an error.
if (pWindowBuffer != NULL) {
lc->pNativeWindow->cancelBuffer(lc->pNativeWindow, pWindowBuffer, -1);
}
if (pArrBuffer) {
free(pArrBuffer);
}
native_window_api_disconnect(lc->pNativeWindow,
NATIVE_WINDOW_API_CPU);
native_window_api_connect(lc->pNativeWindow,
NATIVE_WINDOW_API_MEDIA);
return eErr;
} else {
// Clean up after success.
eErr = native_window_api_disconnect(lc->pNativeWindow,
NATIVE_WINDOW_API_CPU);
if (eErr != NO_ERROR) {
loge("native_window_api_disconnect failed: %s (%d)",
strerror(-eErr), -eErr);
return eErr;
}
eErr = native_window_api_connect(lc->pNativeWindow,
NATIVE_WINDOW_API_MEDIA);
if (eErr != NO_ERROR) {
loge("native_window_api_connect failed: %s (%d)",
strerror(-eErr), -eErr);
return eErr;
}
return 0;
}
}
//* set usage, scaling_mode, pixelFormat, buffers_geometry, buffers_count, crop
static int setLayerParam(LayerCtrlContext* lc)
{
logd("setLayerParam: PixelFormat(%d), nW(%d), nH(%d), leftoff(%d), topoff(%d)",
lc->eDisplayPixelFormat,lc->nWidth,
lc->nHeight,lc->nLeftOff,lc->nTopOff);
logd("setLayerParam: dispW(%d), dispH(%d), buffercount(%d), bProtectFlag(%d),\
bIsSoftDecoderFlag(%d)",
lc->nDisplayWidth,lc->nDisplayHeight,lc->nGpuBufferCount,
lc->bProtectFlag,lc->bIsSoftDecoderFlag);
int pixelFormat;
unsigned int nGpuBufWidth;
unsigned int nGpuBufHeight;
Rect crop;
lc->nUsage = 0;
//* add the protected usage when the video is secure
if(lc->bProtectFlag == 1)
{
// Verify that the ANativeWindow sends images directly to
// SurfaceFlinger.
int nErr = -1;
int nQueuesToNativeWindow = 0;
nErr = lc->pNativeWindow->query(
lc->pNativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
&nQueuesToNativeWindow);
if (nErr != 0) {
loge("error authenticating native window: %d", nErr);
return nErr;
}
if (nQueuesToNativeWindow != 1) {
loge("nQueuesToNativeWindow is not 1, PERMISSION_DENIED");
return PERMISSION_DENIED;
}
logd("set usage to GRALLOC_USAGE_PROTECTED");
lc->nUsage |= GRALLOC_USAGE_PROTECTED;
}
if(lc->bIsSoftDecoderFlag == 1)
{
//* gpu use this usage to malloc buffer with cache.
lc->nUsage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
}
else
{
//* gpu use this usage to malloc continuous physical buffer.
lc->nUsage |= GRALLOC_USAGE_HW_2D;
//* cpu cannot WRITE and READ the buffer if the video is protect.
//* when it is not protect, cpu will W the buffer, but not often.
if(lc->bProtectFlag == 0)
{
lc->nUsage |= GRALLOC_USAGE_SW_WRITE_RARELY;
}
}
//* add other usage
lc->nUsage |= GRALLOC_USAGE_SW_READ_NEVER |
GRALLOC_USAGE_HW_TEXTURE |
GRALLOC_USAGE_EXTERNAL_DISP;
switch(lc->eDisplayPixelFormat)
{
case PIXEL_FORMAT_YV12: //* why YV12 use this pixel format.
pixelFormat = HAL_PIXEL_FORMAT_YV12;
break;
case PIXEL_FORMAT_NV21:
pixelFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
break;
case PIXEL_FORMAT_NV12: //* display system do not support NV12.
default:
{
loge("unsupported pixel format.");
return -1;
break;
}
}
nGpuBufWidth = lc->nWidth; //* restore nGpuBufWidth to mWidth;
nGpuBufHeight = lc->nHeight;
//* 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;
}
crop.left = lc->nLeftOff;
crop.top = lc->nTopOff;
crop.right = lc->nLeftOff + lc->nDisplayWidth;
crop.bottom = lc->nTopOff + lc->nDisplayHeight;
if(lc->nGpuBufferCount <= 0)
{
loge("error: the lc->nGpuBufferCount[%d] is invalid!",lc->nGpuBufferCount);
return -1;
}
logd("set usage, lc->pNativeWindow: %p", lc->pNativeWindow);
native_window_set_usage(lc->pNativeWindow,lc->nUsage);
logd("set sacle");
native_window_set_scaling_mode(lc->pNativeWindow, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
#if defined(CONF_PRODUCT_STB)
lc->pNativeWindow->perform(lc->pNativeWindow,
NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
nGpuBufWidth,
nGpuBufHeight,
pixelFormat);
#endif
//native_window_set_buffers_geometry(lc->pNativeWindow, nGpuBufWidth,
//nGpuBufHeight, pixelFormat);
native_window_set_buffers_dimensions(lc->pNativeWindow, nGpuBufWidth, nGpuBufHeight);
native_window_set_buffers_format(lc->pNativeWindow, pixelFormat);
//#endif
native_window_set_buffer_count(lc->pNativeWindow,lc->nGpuBufferCount);
lc->pNativeWindow->perform(lc->pNativeWindow, NATIVE_WINDOW_SET_CROP, &crop);
return 0;
}
ANativeWindowBuffer* dequeueTheInitGpuBuffer(LayerCtrlContext* lc)
{
int err = -1;
int i = 0;
int nCancelNum = 0;
int nNeedCancelFlag = 0;
int nCancelIndex[GPU_BUFFER_NUM] = {-1};
ANativeWindowBuffer* pWindowBuf = NULL;
dequeue_buffer:
//* dequeue a buffer from the nativeWindow object.
err = lc->pNativeWindow->dequeueBuffer_DEPRECATED(lc->pNativeWindow, &pWindowBuf);
if(err != 0)
{
logw("dequeue buffer fail, return value from dequeueBuffer_DEPRECATED() method is %d.",
err);
return NULL;
}
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].nUsedFlag == 1
&& lc->mGpuBufferInfo[i].pWindowBuf == pWindowBuf)
{
nNeedCancelFlag = 1;
nCancelIndex[nCancelNum] = i;
nCancelNum++;
logv("the buffer have not return ,dequeue agagin! : %p",pWindowBuf);
goto dequeue_buffer;
}
}
if(nNeedCancelFlag == 1)
{
for(i = 0;i<nCancelNum;i++)
{
int nIndex = nCancelIndex[i];
ANativeWindowBuffer* pTmpWindowBuf = lc->mGpuBufferInfo[nIndex].pWindowBuf;
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pTmpWindowBuf);
}
nCancelNum = 0;
nNeedCancelFlag = 0;
}
return pWindowBuf;
}
int getPhyAddrOfGpuBuffer(LayerCtrlContext* lc,
ANativeWindowBuffer* pWindowBuf,
ion_handle_abstract_t* pHandle_ion,
uintptr_t* pPhyaddress)
{
ion_handle_abstract_t handle_ion = ION_NULL_VALUE;
uintptr_t nPhyaddress = 0;
int ret;
#if defined(CONF_GPU_MALI)
private_handle_t* hnd = (private_handle_t *)(pWindowBuf->handle);
if(hnd != NULL)
{
ret = ion_import(lc->ionFd, hnd->share_fd, &handle_ion);
if(ret < 0)
{
loge("ion_import fail, maybe the buffer was free by display!");
return -1;
}
}
else
{
logd("the hnd is wrong : hnd = %p",hnd);
return -1;
}
#elif defined(CONF_GPU_IMG)
IMG_native_handle_t* hnd = (IMG_native_handle_t*)(pWindowBuf->handle);
if(hnd != NULL)
{
ret = ion_import(lc->ionFd, hnd->fd[0], &handle_ion);
if(ret < 0)
{
loge("ion_import fail, maybe the buffer was free by display!");
return -1;
}
}
else
{
logd("the hnd is wrong : hnd = %p",hnd);
return -1;
}
#else
#error invalid GPU type config
#endif
//* we should not get the phyaddr if it is software decoder
if(lc->bIsSoftDecoderFlag == 0)
{
if(lc->ionFd >= 0)
nPhyaddress = CdcIonGetPhyAdr(lc->ionFd, (uintptr_t)handle_ion);
else
{
logd("the ion fd is wrong : fd = %d",lc->ionFd);
return -1;
}
nPhyaddress -= CONF_VE_PHY_OFFSET;
}
*pPhyaddress = nPhyaddress;
*pHandle_ion = handle_ion;
return 0;
}
int matchWindowBufferAndPicture(LayerCtrlContext* lc,
ANativeWindowBuffer* pWindowBuf,
char* pGpuVirBuf,
VideoPicture** ppVideoPicture,
int bInitFlag)
{
logv("matchWindowBufferAndPicture");
int i = 0;
int ret = -1;
uintptr_t nPhyaddress = 0;
ion_handle_abstract_t handle_ion = ION_NULL_VALUE;
VideoPicture* pPicture = NULL;
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].pWindowBuf == NULL)
{
ret = getPhyAddrOfGpuBuffer(lc, pWindowBuf, &handle_ion, &nPhyaddress);
if(ret == -1)
{
loge("getPhyAddrOfGpuBuffer failed");
return -1;
}
if(lc->bVideoWithTwoStreamFlag == 1)
{
initPartialGpuBuffer(pGpuVirBuf,pWindowBuf,lc);
}
lc->mGpuBufferInfo[i].pWindowBuf = pWindowBuf;
lc->mGpuBufferInfo[i].handle_ion = handle_ion;
lc->mGpuBufferInfo[i].pBufVirAddr = pGpuVirBuf;
lc->mGpuBufferInfo[i].pBufPhyAddr = (char*)nPhyaddress;
lc->mGpuBufferInfo[i].nUsedFlag = 1;
lc->mGpuBufferInfo[i].nDequeueFlag = 1;
break;
}
else if(lc->mGpuBufferInfo[i].pWindowBuf == pWindowBuf)
{
lc->mGpuBufferInfo[i].nUsedFlag = 1;
lc->mGpuBufferInfo[i].nDequeueFlag = 1;
break;
}
}
if(i == lc->nGpuBufferCount)
{
loge("not enouth gpu buffer , should not run here");
abort();
}
//* dequeue buffer for the first time, we should not dequeue from picNode
if(bInitFlag == 1)
{
pPicture = *ppVideoPicture;
//* set the buffer address
pPicture->pData0 = lc->mGpuBufferInfo[i].pBufVirAddr;
pPicture->pData1 = pPicture->pData0 + (pWindowBuf->height * pWindowBuf->stride);
pPicture->pData2 = pPicture->pData1 + (pWindowBuf->height * pWindowBuf->stride)/4;
pPicture->phyYBufAddr = (uintptr_t)lc->mGpuBufferInfo[i].pBufPhyAddr;
pPicture->phyCBufAddr = pPicture->phyYBufAddr + (pWindowBuf->height * pWindowBuf->stride);
pPicture->nBufId = i;
pPicture->pPrivate = (void*)(uintptr_t)lc->mGpuBufferInfo[i].handle_ion;
pPicture->ePixelFormat = lc->eDisplayPixelFormat;
pPicture->nWidth = pWindowBuf->stride;
pPicture->nHeight = pWindowBuf->height;
pPicture->nLineStride = pWindowBuf->stride;
if(lc->b4KAlignFlag == 1)
{
uintptr_t tmpAddr = (uintptr_t)pPicture->pData1;
tmpAddr = (tmpAddr + 4095) & ~4095;
pPicture->pData1 = (char *)tmpAddr;
pPicture->phyCBufAddr = (pPicture->phyCBufAddr + 4095) & ~4095;
}
}
else
{
for(i = 0; i<NUM_OF_PICTURES_KEEP_IN_NODE; i++)
{
logv("** dequeue , i(%d), used(%d), pPicture(%p), pNodeWindowBuf(%p),pWindowBuf(%p)",
i,lc->picNodes[i].bUsed,lc->picNodes[i].pPicture,
lc->picNodes[i].pNodeWindowBuf, pWindowBuf);
if(lc->picNodes[i].bUsed == 1
&& lc->picNodes[i].pPicture != NULL
&& lc->picNodes[i].pNodeWindowBuf == pWindowBuf)
{
pPicture = lc->picNodes[i].pPicture ;
lc->picNodes[i].bUsed = 0;
break;
}
}
if(i == NUM_OF_PICTURES_KEEP_IN_NODE)
{
loge("hava no unused picture in the picNode, pDataBuf = %p",pGpuVirBuf);
return -1;
}
}
*ppVideoPicture = pPicture;
return 0;
}
static void __LayerRelease(LayerCtrl* l)
{
logd("__LayerRelease");
LayerCtrlContext* lc;
VPictureNode* nodePtr;
int i;
int ret;
VideoPicture mPicBufInfo;
lc = (LayerCtrlContext*)l;
memset(&mPicBufInfo, 0, sizeof(VideoPicture));
logd("LayerRelease, ionFd = %d",lc->ionFd);
#if defined(CONF_SEND_BLACK_FRAME_TO_GPU)
if (GetConfigParamterInt("black_pic_4_SP", 0) == 1)
{
if(lc->bProtectFlag == 0)
{
if(lc->bHoldLastPictureFlag == false && lc->pNativeWindow != NULL)
{
sendThreeBlackFrameToGpu(lc);
makeSureBlackFrameToShow(lc);
}
}
}
#endif
for(i = 0; i < lc->nGpuBufferCount; i++)
{
//* we should queue buffer which had dequeued to gpu
if(lc->mGpuBufferInfo[i].nDequeueFlag == 1)
{
//* unlock the buffer.
ANativeWindowBuffer* pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
lc->mGpuBufferInfo[i].nDequeueFlag = 0;
}
if(lc->mGpuBufferInfo[i].handle_ion != ION_NULL_VALUE)
{
logd("ion_free: handle_ion[%d] = %p",i,lc->mGpuBufferInfo[i].handle_ion);
ion_free(lc->ionFd,lc->mGpuBufferInfo[i].handle_ion);
}
lc->mGpuBufferInfo[i].pWindowBuf = NULL;
lc->mGpuBufferInfo[i].nUsedFlag = 0;
}
for(i = 0; i<NUM_OF_PICTURES_KEEP_IN_NODE; i++)
{
lc->picNodes[i].bUsed = 0;
}
if(lc->bProtectFlag == 1 /*|| lc->bHoldLastPictureFlag == 0*/)
{
ret = pushBlankBuffersToNativeWindow(lc);
if(ret != 0)
{
loge("pushBlankBuffersToNativeWindow appear error!: ret = %d",ret);
}
}
}
static void __LayerDestroy(LayerCtrl* l)
{
logd("__LayerDestroy");
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
if(lc->ionFd >= 0)
{
ion_close(lc->ionFd);
}
#if (defined(CONF_PTS_TOSF) && (CONF_ANDROID_MAJOR_VER >= 5))
CdxVideoSchedulerDestroy(lc->mVideoScheduler);
#endif
free(lc);
}
//* Description: set initial param -- size of display
static int __LayerSetDisplayBufferSize(LayerCtrl* l, int nWidth, int nHeight)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("Layer set picture size, width = %d, height = %d", nWidth, nHeight);
lc->nWidth = nWidth;
lc->nHeight = nHeight;
lc->nDisplayWidth = nWidth;
lc->nDisplayHeight = nHeight;
lc->nLeftOff = 0;
lc->nTopOff = 0;
lc->bLayerInitialized = 0;
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 -- buffer count
static int __LayerSetDisplayBufferCount(LayerCtrl* l, int nBufferCount)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("LayerSetBufferCount: count = %d",nBufferCount);
lc->nGpuBufferCount = nBufferCount;
if(lc->nGpuBufferCount > GPU_BUFFER_NUM)
lc->nGpuBufferCount = GPU_BUFFER_NUM;
return lc->nGpuBufferCount;
}
//* Description: set display region -- can set when video is playing
static int __LayerSetDisplayRegion(LayerCtrl* l, int nLeftOff, int nTopOff,
int nDisplayWidth, int nDisplayHeight)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("Layer set display region, leftOffset = %d, topOffset = %d, displayWidth = %d, \
displayHeight = %d",
nLeftOff, nTopOff, nDisplayWidth, nDisplayHeight);
if(nDisplayWidth != 0 && nDisplayHeight != 0)
{
lc->nDisplayWidth = nDisplayWidth;
lc->nDisplayHeight = nDisplayHeight;
lc->nLeftOff = nLeftOff;
lc->nTopOff = nTopOff;
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->nHeight*nScaler;
}
if(lc->bLayerInitialized == 1)
{
Rect crop;
crop.left = lc->nLeftOff;
crop.top = lc->nTopOff;
crop.right = lc->nLeftOff + lc->nDisplayWidth;
crop.bottom = lc->nTopOff + lc->nDisplayHeight;
lc->pNativeWindow->perform(lc->pNativeWindow, NATIVE_WINDOW_SET_CROP, &crop);
}
return 0;
}
else
return -1;
}
//* Description: set initial param -- displayer pixel format
static int __LayerSetDisplayPixelFormat(LayerCtrl* l, enum EPIXELFORMAT ePixelFormat)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("Layer set expected pixel format, format = %d", (int)ePixelFormat);
//* add new pixel formats supported by gpu here.
if(ePixelFormat == PIXEL_FORMAT_NV12 ||
ePixelFormat == PIXEL_FORMAT_NV21 ||
ePixelFormat == PIXEL_FORMAT_YV12)
{
lc->eDisplayPixelFormat = ePixelFormat;
}
else
{
logv("receive pixel format is %d, not match.", lc->eDisplayPixelFormat);
return -1;
}
//* on A83-pad and A83-box , the address should 4k align when format is NV21
#if defined(CONF_GPU_IMG)
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_NV21)
lc->b4KAlignFlag = 1;
#endif
return 0;
}
//* Description: set initial param -- video whether have two stream or not
static int __LayerSetVideoWithTwoStreamFlag(LayerCtrl* l, int bVideoWithTwoStreamFlag)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("LayerSetIsTwoVideoStreamFlag, flag = %d",bVideoWithTwoStreamFlag);
lc->bVideoWithTwoStreamFlag = bVideoWithTwoStreamFlag;
return 0;
}
//* Description: set initial param -- whether picture-bitstream decoded by software decoder
static int __LayerSetIsSoftDecoderFlag(LayerCtrl* l, int bIsSoftDecoderFlag)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("LayerSetIsSoftDecoderFlag, flag = %d",bIsSoftDecoderFlag);
lc->bIsSoftDecoderFlag = bIsSoftDecoderFlag;
return 0;
}
//* Description: set buffer timestamp -- set this param every frame
static int __LayerSetBufferTimeStamp(LayerCtrl* l, int64_t nPtsAbs)
{
LayerCtrlContext* lc;
int64_t renderTime;
lc = (LayerCtrlContext*)l;
#if (defined(CONF_PTS_TOSF) && (CONF_ANDROID_MAJOR_VER >= 5))
static int nVsync = -1;
renderTime = CdxVideoSchedulerSchedule(lc->mVideoScheduler, nPtsAbs);
#if 0 //for debug
static cdx_int64 prePts = -1;
static cdx_int64 prePicPts = -1;
if (prePts > 0)
{
logd("====[diff=%lld us, preRenderTime=%lld us, curRenderTime=%lld us],"
"[diff=%lld, prePicPts=%lld us, nPtsAbs=%lld us]",
(renderTime - prePts)/1000, prePts/1000, renderTime/1000,
(nPtsAbs - prePicPts)/1000, prePicPts/1000, nPtsAbs/1000);
}
prePts = renderTime;
prePicPts = nPtsAbs;
#endif
//attention! 4 vsync period is set after measured in h5(video before audio),
//different platform may has different value.
if (nVsync < 0)
nVsync = GetConfigParamterInt("compensate_vsync", 4);
renderTime += nVsync * CdxVideoSchedulerGetVsyncPeriod(lc->mVideoScheduler);
#else
renderTime = nPtsAbs;
#endif
native_window_set_buffers_timestamp(lc->pNativeWindow, renderTime);
return 0;
}
//* Description: reset nativewindow -- need release old resource and init newer
static void __LayerResetNativeWindow(LayerCtrl* l,void* pNativeWindow)
{
logd("LayerResetNativeWindow : %p ",pNativeWindow);
LayerCtrlContext* lc;
VideoPicture mPicBufInfo;
lc = (LayerCtrlContext*)l;
memset(&mPicBufInfo, 0, sizeof(VideoPicture));
//* we should queue buffer which had dequeued to gpu
int i;
for(i = 0; i < GPU_BUFFER_NUM; i++)
{
if(lc->mGpuBufferInfo[i].nDequeueFlag == 1)
{
//* unlock the buffer.
ANativeWindowBuffer* pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
lc->mGpuBufferInfo[i].nDequeueFlag = 0;
}
}
memset(&lc->mGpuBufferInfo,0,sizeof(GpuBufferInfoT)*GPU_BUFFER_NUM);
lc->pNativeWindow = (ANativeWindow*)pNativeWindow;
if(lc->pNativeWindow != NULL)
lc->bLayerInitialized = 0;
return ;
}
//* Description: get the buffer which owned by nativewindow
static VideoPicture* __LayerGetBufferOwnedByGpu(LayerCtrl* l)
{
LayerCtrlContext* lc;
VideoPicture* pPicture = NULL;
lc = (LayerCtrlContext*)l;
for(int i = 0; i<NUM_OF_PICTURES_KEEP_IN_NODE; i++)
{
if(lc->picNodes[i].bUsed == 1)
{
lc->picNodes[i].bUsed = 0;
pPicture = lc->picNodes[i].pPicture;
break;
}
}
return pPicture;
}
//* Description: get FPS(frames per second) of GPU
//* Limitation: private implement for tvbox-platform
static int __LayerGetDisplayFPS(LayerCtrl* l)
{
enum {
DISPLAY_CMD_GETDISPFPS = 0x29,
};
int dispFPS = 0;
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
#if defined(CONF_PRODUCT_STB)
if(lc->pNativeWindow != NULL)
dispFPS = lc->pNativeWindow->perform(lc->pNativeWindow, NATIVE_WINDOW_GETPARAMETER,
DISPLAY_CMD_GETDISPFPS);
#endif
if (dispFPS <= 0) /* DISPLAY_CMD_GETDISPFPS not support, assume a nice fps */
dispFPS = 60;
return dispFPS;
}
static int __LayerGetBufferNumHoldByGpu(LayerCtrl* l)
{
CDX_UNUSE(l);
return GetConfigParamterInt("pic_4list_num", 3);
}
//* Description: make the video to show -- control the status of display
static int __LayerCtrlShowVideo(LayerCtrl* l)
{
LayerCtrlContext* lc;
int i;
lc = (LayerCtrlContext*)l;
logv("LayerCtrlShowVideo, current show flag = %d", lc->bLayerShowed);
#if defined(CONF_PRODUCT_STB)
if(lc->bLayerShowed == 0)
{
if(lc->pNativeWindow != NULL)
{
lc->bLayerShowed = 1;
lc->pNativeWindow->perform(lc->pNativeWindow,
NATIVE_WINDOW_SETPARAMETER,
HWC_LAYER_SHOW,
1);
}
else
{
logw("the nativeWindow is null when call LayerCtrlShowVideo()");
return -1;
}
}
#endif
return 0;
}
//* Description: make the video to hide -- control the status of display
static int __LayerCtrlHideVideo(LayerCtrl* l)
{
LayerCtrlContext* lc;
int i;
lc = (LayerCtrlContext*)l;
logv("LayerCtrlHideVideo, current show flag = %d", lc->bLayerShowed);
#if defined(CONF_PRODUCT_STB)
if(lc->bLayerShowed == 1)
{
if(lc->pNativeWindow != NULL)
{
lc->bLayerShowed = 0;
lc->pNativeWindow->perform(lc->pNativeWindow,
NATIVE_WINDOW_SETPARAMETER,
HWC_LAYER_SHOW,
0);
}
else
{
logw("the nativeWindow is null when call LayerCtrlHideVideo()");
return -1;
}
}
#endif
return 0;
}
//* Description: query whether the video is showing -- query the status of display
static int __LayerCtrlIsVideoShow(LayerCtrl* l)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
logv("LayerCtrlIsVideoShow : bLayerShowed = %d",lc->bLayerShowed);
return lc->bLayerShowed;
}
//* Description: make the last pic to show always when quit playback
static int __LayerCtrlHoldLastPicture(LayerCtrl* l, int bHold)
{
logv("LayerCtrlHoldLastPicture, bHold = %d", bHold);
//*TODO
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
lc->bHoldLastPictureFlag = bHold;
return 0;
}
//* Description: the picture buf is secure
static int __LayerSetSecure(LayerCtrl* l, int bSecure)
{
logv("__LayerSetSecure, bSecure = %d", bSecure);
//*TODO
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
lc->bProtectFlag = bSecure;
return 0;
}
//* Description: dequeue buffer from nativewindow
static int __LayerDequeueBuffer(LayerCtrl* l,VideoPicture** ppVideoPicture, int bInitFlag)
{
logv("__LayerDequeueBuffer, *ppVideoPicture(%p),bInitFlag(%d)",
*ppVideoPicture,bInitFlag);
LayerCtrlContext* lc = (LayerCtrlContext*)l;
ANativeWindowBuffer* pWindowBuf = NULL;
void* pDataBuf = NULL;
int err = -1;
int i = 0;
if(lc->pNativeWindow == NULL)
{
logw("pNativeWindow is null when dequeue buffer");
return -1;
}
if(lc->bLayerInitialized == 0)
{
if(setLayerParam(lc) != 0)
{
loge("can not initialize layer.");
return -1;
}
lc->bLayerInitialized = 1;
}
//* we should make sure that the dequeue buffer is new when init
if(bInitFlag == 1)
{
pWindowBuf = dequeueTheInitGpuBuffer(lc);
if(pWindowBuf == NULL)
{
loge("*** dequeueTheInitGpuBuffer failed");
return -1;
}
}
else
{
//* dequeue a buffer from the nativeWindow object.
err = lc->pNativeWindow->dequeueBuffer_DEPRECATED(lc->pNativeWindow, &pWindowBuf);
if(err != 0)
{
logw("dequeue buffer fail, return value from dequeueBuffer_DEPRECATED() method is %d.",
err);
return -1;
}
}
//* lock the data buffer.
lc->pNativeWindow->lockBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
{
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
Rect bounds(lc->nWidth, lc->nHeight);
graphicMapper.lock(pWindowBuf->handle,lc->nUsage, bounds, &pDataBuf);
}
err = matchWindowBufferAndPicture(lc, pWindowBuf, (char*)pDataBuf, ppVideoPicture, bInitFlag);
if(err == -1)
{
loge("matchWindowBufferAndPicture failed");
return -1;
}
return 0;
}
//* Description: queue buffer to nativewindow
static int __LayerQueueBuffer(LayerCtrl* l,VideoPicture* pInPicture, int bValid)
{
logv("LayerQueueBuffer: pInPicture = %p, pData0 = %p",
pInPicture,pInPicture->pData0);
ANativeWindowBuffer* pWindowBuf = NULL;
int i = 0;
char* pBuf = NULL;
int nBufId = -1;
LayerCtrlContext* lc = (LayerCtrlContext*)l;
if(lc->bLayerInitialized == 0)
{
if(setLayerParam(lc) != 0)
{
loge("can not initialize layer.");
return -1;
}
lc->bLayerInitialized = 1;
}
for(i = 0; i<NUM_OF_PICTURES_KEEP_IN_NODE; i++)
{
if(lc->picNodes[i].bUsed == 0)
{
lc->picNodes[i].bUsed = 1;
lc->picNodes[i].pPicture = pInPicture;
break;
}
}
if(i == NUM_OF_PICTURES_KEEP_IN_NODE)
{
loge("*** picNode is full when queue buffer");
return -1;
}
//loge("*** LayerQueueBuffer pInPicture = %p, bValid = %d",pInPicture,bValid);
pBuf = (char*)pInPicture->phyYBufAddr;
nBufId = pInPicture->nBufId;
pWindowBuf = lc->mGpuBufferInfo[nBufId].pWindowBuf;
lc->picNodes[i].pNodeWindowBuf = pWindowBuf;
//* unlock the buffer.
{
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
}
if(bValid == 1)
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
else
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
lc->mGpuBufferInfo[nBufId].nDequeueFlag = 0;
logv("******LayerQueueBuffer finish!");
return 0;
}
//* Description: release the buffer by ion
static int __LayerReleaseBuffer(LayerCtrl* l,VideoPicture* pPicture)
{
logd("***LayerReleaseBuffer");
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
ion_handle_abstract_t handle_ion = ION_NULL_VALUE;
handle_ion = (ion_handle_abstract_t)(uintptr_t)pPicture->pPrivate;
ion_free(lc->ionFd,handle_ion);
return 0;
}
static int __LayerReset(LayerCtrl* l)
{
LayerCtrlContext* lc;
int i;
lc = (LayerCtrlContext*)l;
for(i = 0; i < lc->nGpuBufferCount; i++)
{
//* we should queue buffer which had dequeued to gpu
if(lc->mGpuBufferInfo[i].nDequeueFlag == 1)
{
//* unlock the buffer.
ANativeWindowBuffer* pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
lc->mGpuBufferInfo[i].nDequeueFlag = 0;
}
if(lc->mGpuBufferInfo[i].handle_ion != ION_NULL_VALUE)
{
logd("ion_free: handle_ion[%d] = %p",i,lc->mGpuBufferInfo[i].handle_ion);
ion_free(lc->ionFd,lc->mGpuBufferInfo[i].handle_ion);
}
lc->mGpuBufferInfo[i].pWindowBuf = NULL;
lc->mGpuBufferInfo[i].nUsedFlag = 0;
}
for(i = 0; i<NUM_OF_PICTURES_KEEP_IN_NODE; i++)
{
lc->picNodes[i].bUsed = 0;
}
return 0;
}
static int __LayerControl(LayerCtrl* l, int cmd, void *para)
{
LayerCtrlContext *lc = (LayerCtrlContext*)l;
CDX_UNUSE(para);
switch(cmd)
{
#if (defined(CONF_PTS_TOSF) && (CONF_ANDROID_MAJOR_VER >= 5))
case CDX_LAYER_CMD_RESTART_SCHEDULER:
{
CdxVideoSchedulerRestart(lc->mVideoScheduler);
break;
}
#endif
default:
break;
}
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(void* pNativeWindow)
{
logv("LayerInit.");
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)malloc(sizeof(LayerCtrlContext));
if(lc == NULL)
{
loge("malloc memory fail.");
return NULL;
}
memset(lc, 0, sizeof(LayerCtrlContext));
lc->ionFd = -1;
lc->ionFd = ion_open();
logd("ion open fd = %d",lc->ionFd);
if(lc->ionFd < -1)
{
loge("ion open fail ! ");
return NULL;
}
lc->base.ops = &mLayerControlOps;
lc->base.pNativeWindow = (void*)pNativeWindow;
lc->pNativeWindow = (ANativeWindow*)pNativeWindow;
#if (defined(CONF_PTS_TOSF) && (CONF_ANDROID_MAJOR_VER >= 5))
lc->mVideoScheduler = CdxVideoSchedulerCreate();
if (lc->mVideoScheduler == NULL)
logw("CdxVideoSchedulerCreate failed");
#endif
return (LayerCtrl*)&lc->base;
}