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

2235 lines
69 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"
#include <cutils/properties.h>
#if (((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
#include <gui/ISurfaceTexture.h>
#elif ((CONF_ANDROID_MAJOR_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))
#include <hardware/hal_public.h>
#endif
#include <linux/ion.h>
#include <ion/ion.h>
#include <sys/mman.h>
#if (defined(CONF_PTS_TOSF))
#include "VideoFrameSchedulerWrap.h"
#endif
#if (defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE) || defined(CONF_AFBC_ENABLE))
#include <hardware/sunxi_metadata_def.h>
#endif
#if defined(CONF_PRODUCT_STB)
#if ((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4))
#include <gui/ISurfaceComposer.h>
//#include <private/gui/ComposerService.h> //* another way
#include <binder/IServiceManager.h>
#elif (CONF_ANDROID_MAJOR_VER == 7)
#include "libdispclient.h"
#endif
#endif
using namespace android;
#if defined(CONF_ION_HANDLE_POINTER)
typedef struct ion_handle* ion_handle_abstract_t;
#define ION_NULL_VALUE (NULL)
#elif defined(CONF_ION_HANDLE_INT)
typedef ion_user_handle_t ion_handle_abstract_t;
#define ION_NULL_VALUE (0)
#else
#error: not define ion_handle type.
#endif
#if defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE)
#define CONF_10BIT_ENABLE
#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;
};
enum BufferStatus
{
UNRECOGNIZED, // not a tracked buffer
OWN_BY_NATIVE_WINDOW,
OWN_BY_US,
OWN_BY_DECODER,
};
typedef struct GpuBufferInfoS
{
ANativeWindowBuffer* pWindowBuf;
ion_handle_abstract_t handle_ion;
int nBufFd;
char* pBufPhyAddr;
char* pBufVirAddr;
enum BufferStatus mStatus;
int nUsedFlag;
void* pMetaDataVirAddr;
int nMetaDataVirAddrSize;
int nMetaDataMapFd;
ion_handle_abstract_t metadata_handle_ion;
VideoPicture pPicture;
}GpuBufferInfoT;
typedef struct LayerCtrlContext
{
LayerCtrl base;
ANativeWindow* pNativeWindow;
enum EPIXELFORMAT eDisplayPixelFormat;
enum EVIDEOCODECFORMAT eVideoCodecFormat;
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)||((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4))))
CdxVideoScheduler *mVideoScheduler;
#endif
int bHdrVideoFlag;
int b10BitVideoFlag;
int bAfbcModeFlag;
int b3DDisplayFlag;
int nVideoWidth;
int nVideoHeight;
//* there are some buffers cached in hwc at AndroidO,
//* we should switch buffers in cache, or the number of buffers will double in case loop playback
//* only swicth buffer in start of play, no need in resetSurface.
int bSwitchBuffer;
int nSwitchNum;
//* the buffer used by decoder & display,
//* we should check whether the buffers are freed avoid memoryleak;
int nUnFreeBufferCount;
}LayerCtrlContext;
static int getVirAddrOfMetadataBuffer(LayerCtrlContext* lc,
ANativeWindowBuffer* pWindowBuf,
ion_handle_abstract_t* pHandle_ion,
int* pMapfd,
int* pVirsize,
void** pViraddress)
{
ion_handle_abstract_t handle_ion = ION_NULL_VALUE;
int nMapfd = -1;
unsigned char* nViraddress = 0;
int nVirsize = 0;
int ret = 0;
#if (defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE) || defined(CONF_AFBC_ENABLE))
#if defined(CONF_GPU_MALI)
private_handle_t* hnd = (private_handle_t *)(pWindowBuf->handle);
if(hnd != NULL)
{
ret = ion_import(lc->ionFd, hnd->metadata_fd, &handle_ion);
if(ret < 0)
{
loge("ion_import fail, maybe the buffer was free by display!");
return -1;
}
nVirsize = hnd->ion_metadata_size;
}
else
{
logd("the hnd is wrong : hnd = %p", hnd);
return -1;
}
ret = ion_map(lc->ionFd, handle_ion, nVirsize,
PROT_READ | PROT_WRITE, MAP_SHARED, 0, &nViraddress, &nMapfd);
if(ret < 0)
{
loge("ion_map fail!");
if(nMapfd >= 0)
close(nMapfd);
ion_free(lc->ionFd, handle_ion);
*pViraddress = 0;
*pVirsize = 0;
*pMapfd = 0;
*pHandle_ion = 0;
return -1;
}
#else
#error invalid GPU type config
#endif
#endif
*pViraddress = nViraddress;
*pVirsize = nVirsize;
*pMapfd = nMapfd;
*pHandle_ion = handle_ion;
return 0;
}
static int freeVirAddrOfMetadataBuffer(LayerCtrlContext* lc,
ion_handle_abstract_t handle_ion,
int mapfd,
int virsize,
void* viraddress)
{
#if (defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE) || defined(CONF_AFBC_ENABLE))
if (viraddress != 0) {
munmap(viraddress, virsize);
}
if (mapfd != 0) {
close(mapfd);
}
if (handle_ion != 0) {
ion_free(lc->ionFd, handle_ion);
}
#endif
return 0;
}
#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);
int ret = -1;
void* nViraddress = NULL;
int nVirsize = 0;
int nMapfd = -1;
ion_handle_abstract_t metadata_handle_ion = ION_NULL_VALUE;
if (lc->pNativeWindow == NULL || lc->bLayerInitialized == 0)
{
logv("skip %s", __func__);
return 0;
}
native_window_set_buffers_format(lc->pNativeWindow, HAL_PIXEL_FORMAT_AW_NV12);
#if defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE)
native_window_set_buffers_data_space(lc->pNativeWindow, HAL_DATASPACE_UNKNOWN);
#endif
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);
unsigned int nUsage = lc->nUsage|GRALLOC_USAGE_SW_WRITE_OFTEN;
graphicMapper.lock(pWindowBuf->handle, 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);
}
ret = getVirAddrOfMetadataBuffer(lc, pWindowBuf, &metadata_handle_ion,
&nMapfd, &nVirsize, &nViraddress);
if(ret == -1)
{
loge("getVirAddrOfMetadataBuffer failed");
return -1;
}
#if (defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE) || defined(CONFIG_AFBC_ENABLE))
sunxi_metadata* s_metadata = (sunxi_metadata*)nViraddress;
s_metadata->flag = 0;
#endif
//* unlock the buffer.
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
freeVirAddrOfMetadataBuffer(lc, metadata_handle_ion, nMapfd, nVirsize, nViraddress);
}
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 for 3D/2D rotate case.
//* just init alignment 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)
//* when the display to 2D,the appearance of "Green edges" in ratation if not init.
//* 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->bVideoWithTwoStreamFlag == 1)
{
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_NV21)
{
//* Y1
int nRealHeight = pWindowBuf->height/2;
int nInitHeight = GetConfigParamterInt("gpu_align_bitwidth", 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;
}
}
else
{
if(lc->eDisplayPixelFormat == PIXEL_FORMAT_NV21)
{
//* Y
int nRealHeight = pWindowBuf->height;
int nInitHeight = GetConfigParamterInt("gpu_align_bitwidth", 32);
int nSkipLen = pWindowBuf->stride*(nRealHeight - nInitHeight);
int nCpyLenY = pWindowBuf->stride*nInitHeight;
memset(pDataBuf+nSkipLen, 0x10, nCpyLenY);
//*UV
nSkipLen += nCpyLenY;
nSkipLen += (pWindowBuf->stride)*(nRealHeight/2 - nInitHeight/2);
int nCpyLenUV = (pWindowBuf->stride)*(nInitHeight/2);
memset(pDataBuf+nSkipLen, 0x80, nCpyLenUV);
}
else if(lc->eDisplayPixelFormat == PIXEL_FORMAT_YV12)
{
if(lc->eVideoCodecFormat == VIDEO_CODEC_FORMAT_VP9 && lc->bIsSoftDecoderFlag)
{
//* Y
int nRealHeight = pWindowBuf->height;
int nSkipLen = pWindowBuf->stride*nRealHeight;
memset(pDataBuf, 0x10, pWindowBuf->stride*nRealHeight);
//* UV
memset(pDataBuf+nSkipLen,0x80,nSkipLen/2);
}
else
{
//* Y
int nRealHeight = pWindowBuf->height;
int nInitHeight = GetConfigParamterInt("gpu_align_bitwidth", 32);
int nSkipLen = pWindowBuf->stride*(nRealHeight - nInitHeight);
int nCpyLenY = pWindowBuf->stride*nInitHeight;
memset(pDataBuf+nSkipLen, 0x10, nCpyLenY);
//*U
nSkipLen += nCpyLenY;
nSkipLen += (pWindowBuf->stride/2)*(nRealHeight/2 - nInitHeight/2);
int nCpyLenU = (pWindowBuf->stride/2)*(nInitHeight/2);
memset(pDataBuf+nSkipLen, 0x80, nCpyLenU);
//*V
nSkipLen += nCpyLenU;
nSkipLen += (pWindowBuf->stride/2)*(nRealHeight/2 - nInitHeight/2);
int nCpyLenV = (pWindowBuf->stride/2)*(nInitHeight/2);
memset(pDataBuf+nSkipLen, 0x80, nCpyLenV);
}
}
}
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;
}
#if (CONF_ANDROID_MAJOR_VER >= 8)
sp<GraphicBuffer> mGraphicBuffer(GraphicBuffer::from(pWindowBuffer));
#else
sp<GraphicBuffer> mGraphicBuffer(new GraphicBuffer(pWindowBuffer, false));
#endif
// 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;
}
}
static cdx_int64 GetNowUs()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
}
//* 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;
}
}
//if(lc->bVideoWithTwoStreamFlag == 1)
lc->nUsage |= GRALLOC_USAGE_SW_WRITE_OFTEN; // we will memset bottom green screen
//* add other usage
lc->nUsage |= GRALLOC_USAGE_SW_READ_NEVER |
GRALLOC_USAGE_HW_TEXTURE |
GRALLOC_USAGE_EXTERNAL_DISP;
#if (defined(CONF_AFBC_ENABLE))
// do not need set the flag GRALLOC_USAGE_METADATA_BUF;
// gralloc will alloc metadata buffer in all mode
if (lc->bAfbcModeFlag)
lc->nUsage |= GRALLOC_USAGE_AFBC_MODE;
#endif
switch(lc->eDisplayPixelFormat)
{
case PIXEL_FORMAT_YV12: //* why YV12 use this pixel format.
{
logd("++++++++ yv12");
pixelFormat = HAL_PIXEL_FORMAT_YV12;
#if (defined(CONF_10BIT_ENABLE))
if(lc->b10BitVideoFlag)
pixelFormat = HAL_PIXEL_FORMAT_AW_YV12_10bit;
#endif
break;
}
case PIXEL_FORMAT_NV21:
{
logd("++++++++++++++ nv21");
pixelFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
#if (defined(CONF_10BIT_ENABLE))
if(lc->b10BitVideoFlag)
pixelFormat = HAL_PIXEL_FORMAT_AW_NV21_10bit;
#endif
break;
}
case PIXEL_FORMAT_NV12: //* display system do not support NV12.
{
loge("=+++++ it is nv12, just for test");
pixelFormat = HAL_PIXEL_FORMAT_AW_NV12; //HAL_PIXEL_FORMAT_AW_NV12;
#if (defined(CONF_10BIT_ENABLE))
if(lc->b10BitVideoFlag)
pixelFormat = HAL_PIXEL_FORMAT_AW_NV12_10bit;
#endif
break;
}
#if (defined(CONF_10BIT_ENABLE))
case PIXEL_FORMAT_P010_UV:
{
pixelFormat = HAL_PIXEL_FORMAT_AW_P010_UV;
break;
}
case PIXEL_FORMAT_P010_VU:
{
pixelFormat = HAL_PIXEL_FORMAT_AW_P010_VU;
break;
}
#endif
default:
{
loge("unsupported pixel format.");
return -1;
}
}
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;
logd("crop (l,t,r,b); %d %d %d %d", crop.left, crop.top, crop.right, crop.bottom);
if(lc->nGpuBufferCount <= 0)
{
loge("error: the lc->nGpuBufferCount[%d] is invalid!",lc->nGpuBufferCount);
return -1;
}
native_window_set_usage(lc->pNativeWindow,lc->nUsage);
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_dimensions(lc->pNativeWindow, nGpuBufWidth, nGpuBufHeight);
native_window_set_buffers_format(lc->pNativeWindow, pixelFormat);
native_window_set_buffer_count(lc->pNativeWindow,lc->nGpuBufferCount);
lc->pNativeWindow->perform(lc->pNativeWindow, NATIVE_WINDOW_SET_CROP, &crop);
return 0;
}
static int switchBuffer(LayerCtrlContext* lc)
{
int64_t start=GetNowUs();
ANativeWindowBuffer* pWindowBuf = NULL;
int i=0, j=0;
struct checkBuffer
{
ANativeWindowBuffer* pWindowBuf;
int bDeque;
};
void* pDataBuf = NULL;
int YSize = lc->nWidth*lc->nHeight;
struct checkBuffer* bufferV = (struct checkBuffer*)malloc(lc->nGpuBufferCount*sizeof(struct checkBuffer));
for(i = 0; i < lc->nGpuBufferCount; i++)
{
do
{
lc->pNativeWindow->dequeueBuffer_DEPRECATED(lc->pNativeWindow, &pWindowBuf);
for(j=0; j<i; j++)
{
if(bufferV[j].pWindowBuf == pWindowBuf)
{
bufferV[j].bDeque = 1;
break;
}
}
} while(j != i);
bufferV[i].pWindowBuf = pWindowBuf;
bufferV[i].bDeque = 1;
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);
memset(pDataBuf, 0x10, YSize);
memset((char*)pDataBuf+YSize, 0x80, YSize/2);
graphicMapper.unlock(pWindowBuf->handle);
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
bufferV[i].bDeque = 0;
}
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(bufferV[i].bDeque)
{
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow, bufferV[i].pWindowBuf);
bufferV[i].bDeque = 0;
}
}
free(bufferV);
logd("=== diff: %lld", GetNowUs()-start);
return 0;
}
int getPhyAddrOfGpuBuffer(LayerCtrlContext* lc,
ANativeWindowBuffer* pWindowBuf,
ion_handle_abstract_t* pHandle_ion,
uintptr_t* pPhyaddress,
int* pBufFd)
{
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 get the phyaddr, because queueBuffer and queueBuffer need
//* get the buffer id according the phyaddr
//if(lc->bIsSoftDecoderFlag == 0)
{
if(lc->ionFd >= 0)
{
nPhyaddress = CdcIonGetPhyAdr(lc->ionFd, (uintptr_t)handle_ion);
*pBufFd = CdcIonGetFd(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;
}
VideoPicture* dequeueTheInitGpuBuffer(LayerCtrlContext* lc)
{
int err = -1;
int i = 0;
int nCancelNum = 0;
int nNeedCancelFlag = 0;
int nCancelIndex[GPU_BUFFER_NUM] = {-1};
ANativeWindowBuffer* pWindowBuf = NULL;
int ret = -1;
uintptr_t nPhyaddress = 0;
int nBufFd = -1;
ion_handle_abstract_t handle_ion = ION_NULL_VALUE;
void* nViraddress = NULL;
int nVirsize = 0;
int nMapfd = -1;
ion_handle_abstract_t metadata_handle_ion = ION_NULL_VALUE;
dequeue_buffer:
//* queueBuffer in switchBuffer, so there is a buffer in surfaceflinger cannot be dequeue.
//* we must queue a buffer in order to dequeu the last buffer
if(lc->nSwitchNum == lc->nGpuBufferCount-1 && lc->bSwitchBuffer)
{
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow,
lc->mGpuBufferInfo[lc->nGpuBufferCount-3].pWindowBuf);
lc->mGpuBufferInfo[lc->nGpuBufferCount-3].mStatus = OWN_BY_NATIVE_WINDOW;
lc->nSwitchNum --;
}
//* 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 &&
pWindowBuf == lc->mGpuBufferInfo[i].pWindowBuf)
{
nNeedCancelFlag = 1;
nCancelIndex[nCancelNum] = i;
nCancelNum++;
logv("the buffer[%p] not return, dequeue again!", pWindowBuf);
goto dequeue_buffer;
}
}
int j=0;
if(nNeedCancelFlag == 1)
{
for(j = 0; j<nCancelNum; j++)
{
int nIndex = nCancelIndex[j];
ANativeWindowBuffer* pTmpWindowBuf = lc->mGpuBufferInfo[nIndex].pWindowBuf;
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pTmpWindowBuf);
}
nCancelNum = 0;
nNeedCancelFlag = 0;
}
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].pWindowBuf == NULL)
{
lc->mGpuBufferInfo[i].mStatus = OWN_BY_US;
break;
}
}
if(i == lc->nGpuBufferCount)
{
loge("cannot find the buffer");
return NULL;
}
lc->nSwitchNum ++;
ret = getPhyAddrOfGpuBuffer(lc, pWindowBuf, &handle_ion, &nPhyaddress, &nBufFd);
if(ret == -1)
{
loge("getPhyAddrOfGpuBuffer failed");
return NULL;
}
//* get the virtual address
lc->pNativeWindow->lockBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
Rect bounds(lc->nWidth, lc->nHeight);
graphicMapper.lock(pWindowBuf->handle,lc->nUsage, bounds, &nViraddress);
// if witch buffer( the pixels have init black), we donot need init partial buffer
initPartialGpuBuffer((char*)nViraddress, pWindowBuf, lc);
lc->mGpuBufferInfo[i].pWindowBuf = pWindowBuf;
lc->mGpuBufferInfo[i].handle_ion = handle_ion;
lc->mGpuBufferInfo[i].pBufVirAddr = (char*)nViraddress;
lc->mGpuBufferInfo[i].pBufPhyAddr = (char*)nPhyaddress;
lc->mGpuBufferInfo[i].nBufFd = nBufFd;
lc->mGpuBufferInfo[i].mStatus = OWN_BY_DECODER;
lc->mGpuBufferInfo[i].nUsedFlag = 1;
lc->nUnFreeBufferCount++;
private_handle_t *hnd = (private_handle_t*)pWindowBuf->handle;
logd("==== init: buf(fd: %d), nUnFreeBufferCount: %d, aw_buf_id: %lld, private_handle_t: %p", nBufFd, lc->nUnFreeBufferCount, hnd->aw_buf_id, hnd);
ret = getVirAddrOfMetadataBuffer(lc, pWindowBuf, &metadata_handle_ion,
&nMapfd, &nVirsize, &nViraddress);
if(ret == -1)
{
loge("getVirAddrOfMetadataBuffer failed");
return NULL;
}
lc->mGpuBufferInfo[i].pMetaDataVirAddr = nViraddress;
lc->mGpuBufferInfo[i].nMetaDataVirAddrSize = nVirsize;
lc->mGpuBufferInfo[i].nMetaDataMapFd = nMapfd;
lc->mGpuBufferInfo[i].metadata_handle_ion = metadata_handle_ion;
VideoPicture* pPicture = &lc->mGpuBufferInfo[i].pPicture;
//* set the buffer address
pPicture->pData0 = lc->mGpuBufferInfo[i].pBufVirAddr;
#if (defined(CONF_10BIT_ENABLE))
if((lc->eDisplayPixelFormat == PIXEL_FORMAT_P010_UV)
||(lc->eDisplayPixelFormat == PIXEL_FORMAT_P010_VU))
{
pPicture->pData1 = pPicture->pData0 + (pWindowBuf->height * pWindowBuf->stride*2);
pPicture->pData2 = pPicture->pData1 + (pWindowBuf->height * pWindowBuf->stride)/2;
pPicture->phyYBufAddr = (uintptr_t)lc->mGpuBufferInfo[i].pBufPhyAddr;
pPicture->phyCBufAddr = pPicture->phyYBufAddr + (pWindowBuf->height * pWindowBuf->stride*2);
}
else
#endif
{
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->nBufFd = nBufFd;
pPicture->ePixelFormat = lc->eDisplayPixelFormat;
pPicture->nWidth = pWindowBuf->stride;
pPicture->nHeight = pWindowBuf->height;
pPicture->nLineStride = pWindowBuf->stride;
pPicture->pMetaData = lc->mGpuBufferInfo[i].pMetaDataVirAddr;
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;
}
return pPicture;
}
#if (defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE))
static android_dataspace_t getDataspaceFromVideoPicture(const VideoPicture *pic)
{
uint32_t space = HAL_DATASPACE_UNKNOWN;
switch (pic->transfer_characteristics)
{
case VIDEO_TRANSFER_RESERVED_0:
case VIDEO_TRANSFER_BT1361:
case VIDEO_TRANSFER_UNSPECIFIED:
case VIDEO_TRANSFER_RESERVED_1:
space |= HAL_DATASPACE_TRANSFER_UNSPECIFIED;
break;
case VIDEO_TRANSFER_GAMMA2_2:
space |= HAL_DATASPACE_TRANSFER_GAMMA2_2;
break;
case VIDEO_TRANSFER_GAMMA2_8:
space |= HAL_DATASPACE_TRANSFER_GAMMA2_8;
break;
case VIDEO_TRANSFER_SMPTE_170M:
space |= HAL_DATASPACE_TRANSFER_SMPTE_170M;
break;
case VIDEO_TRANSFER_SMPTE_240M:
space |= HAL_DATASPACE_TRANSFER_UNSPECIFIED;
break;
case VIDEO_TRANSFER_LINEAR:
space |= HAL_DATASPACE_TRANSFER_LINEAR;
break;
case VIDEO_TRANSFER_LOGARITHMIC_0:
case VIDEO_TRANSFER_LOGARITHMIC_1:
case VIDEO_TRANSFER_IEC61966:
case VIDEO_TRANSFER_BT1361_EXTENDED:
space |= HAL_DATASPACE_TRANSFER_UNSPECIFIED;
break;
case VIDEO_TRANSFER_SRGB:
space |= HAL_DATASPACE_TRANSFER_SRGB;
break;
case VIDEO_TRANSFER_BT2020_0:
case VIDEO_TRANSFER_BT2020_1:
space |= HAL_DATASPACE_TRANSFER_UNSPECIFIED;
break;
case VIDEO_TRANSFER_ST2084:
space |= HAL_DATASPACE_TRANSFER_ST2084;
break;
case VIDEO_TRANSFER_ST428_1:
space |= HAL_DATASPACE_TRANSFER_UNSPECIFIED;
break;
case VIDEO_TRANSFER_HLG:
space |= HAL_DATASPACE_TRANSFER_HLG;
break;
default:
space |= HAL_DATASPACE_TRANSFER_UNSPECIFIED;
break;
}
switch (pic->matrix_coeffs)
{
case VIDEO_MATRIX_COEFFS_IDENTITY:
space |= HAL_DATASPACE_STANDARD_UNSPECIFIED;
break;
case VIDEO_MATRIX_COEFFS_BT709:
space |= HAL_DATASPACE_STANDARD_BT709;
break;
case VIDEO_MATRIX_COEFFS_UNSPECIFIED_0:
case VIDEO_MATRIX_COEFFS_RESERVED_0:
space |= HAL_DATASPACE_STANDARD_UNSPECIFIED;
break;
case VIDEO_MATRIX_COEFFS_BT470M:
space |= HAL_DATASPACE_STANDARD_BT470M;
break;
case VIDEO_MATRIX_COEFFS_BT601_625_0:
space |= HAL_DATASPACE_BT601_625;
break;
case VIDEO_MATRIX_COEFFS_BT601_625_1:
space |= HAL_DATASPACE_BT601_525;
break;
case VIDEO_MATRIX_COEFFS_SMPTE_240M:
case VIDEO_MATRIX_COEFFS_YCGCO:
space |= HAL_DATASPACE_STANDARD_UNSPECIFIED;
break;
case VIDEO_MATRIX_COEFFS_BT2020:
space |= HAL_DATASPACE_STANDARD_BT2020;
break;
case VIDEO_MATRIX_COEFFS_BT2020_CONSTANT_LUMINANCE:
space |= HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE;
break;
case VIDEO_MATRIX_COEFFS_SOMPATE:
case VIDEO_MATRIX_COEFFS_CD_NON_CONSTANT_LUMINANCE:
case VIDEO_MATRIX_COEFFS_CD_CONSTANT_LUMINANCE:
case VIDEO_MATRIX_COEFFS_BTICC:
space |= HAL_DATASPACE_STANDARD_UNSPECIFIED;
break;
default:
space |= HAL_DATASPACE_STANDARD_UNSPECIFIED;
break;
}
switch (pic->video_full_range_flag)
{
case VIDEO_FULL_RANGE_LIMITED:
space |= HAL_DATASPACE_RANGE_LIMITED;
break;
case VIDEO_FULL_RANGE_FULL:
space |= HAL_DATASPACE_RANGE_FULL;
break;
default:
{
loge("should not be here");
abort();
}
}
return (android_dataspace_t)space;
}
#endif
#if defined(CONF_PRODUCT_STB)
static void setDisplay3DMode(LayerCtrlContext* lc)
{
if (lc->bVideoWithTwoStreamFlag == 0)
return;
if (lc->b3DDisplayFlag == 1)
return;
if (lc->nVideoHeight == 0) // set 3d display after height got
return;
if(lc->bVideoWithTwoStreamFlag == 1)
property_set("mediasw.doublestream", "1");
else
property_set("mediasw.doublestream", "0");
#if ((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4))
//sp<ISurfaceComposer> composer(ComposerService::getComposerService());
logd("abao lc->nDisplayHeight=%d, nHeight=%d", lc->nDisplayHeight, lc->nHeight);
String16 name("SurfaceFlinger");
sp<IServiceManager> sm = defaultServiceManager();
sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(sm->checkService(name));
if(composer->getDisplayParameter(0, DISPLAY_CMD_GETSUPPORT3DMODE, 0, 0))
{
composer->setDisplayParameter(0, DISPLAY_CMD_SET3DMODE,
DISPLAY_3D_TOP_BOTTOM_HDMI, lc->nVideoHeight*2, 0);
}
#elif (CONF_ANDROID_MAJOR_VER == 7)
displaydClient client;
if(client.getSupport3DMode(1) == 1)
{
client.set3DLayerMode(1, DISPLAY_3D_TOP_BOTTOM_HDMI);
}
#endif
lc->b3DDisplayFlag == 1;
}
#endif
static void __LayerRelease(LayerCtrl* l)
{
logv("__LayerRelease");
LayerCtrlContext* lc;
VPictureNode* nodePtr;
int i;
int ret;
VideoPicture mPicBufInfo;
ANativeWindowBuffer* pWindowBuf;
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 funshion apk, when reopen the apk to continue playing
if(lc->pNativeWindow != NULL)
native_window_api_connect(lc->pNativeWindow, NATIVE_WINDOW_API_MEDIA);
for(i = 0; i < GPU_BUFFER_NUM; i++)
{
pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
if(lc->mGpuBufferInfo[i].mStatus != UNRECOGNIZED)
{
//* unlock the buffer.
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
}
//* we should queue buffer which had dequeued to gpu
if(lc->mGpuBufferInfo[i].mStatus == OWN_BY_DECODER
|| lc->mGpuBufferInfo[i].mStatus == OWN_BY_US)
{
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
lc->mGpuBufferInfo[i].mStatus = OWN_BY_NATIVE_WINDOW;
}
if(lc->mGpuBufferInfo[i].nBufFd >= 0)
{
logd("close: ion_buf_fd[%d] = %d", i, lc->mGpuBufferInfo[i].nBufFd);
close(lc->mGpuBufferInfo[i].nBufFd);
}
if(lc->mGpuBufferInfo[i].handle_ion != ION_NULL_VALUE)
{
lc->nUnFreeBufferCount--;
logd("ion_free: handle_ion[%d] = %p, nUnFreeBufferCount: %d",
i, lc->mGpuBufferInfo[i].handle_ion, lc->nUnFreeBufferCount);
ion_free(lc->ionFd,lc->mGpuBufferInfo[i].handle_ion);
}
if(lc->mGpuBufferInfo[i].pMetaDataVirAddr != NULL)
{
munmap(lc->mGpuBufferInfo[i].pMetaDataVirAddr,lc->mGpuBufferInfo[i].nMetaDataVirAddrSize);
}
if(lc->mGpuBufferInfo[i].nMetaDataMapFd >= 0)
{
close(lc->mGpuBufferInfo[i].nMetaDataMapFd);
}
if(lc->mGpuBufferInfo[i].metadata_handle_ion != ION_NULL_VALUE)
{
ion_free(lc->ionFd,lc->mGpuBufferInfo[i].metadata_handle_ion);
}
lc->mGpuBufferInfo[i].pWindowBuf = NULL;
lc->mGpuBufferInfo[i].nUsedFlag = 0;
lc->mGpuBufferInfo[i].mStatus = UNRECOGNIZED;
}
if(lc->bProtectFlag == 1 /*|| lc->bHoldLastPictureFlag == 0*/)
{
ret = pushBlankBuffersToNativeWindow(lc);
if(ret != 0)
{
loge("pushBlankBuffersToNativeWindow appear error!: ret = %d",ret);
}
}
if(lc->nUnFreeBufferCount > 0)
{
logw("========= memory leak : %d", lc->nUnFreeBufferCount);
}
#if defined(CONF_PRODUCT_STB)
#if ((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER >= 4))
if(lc->bVideoWithTwoStreamFlag == 1)
{
//sp<ISurfaceComposer> composer(ComposerService::getComposerService());
String16 name("SurfaceFlinger");
sp<IServiceManager> sm = defaultServiceManager();
sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(sm->checkService(name));
if(composer->getDisplayParameter(0, DISPLAY_CMD_GETSUPPORT3DMODE, 0, 0))
{
composer->setDisplayParameter(0, DISPLAY_CMD_SET3DMODE, DISPLAY_2D_ORIGINAL, 0, 0);
}
}
#elif (CONF_ANDROID_MAJOR_VER == 7)
if(lc->bVideoWithTwoStreamFlag == 1)
{
displaydClient client;
if(client.getSupport3DMode(1) == 1)
client.set3DLayerMode(1, DISPLAY_2D_ORIGINAL);
}
#endif
#endif
}
static void __LayerDestroy(LayerCtrl* l)
{
logd("__LayerDestroy");
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
if(lc->nUnFreeBufferCount > 0)
{
logw("========= memory leak : %d", lc->nUnFreeBufferCount);
}
if(lc->ionFd >= 0)
{
ion_close(lc->ionFd);
}
#if (defined(CONF_PTS_TOSF))
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);
lc->nVideoWidth = nDisplayWidth;
lc->nVideoHeight = nDisplayHeight;
#if defined(CONF_PRODUCT_STB)
setDisplay3DMode(lc);
#endif
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;
}
#if (defined(CONF_10BIT_ENABLE))
else if(ePixelFormat == PIXEL_FORMAT_P010_UV ||
ePixelFormat == PIXEL_FORMAT_P010_VU)
{
lc->eDisplayPixelFormat = ePixelFormat;
}
#endif
else
{
logv("receive pixel format is %d, not match.", lc->eDisplayPixelFormat);
return -1;
}
/*
#if defined(CONF_GPU_IMG)
//* on A83-pad and A83-box , the address should 4k align when format is NV21.
//* it is a GPU bug, we had make sure that it is no need 4K align for IMG
if((lc->eDisplayPixelFormat == PIXEL_FORMAT_NV21) ||
(lc->eDisplayPixelFormat == PIXEL_FORMAT_NV12))
lc->b4KAlignFlag = 1;
#endif
*/
return 0;
}
//* Description: set initial param -- video whether have hdr info or not
static int LayerSetHdrInfo(LayerCtrl *l, const FbmBufInfo *fbmInfo)
{
if (!fbmInfo)
{
loge("fbmInfo is null");
return -1;
}
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
lc->bHdrVideoFlag = fbmInfo->bHdrVideoFlag;
lc->b10BitVideoFlag = fbmInfo->b10bitVideoFlag;
lc->bAfbcModeFlag = fbmInfo->bAfbcModeFlag;
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))
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;
ANativeWindowBuffer* pWindowBuf;
memset(&mPicBufInfo, 0, sizeof(VideoPicture));
//* we should queue buffer which had dequeued to gpu
int i;
for(i = 0; i < GPU_BUFFER_NUM; i++)
{
pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
if(lc->mGpuBufferInfo[i].mStatus != UNRECOGNIZED)
{
//* unlock the buffer.
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
}
if(lc->mGpuBufferInfo[i].mStatus == OWN_BY_DECODER
|| lc->mGpuBufferInfo[i].mStatus == OWN_BY_US)
{
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
lc->mGpuBufferInfo[i].mStatus = UNRECOGNIZED;
}
}
//memset(&lc->mGpuBufferInfo,0,sizeof(GpuBufferInfoT)*GPU_BUFFER_NUM);
lc->pNativeWindow = (ANativeWindow*)lc->base.pNativeWindow ;//(ANativeWindow*)pNativeWindow;
if(lc->pNativeWindow != NULL)
lc->bLayerInitialized = 0;
return ;
}
static int PrintBufferStatus(LayerCtrlContext* lc)
{
int i;
logd("========== print start =============");
for(i = 0; i < lc->nGpuBufferCount; i++)
{
logd("buffer[%d], status: %d, nBufFd: %d, phyAddr: %x, pWindowBuf: %p",
i, lc->mGpuBufferInfo[i].mStatus, lc->mGpuBufferInfo[i].nBufFd,
lc->mGpuBufferInfo[i].pPicture.phyYBufAddr, lc->mGpuBufferInfo[i].pWindowBuf);
}
logd("====== print end ===========");
return 0;
}
//* Description: get the buffer which owned by nativewindow
//* use in setWindow
static VideoPicture* __LayerGetBufferOwnedByGpu(LayerCtrl* l)
{
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)l;
for(int i = 0; i< lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].mStatus == OWN_BY_NATIVE_WINDOW)
{
// in reset native window, all of the buffers should be cancel to nativeWindow,
// so we set the status of buffers to UNRECOGNIZED, which already in native window;
// the other buffers in decoder will be set UNRECOGNIZED in LayerResetNativeWindow
lc->mGpuBufferInfo[i].mStatus = UNRECOGNIZED;
return &lc->mGpuBufferInfo[i].pPicture;
}
}
return NULL;
}
//* 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;
}
#if defined(CONF_PRODUCT_STB)
setDisplay3DMode(lc);
#endif
#if (CONF_ANDROID_MAJOR_VER >= 8)
if(lc->nWidth * lc->nHeight > 8000000 && lc->nSwitchNum==0)
{
switchBuffer(lc);
lc->bSwitchBuffer = 1;
lc->nSwitchNum = 0;
}
#endif
lc->bLayerInitialized = 1;
}
//* we should make sure that the dequeue buffer is new when init
if(bInitFlag == 1)
{
*ppVideoPicture = dequeueTheInitGpuBuffer(lc);
if(*ppVideoPicture == NULL)
{
loge("*** dequeueTheInitGpuBuffer failed");
return -1;
}
//PrintBufferStatus(lc);
}
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;
}
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].pWindowBuf == pWindowBuf)
{
if(lc->mGpuBufferInfo[i].mStatus == OWN_BY_DECODER)
{
logw("=== status error, i: %d", i);
}
lc->mGpuBufferInfo[i].mStatus = OWN_BY_US;
break;
}
}
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].mStatus == OWN_BY_US)
{
lc->mGpuBufferInfo[i].mStatus = OWN_BY_DECODER;
*ppVideoPicture = &lc->mGpuBufferInfo[i].pPicture;
break;
}
}
}
//PrintBufferStatus(lc);
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;
LayerCtrlContext* lc = (LayerCtrlContext*)l;
if(lc->bLayerInitialized == 0)
{
if(setLayerParam(lc) != 0)
{
loge("can not initialize layer.");
return -1;
}
#if defined(CONF_PRODUCT_STB)
setDisplay3DMode(lc);
#endif
lc->bLayerInitialized = 1;
}
if(lc->bSwitchBuffer)
{
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].pPicture.phyYBufAddr == pInPicture->phyYBufAddr)
{
if(i != lc->nGpuBufferCount-3)
{
logw("=== buffer error, i: %d", i);
}
lc->mGpuBufferInfo[i].mStatus = OWN_BY_NATIVE_WINDOW;
break;
}
}
lc->bSwitchBuffer = 0;
lc->nSwitchNum = 0;
//PrintBufferStatus(lc);
return 0;
}
for(i = 0; i < lc->nGpuBufferCount; i++)
{
if(lc->mGpuBufferInfo[i].pPicture.phyYBufAddr == pInPicture->phyYBufAddr)
{
if(lc->mGpuBufferInfo[i].mStatus != OWN_BY_DECODER)
{
logd("=== status error %d, buf id: %d", lc->mGpuBufferInfo[i].mStatus, i);
//PrintBufferStatus(lc);
return -1;
}
break;
}
}
//loge("*** LayerQueueBuffer pInPicture = %p, bValid = %d",pInPicture,bValid);
pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
if(bValid == 1)
{
#if (defined(CONF_HIGH_DYNAMIC_RANGE_ENABLE))
android_dataspace_t space = getDataspaceFromVideoPicture(pInPicture);
native_window_set_buffers_data_space(lc->pNativeWindow, space);
#endif
lc->pNativeWindow->queueBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
}
else
{
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
}
lc->mGpuBufferInfo[i].mStatus = OWN_BY_NATIVE_WINDOW;
logv("******LayerQueueBuffer finish!");
return 0;
}
//* Description: release the buffer by ion
static int __LayerReleaseBuffer(LayerCtrl* l,VideoPicture* pPicture)
{
logv("***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;
int i;
for(i = 0; i < GPU_BUFFER_NUM; i++)
{
if((size_addr)lc->mGpuBufferInfo[i].pBufPhyAddr == pPicture->phyYBufAddr)
{
if(pPicture->nBufFd >= 0)
close(pPicture->nBufFd);
if(handle_ion != ION_NULL_VALUE)
ion_free(lc->ionFd,handle_ion);
if(lc->mGpuBufferInfo[i].pMetaDataVirAddr != NULL)
{
munmap(lc->mGpuBufferInfo[i].pMetaDataVirAddr,lc->mGpuBufferInfo[i].nMetaDataVirAddrSize);
}
if(lc->mGpuBufferInfo[i].nMetaDataMapFd >= 0)
{
close(lc->mGpuBufferInfo[i].nMetaDataMapFd);
}
if(lc->mGpuBufferInfo[i].metadata_handle_ion != ION_NULL_VALUE)
{
ion_free(lc->ionFd,lc->mGpuBufferInfo[i].metadata_handle_ion);
}
lc->mGpuBufferInfo[i].nBufFd = -1;
lc->mGpuBufferInfo[i].nMetaDataMapFd = -1;
lc->mGpuBufferInfo[i].handle_ion = ION_NULL_VALUE;
lc->mGpuBufferInfo[i].metadata_handle_ion = ION_NULL_VALUE;
lc->mGpuBufferInfo[i].pWindowBuf = NULL;
lc->mGpuBufferInfo[i].mStatus = UNRECOGNIZED;
lc->nUnFreeBufferCount--;
logd("release this buffer(fd: %d), nUnFreeBufferCount: %d", pPicture->nBufFd, lc->nUnFreeBufferCount);
break;
}
}
if(i == GPU_BUFFER_NUM)
{
logw("warning: the buffer (fd:%d) cannot found in list", pPicture->nBufFd);
}
return 0;
}
static int __LayerReset(LayerCtrl* l)
{
LayerCtrlContext* lc;
int i;
lc = (LayerCtrlContext*)l;
ANativeWindowBuffer* pWindowBuf;
for(i = 0; i < lc->nGpuBufferCount; i++)
{
pWindowBuf = lc->mGpuBufferInfo[i].pWindowBuf;
if(lc->mGpuBufferInfo[i].mStatus != UNRECOGNIZED)
{
//* unlock the buffer.
GraphicBufferMapper& graphicMapper = GraphicBufferMapper::get();
graphicMapper.unlock(pWindowBuf->handle);
}
//* we should queue buffer which had dequeued to gpu
if(lc->mGpuBufferInfo[i].mStatus == OWN_BY_DECODER
|| lc->mGpuBufferInfo[i].mStatus == OWN_BY_US)
{
lc->pNativeWindow->cancelBuffer_DEPRECATED(lc->pNativeWindow, pWindowBuf);
}
if(lc->mGpuBufferInfo[i].pMetaDataVirAddr != NULL)
{
munmap(lc->mGpuBufferInfo[i].pMetaDataVirAddr,lc->mGpuBufferInfo[i].nMetaDataVirAddrSize);
}
if(lc->mGpuBufferInfo[i].nMetaDataMapFd >= 0)
{
close(lc->mGpuBufferInfo[i].nMetaDataMapFd);
}
if(lc->mGpuBufferInfo[i].metadata_handle_ion != ION_NULL_VALUE)
{
ion_free(lc->ionFd,lc->mGpuBufferInfo[i].metadata_handle_ion);
}
if(lc->mGpuBufferInfo[i].nBufFd >= 0)
{
lc->nUnFreeBufferCount--;
logd("close: ion_buf_fd[%d] = %d",i,lc->mGpuBufferInfo[i].nBufFd);
close(lc->mGpuBufferInfo[i].nBufFd);
}
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;
lc->mGpuBufferInfo[i].mStatus = UNRECOGNIZED;
}
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))
case CDX_LAYER_CMD_RESTART_SCHEDULER:
{
CdxVideoSchedulerRestart(lc->mVideoScheduler);
break;
}
#endif
case CDX_LAYER_CMD_SET_HDR_INFO:
{
LayerSetHdrInfo(l, (const FbmBufInfo *)para);
break;
}
case CDX_LAYER_CMD_SET_NATIVE_WINDOW:
{
lc->base.pNativeWindow = (void*)para;
break;
}
case CDX_LAYER_CMD_SET_VIDEOCODEC_FORMAT:
{
lc->eVideoCodecFormat = *((enum EVIDEOCODECFORMAT *)para);
break;
}
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()
{
logv("LayerInit.");
LayerCtrlContext* lc;
lc = (LayerCtrlContext*)malloc(sizeof(LayerCtrlContext));
if(lc == NULL)
{
loge("malloc memory fail.");
return NULL;
}
memset(lc, 0, sizeof(LayerCtrlContext));
int i;
for(i = 0; i < GPU_BUFFER_NUM; i++)
{
lc->mGpuBufferInfo[i].nBufFd = -1;
lc->mGpuBufferInfo[i].nMetaDataMapFd = -1;
lc->mGpuBufferInfo[i].handle_ion = ION_NULL_VALUE;
lc->mGpuBufferInfo[i].metadata_handle_ion = ION_NULL_VALUE;
lc->mGpuBufferInfo[i].pWindowBuf = NULL;
}
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;
#if (defined(CONF_PTS_TOSF))
lc->mVideoScheduler = CdxVideoSchedulerCreate();
if (lc->mVideoScheduler == NULL)
logw("CdxVideoSchedulerCreate failed");
#endif
return (LayerCtrl*)&lc->base;
}