/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author$
 * $Date$
 * $RCSfile: fbm_if.c,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

/** @file fbm_if.c
 *  This file contains implementation of exported APIs of FBM.
 */


//---------------------------------------------------------------------------
// Include files
//---------------------------------------------------------------------------

#include "x_lint.h"
#include "fbm_drvif.h"
#include "fbm_fb.h"
#include "fbm_pool.h"
#include "fbm_pool_config.h"
#include "fbm_cs.h"
#include "fbm_debug.h"
#include "vdp_prescale_drvif.h"
LINT_EXT_HEADER_BEGIN
#include "x_hal_5381.h"
#include "x_os.h"
#include "x_assert.h"
#include "x_syslog.h"
#include "x_timer.h"
#include "x_bim.h"
#include "drvcust_if.h"
#include "vdec_drvif.h"
#include "b2r_drvif.h"
#include "gfx_drvif.h"
#include "gdma_if.h"
#include "drv_mjc_if.h"
LINT_EXT_HEADER_END


//---------------------------------------------------------------------------
// Configurations
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Constant definitions
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Type definitions
//---------------------------------------------------------------------------

typedef struct
{
    UPTR u4Addr;
    UINT32 u4Size;
    BOOL fgInUse;
} FBM_SEAMLESS_T;

typedef struct
{
    UPTR u4Addr;
    UINT32 u4Size;
    BOOL fgInUse;
} FBM_IMGRZ_TMP_BUF_T;

typedef struct
{
    UPTR u4YAddr;
    UINT32 u4YSize;
    UPTR u4CAddr;
    UINT32 u4CSize;
    BOOL   fgInUse;
    FBM_RESOLUTION_CHANGE_MODE_T eChangeMode;
} FBM_RESERVE_BUF_T;


#if defined(CC_FBM_TWO_4K2K)||defined(CC_FBM_FOUR_INST_SUPPORT)
#define MAX_SEAMLESS_BUFF_COUNT 4
#elif defined(CC_FBM_TWO_FBP)||defined(CC_FBM_SUPPORT_4K2K)
#define MAX_SEAMLESS_BUFF_COUNT 2
#else
#define MAX_SEAMLESS_BUFF_COUNT 1
#endif

//---------------------------------------------------------------------------
// Macro definitions
//---------------------------------------------------------------------------

#define VERIFY_FBG(id)                                  \
    ((id >= FBG_MAX_NS) ||                              \
    (_arFbg[id].ucFbgType == FBM_FBG_TYPE_UNKNOWN) ||   \
    (_arFbg[id].ucFbgId != id))

#define VERIFY_FB(gid, id)                              \
    (!(((_arFbg[gid].ucFbNsBase <= id) && (id < _arFbg[gid].ucFbNs))   ||  \
      ((_arFbg[gid].ucFbNsMajorBase <= id) && (id < _arFbg[gid].ucFbNsMajor)) ||\
      ((_arFbg[gid].ucFbNsMinorBase <= id) && (id < _arFbg[gid].ucFbNsMinor)))   || \
    (id >= FBM_MAX_FB_NS_PER_GROUP))

#define VERIFY_FB_NS(gid)                               \
    (_arFbg[gid].ucFbNs - _arFbg[gid].ucFbNsBase > FBM_MAX_FB_NS_PER_GROUP)

#define IS_REFERENCE_FB(gid, id)                        \
    ((id == _arFbg[gid].ucFbFRef) || (id == _arFbg[gid].ucFbBRef))

#define NOT_REFERENCE_FB(gid, id)                        \
    ((id != _arFbg[gid].ucFbFRef) && (id != _arFbg[gid].ucFbBRef))

#ifdef CC_VDP_FULL_ISR

#define FBM_MUTEX_LOCK(id)                              \
    (*_arFbg[id].prState = x_crit_start())

#define FBM_MUTEX_UNLOCK(id)                            \
    (x_crit_end(*_arFbg[id].prState))

#else

#define FBM_MUTEX_LOCK(id)                              \
    (VERIFY(x_sema_lock(_arFbg[id].hMutex, X_SEMA_OPTION_WAIT) == OSR_OK))

#define FBM_MUTEX_UNLOCK(id)                            \
    (VERIFY(x_sema_unlock(_arFbg[id].hMutex) == OSR_OK))

#endif


#define FBM_MEMSET(addr, value, len)                    \
    (VERIFY(x_memset((addr), value, len) == (addr)))

#define FBM_BYTE(value)                                 \
    ((UCHAR)(value & 0xFF))

#define FBM_GFX_MEMSET(u4Addr, u4Width, u4Height, u4Color)    \
    if (FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GFX_MEMSET], _arFbmCbFunc.au4CbFuncCRC[FBM_CB_FUNC_GFX_MEMSET])) \
    {\
        ((FBM_GFX_MEMSET_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GFX_MEMSET])((UINT8*)u4Addr, u4Width, u4Height, u4Color);\
    }

#define FBM_GFX_MEMSET_ASYNC(u4Addr, u4Width, u4Height, u4Color)    \
    ((FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET], _arFbmCbFunc.au4CbFuncCRC[FBM_CB_FUNC_GFX_TASK_MEMSET])) ?\
    (((FBM_GFX_TASK_MEMSET_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET])((UINT8*)u4Addr, u4Width, u4Height, u4Color)) : 0)

#define FBM_GDMA_MEMSET(s,c,n)    \
  if((_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GDMA_MEMSET])) \
  {\
        ((FBM_GDMA_MEMSET_FUNC)(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GDMA_MEMSET]))(s,c,n);\
  }

#define FBM_GDMA_MEMSET_ASYNC(s,c,n)    \
    ((FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET], _arFbmCbFunc.au4CbFuncCRC[FBM_CB_FUNC_GDMA_TASK_MEMSET])) ?\
    (((FBM_GDMA_TASK_MEMSET_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET])(s,c,n)) : 0)

#define FBM_Check_AddrIsOverLap(u4Addr,u4Size,u4StartAddr,u4EndAddr)    \
    if((u4Addr >= u4StartAddr) && \
       (u4Addr <= u4EndAddr) && \
       (u4Addr+u4Size >= u4StartAddr) && \
       (u4Addr+u4Size <= u4EndAddr)) \
    {\
     \
    }\
    else \
    {\
        LOG(0,"S--E[0x%lx-0x%lx] Addr(0x%lx) u4Size(0x%x) layout overlap!! \n",u4StartAddr,u4EndAddr,u4Addr,u4Size);\
    }

//If ns >= 10, return 10; else if ns >= 5, return 5; else return ns;
#define FBM_FLOOR_FIX(ns, a, b) (((ns)>=(a)) ? (a) : (((ns)>=(b)) ? (b) : (ns)))
#define FBM_MIN(a, b) ((a) < (b) ? (a) : (b))


extern UINT32 u4FbmCtrlLog;
//---------------------------------------------------------------------------
// Imported variables
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Imported functions
//---------------------------------------------------------------------------
#ifndef CC_64BIT_SUPPORT
extern UINT32 _FBM_QueryBufNum(UINT32 u4VDecFmt, UINT32 u4Width,
                               UINT32 u4Height, UCHAR ucColorMode, UINT32 *pu4BufNum, UINT32 *pu4Stride,
                               UINT32 *pu4SliceHeight, UINT32 *pu4UVAddrOffset, UINT32 u4ExtOption);
#endif

#ifdef FBM_CS_LOG
extern void _FbmCsLog(UINT32 u4Log, INT32 i4Count, UINT32 u4handle);
#endif

//---------------------------------------------------------------------------
// Static function forward declarations
//---------------------------------------------------------------------------

static void _FbgStatus(UCHAR ucFbgId);
static void _FBM_CheckRemainMemSize(BOOL bUfo,UINT32 u4Addr,UINT32 u4Size,UINT32 u4EndPoolAddr);

static VOID _FBM_B2RDumpPendingQ(UCHAR ucFbgId);

void _EnableNewSeamless(UCHAR ucFbgId);
#ifdef CC_B2R_RES_SUPPORT
void _FBM_B2rResInit(void);
void _FBM_B2rResGetSrcInfo(UCHAR ucFbgId,
                           B2R_IPT_INFO_T* pt_src,
                           FBM_CREATE_FBG_PAR_T* ptPar);
UINT8 FBM_B2rResIdRelease(UCHAR ucFbgId);
#endif

static VOID FBM_ActiveMajorFrameBuffer(UCHAR ucFbgId);
static VOID FBM_ActiveMinorFrameBuffer(UCHAR ucFbgId);
static VOID FBM_ActiveMajorMv(UCHAR ucFbgId);
static VOID FBM_ActiveMinorMv(UCHAR ucFbgId);


static UINT32 FBM_CfgMvbuffer(UCHAR ucFbgId,UINT32 u4YSize,UCHAR ucMvBufNs);
static UINT32 FBM_ConfigFrameBuffer(UCHAR ucFbgId, UINT32 u4HSize,UINT32 u4VSize, FBM_CREATE_FBG_PAR_T *prPar);
static UCHAR FBM_InitFbgInfo(FBM_CREATE_FBG_PAR_T *prPar);
static VOID FBM_ChangeResolution(UCHAR ucFbgId,UINT32 u4HSize,UINT32 u4VSize,BOOL fgFirstCreate);



#define FBM_RETURN_OK    0
#define FBM_RETURN_ERROR 1

#define FBM_8K_SIZE (0x2000)
#define FBM_100M_SIZE (0x6400000)
//---------------------------------------------------------------------------
// Static variables
//---------------------------------------------------------------------------

// Initiated Protection
static UCHAR _FbmInitiated = 0;

#ifndef FBM_VIRTUAL_MPEG
// frame buffer group
static FBM_FBG_T *_arFbg = NULL;// reduce ko size using malloc fbm instance
#else
FBM_FBG_T *_arFbg = NULL;
#endif


#define DUMP_DIR_LENTH 150
static CHAR dumpDir[DUMP_DIR_LENTH];
static FBM_IMGRZ_TMP_BUF_T    _arImgRzTmpBufInfo[MAX_SEAMLESS_BUFF_COUNT];

#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
static FBM_SEAMLESS_T _arSeamlessInfo[FBM_SEAMLESS_GROUP_COUNT];
#endif

static UINT8 _u1FbgColorMode = FBM_CM_420;

static BOOL _fgSetDecoderFb = FALSE;
static UINT8 _u1DecoderType = FBM_VDEC_UNKNOWN;
static UINT8 _u1NumOfFb = 4;

static FBM_POOL_T *_prPool = NULL;

static FBM_CB_FUNC_T _arFbmCbFunc;

#ifdef CC_B2R_RES_SUPPORT
static B2R_HW_RES_T _arB2rHwRes[B2R_HW_MAX_ID];
#endif

#ifdef CC_VDP_FULL_ISR
static CRIT_STATE_T _rState;
#endif

#ifdef FBM_CS_LOG
UINT32 _u4EQHandle = 0;
#endif

static HANDLE_T _hFbgMutex = (HANDLE_T)(NULL);

EXTERN void _VdpCheckFbgReady(UCHAR ucFbgId, UCHAR ucEsId);

//---------------------------------------------------------------------------
// Static functions
//---------------------------------------------------------------------------

//-------------------------------------------------------------------------
/** _FbgStatus
 *  Print FBM status
 *  @return NONE.
 */
//-------------------------------------------------------------------------
static void _FbgStatus(UCHAR ucFbgId)
{
    UCHAR ucIdx;
    UCHAR ucDispTag;

    if (ucFbgId >= FBG_MAX_NS)
    {
        return;
    }

    if ((_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_UNKNOWN) ||
        (_arFbg[ucFbgId].ucFbgId != ucFbgId))
    {
        LOG(1, "FBG(%d) is NULL!\n", ucFbgId);
        return;
    }

    LOG(0, "FBG(%d) Type(%d) CM(%d) Ns(%d) D(%d) F(%d) B(%d) Pool(0x%lx, 0x%x) SM(%d) \n",
        _arFbg[ucFbgId].ucFbgId,
        _arFbg[ucFbgId].ucFbgType,
        _arFbg[ucFbgId].ucFbgCm,
        _arFbg[ucFbgId].ucFbNs,
        _arFbg[ucFbgId].ucFbDecode,
        _arFbg[ucFbgId].ucFbFRef,
        _arFbg[ucFbgId].ucFbBRef,
        _arFbg[ucFbgId].u4FbMemoryPool,
        _arFbg[ucFbgId].u4FbMemoryPoolSize,
        _arFbg[ucFbgId].eSeamlessMode);
    LOG(0,"Resolution(0x%x,0x%x),Pitch(0x%x),Raster(%d),422Mode(%d)\n",
        _arFbg[ucFbgId].rSeqHdr.u4SourceWidth,
        _arFbg[ucFbgId].rSeqHdr.u4SourceHeight,
        _arFbg[ucFbgId].rSeqHdr.u4PicPitch,
        _arFbg[ucFbgId].rSeqHdr.fgRasterOrder,
        _arFbg[ucFbgId].rSeqHdr.fg422Mode);
    for(ucIdx = _arFbg[ucFbgId].ucFbNsMajorBase; ucIdx < _arFbg[ucFbgId].ucFbNsMajor; ucIdx++)
    {
        if(ucIdx < FBM_MAX_FB_NS_PER_GROUP)
        {
            if ( _arFbg[ucFbgId].u4DispTag[ucIdx] == INVALID_DISPTAG)
            {
                ucDispTag = 'R';
            }
            else if ( _arFbg[ucFbgId].u4DispTag[ucIdx] == OMX_PENDING_DISPTAG)
            {
                ucDispTag = 'P';
            }
            else
            {
                ucDispTag = 'D';
            }
            if (_arFbg[ucFbgId].fgUFO)
            {
                LOG(0, "\tFB(%d) S(%d,%d,%c) Y(0x%lx) Y_Ext(0x%lx) | C(0x%lx) C_Ext(0x%lx) PTS-Id(0x%llx-%d)\n",
                    ucIdx,
                    _arFbg[ucFbgId].aucFbStatus[ucIdx],
                    _arFbg[ucFbgId].afgRefList[ucIdx],
                    ucDispTag,
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY_Ext[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC_Ext[ucIdx])),
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].u4PTS : 0,
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].ucPicId: 0);
            }
            else
            {
                LOG(0, "\tFB(%2d) S(%d,%d,%c) Y(0x%lx) C(0x%lx) PTS-Id(0x%llx-%d)\n",
                    ucIdx,
                    _arFbg[ucFbgId].aucFbStatus[ucIdx],
                    _arFbg[ucFbgId].afgRefList[ucIdx],
                    ucDispTag,
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC[ucIdx])),
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].u4PTS : 0,
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].ucPicId: 0);
            }
        }
    }
    for(ucIdx = _arFbg[ucFbgId].ucFbNsMinorBase; ucIdx < _arFbg[ucFbgId].ucFbNsMinor; ucIdx++)
    {
        if(ucIdx < FBM_MAX_FB_NS_PER_GROUP)
        {
            if ( _arFbg[ucFbgId].u4DispTag[ucIdx] == INVALID_DISPTAG)
            {
                ucDispTag = 'R';
            }
            else if ( _arFbg[ucFbgId].u4DispTag[ucIdx] == OMX_PENDING_DISPTAG)
            {
                ucDispTag = 'P';
            }
            else
            {
                ucDispTag = 'D';
            }
            if (_arFbg[ucFbgId].fgUFO)
            {
                LOG(0, "\tFB(%d) S(%d,%d,%c) Y(0x%lx) Y_Ext(0x%lx) | C(0x%lx) C_Ext(0x%lx) PTS-Id(0x%llx-%d)\n",
                    ucIdx,
                    _arFbg[ucFbgId].aucFbStatus[ucIdx],
                    _arFbg[ucFbgId].afgRefList[ucIdx],
                    ucDispTag,
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY_Ext[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC_Ext[ucIdx])),
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].u4PTS : 0,
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].ucPicId: 0);
            }
            else
            {
                LOG(0, "\tFB(%2d) S(%d,%d,%c) Y(0x%lx) C(0x%lx) PTS-Id(0x%llx-%d)\n",
                    ucIdx,
                    _arFbg[ucFbgId].aucFbStatus[ucIdx],
                    _arFbg[ucFbgId].afgRefList[ucIdx],
                    ucDispTag,
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY[ucIdx])),
                    (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC[ucIdx])),
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].u4PTS : 0,
                    _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].ucPicId: 0);
            }
        }
    }
    if ((!_arFbg[ucFbgId].ucFbNsMinor) && (!_arFbg[ucFbgId].ucFbNsMajor))
    {
        for(ucIdx = _arFbg[ucFbgId].ucFbNsBase; ucIdx < _arFbg[ucFbgId].ucFbNs; ucIdx++)
        {
            if(ucIdx < FBM_MAX_FB_NS_PER_GROUP)
            {
                if ( _arFbg[ucFbgId].u4DispTag[ucIdx] == INVALID_DISPTAG)
                {
                    ucDispTag = 'R';
                }
                else if ( _arFbg[ucFbgId].u4DispTag[ucIdx] == OMX_PENDING_DISPTAG)
                {
                    ucDispTag = 'P';
                }
                else
                {
                    ucDispTag = 'D';
                }
                if (_arFbg[ucFbgId].fgUFO)
                {
                    LOG(0, "\tFB(%d) S(%d,%d,%c) Y(0x%lx) Y_Ext(0x%lx) | C(0x%lx) C_Ext(0x%lx) PTS-Id(0x%llx-%d)\n",
                        ucIdx,
                        _arFbg[ucFbgId].aucFbStatus[ucIdx],
                        _arFbg[ucFbgId].afgRefList[ucIdx],
                        ucDispTag,
                        (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY[ucIdx])),
                        (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY_Ext[ucIdx])),
                        (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC[ucIdx])),
                        (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC_Ext[ucIdx])),
                        _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].u4PTS : 0,
                        _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].ucPicId: 0);
                }
                else
                {
                    LOG(0, "\tFB(%2d) S(%d,%d,%c) Y(0x%lx) C(0x%lx) PTS-Id(0x%llx-%d)\n",
                        ucIdx,
                        _arFbg[ucFbgId].aucFbStatus[ucIdx],
                        _arFbg[ucFbgId].afgRefList[ucIdx],
                        ucDispTag,
                        (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrY[ucIdx])),
                        (_arFbg[ucFbgId].fgNonBuf?(0x0):(_arFbg[ucFbgId].au4AddrC[ucIdx])),
                        _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].u4PTS : 0,
                        _arFbg[ucFbgId].prPicHdr ? _arFbg[ucFbgId].prPicHdr[ucIdx].ucPicId: 0);
                }
            }
        }

    }

    if(_arFbg[ucFbgId].fgEnableNewSeamless)
    {
        for (ucIdx = 0; ucIdx < _arFbg[ucFbgId].ucSeamlessFbNs; ucIdx++)
        {
            if(ucIdx < FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0, "\tFB(%d) S(%d) O(%d) Y(0x%lx) C(0x%lx)\n",
                    ucIdx,
                    _arFbg[ucFbgId].aucResizeFbStatus[ucIdx],
                    _arFbg[ucFbgId].aucResizeSrcFbId[ucIdx],
                    _arFbg[ucFbgId].au4ResizeAddrY[ucIdx],
                    _arFbg[ucFbgId].au4ResizeAddrC[ucIdx]);
            }
        }

        for (ucIdx = 0; ucIdx < _arFbg[ucFbgId].ucSeamless2FbNs; ucIdx++)
        {
            if(ucIdx < FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0, "\tFB(%d) S(%d) O(%d) Y(0x%lx) C(0x%lx)\n",
                    ucIdx,
                    _arFbg[ucFbgId].aucResize2FbStatus[ucIdx],
                    _arFbg[ucFbgId].aucResize2SrcFbId[ucIdx],
                    _arFbg[ucFbgId].au4Resize2AddrY[ucIdx],
                    _arFbg[ucFbgId].au4Resize2AddrC[ucIdx]);
            }
        }


        for (ucIdx=0; ucIdx < MAX_SEAMLESS_BUFF_COUNT; ucIdx++)
        {
            if (_arImgRzTmpBufInfo[ucIdx].u4Size != 0)
            {
                LOG(1,"\tImgRz[%d] Addr 0x%lx Size 0x%x\n",
                    ucIdx,
                    _arImgRzTmpBufInfo[ucIdx].u4Addr,
                    _arImgRzTmpBufInfo[ucIdx].u4Size);
            }

        }

    }

    if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1))
    {
        for (ucIdx = 0; ucIdx < _arFbg[ucFbgId].ucMvBufNs; ucIdx++)
        {
            if(ucIdx < FBM_MAX_FB_NS_PER_GROUP - 1)
            {
                LOG(1, "\tFB(%d) AddrMv(0x%lx)\n",ucIdx,_arFbg[ucFbgId].au4AddrMv[ucIdx]);
            }
        }
    }

}


void _EnableNewSeamless(UCHAR ucFbgId)
{
    if (!_arFbg[ucFbgId].fgEnableNewSeamless)
    {
        UPTR u4Addr;
        UCHAR  ucFbIdx;
        UINT32  u4FbCntLimit = 2;
        UINT32 u4SeamlessYSize = FBM_FBG_TYPE_1080HD_Y_SIZE;
        UINT32 u4SeamlessCSize = FBM_FBG_TYPE_1080HD_C_SIZE;
        FBM_POOL_T* prFbmPool = NULL;
        UPTR u4ExtraAddr = 0;
        UCHAR ucSeamlessExtaFbNs = 0;

        FBM_CODEC_RESOLUTION_T rResolution;
        x_memset((VOID*)&rResolution,0x0,sizeof(FBM_CODEC_RESOLUTION_T));

        _arFbg[ucFbgId].rResizeEmptyQ.ucCount = 0;
        _arFbg[ucFbgId].rResizeEmptyQ.ucReadIdx = 0;

        _arFbg[ucFbgId].rResize2EmptyQ.ucCount = 0;
        _arFbg[ucFbgId].rResize2EmptyQ.ucReadIdx = 0;

        _arFbg[ucFbgId].ucSeamlessFbNs = 0;
        _arFbg[ucFbgId].ucSeamless2FbNs = 0;

        _arFbg[ucFbgId].u4FbResizeMemoryPool = 0;
        _arFbg[ucFbgId].u4FbResizeMemoryPoolSize = 0;

        if(FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_RESIZER)
           && FBM_ChkSeamlessMode(ucFbgId,POST_PROCESS_DISPLAY_ROTATE))
        {
            u4FbCntLimit ++;
        }

        // Allocate seamless buffer for netflix, etc.
        LOG(0, "Partitioning seamless buffer.\n");
        FBM_GetCodecResolution(ucFbgId,&rResolution);
        if (((rResolution.u4Width <= FBM_FBG_4K2K_H) && (rResolution.u4Width > FBM_FBG_1080HD_H)) &&
            ((rResolution.u4Height <= FBM_FBG_4K2K_V) && (rResolution.u4Height > FBM_FBG_1080HD_V)))
        {
            u4SeamlessYSize = FBM_FBG_TYPE_4K2K_Y_SIZE;
            u4SeamlessCSize = FBM_FBG_TYPE_4K2K_C_SIZE;

            prFbmPool =FBM_Alloc((UCHAR)FBM_TYPE_SML);
            if (prFbmPool == NULL)
            {
                return;
            }
            _arFbg[ucFbgId].pFbmSmlPool = prFbmPool;

            if (prFbmPool->u4Size > 0)
            {
                _arFbg[ucFbgId].ucSeamlessFbNs = (UCHAR)(prFbmPool->u4Size / (u4SeamlessYSize + u4SeamlessCSize));
                LOG(1, "Seamless Config(4K): FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                    _arFbg[ucFbgId].ucSeamlessFbNs, u4SeamlessYSize, u4SeamlessCSize, prFbmPool->u4Size);
            }
            else
            {
                LOG(0,"Can not Allocate SML buffer\n");
                return;
            }

            if(_arFbg[ucFbgId].ucSeamlessFbNs < u4FbCntLimit)
            {
                LOG(0,"Allocate SML buffer cnt %d < %d.\n", _arFbg[ucFbgId].ucSeamlessFbNs,u4FbCntLimit);
            }

            u4Addr = prFbmPool->u4Addr;
            for (ucFbIdx = 0; ((ucFbIdx < _arFbg[ucFbgId].ucSeamlessFbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
            {
                u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                _arFbg[ucFbgId].au4ResizeAddrY[ucFbIdx] = u4Addr;
                FBM_GDMA_MEMSET((VOID*)u4Addr,0x0,u4SeamlessYSize);
                u4Addr += u4SeamlessYSize;

                u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                _arFbg[ucFbgId].au4ResizeAddrC[ucFbIdx] = u4Addr;
                FBM_GDMA_MEMSET((VOID*)u4Addr,0x80808080,u4SeamlessCSize);
                u4Addr += u4SeamlessCSize;

                LOG(1,"4K Seamless Y/C[%d] (0x%lx/0x%lx)\n",
                    ucFbIdx,
                    _arFbg[ucFbgId].au4ResizeAddrY[ucFbIdx],
                    _arFbg[ucFbgId].au4ResizeAddrC[ucFbIdx]);
            }
            /*------------------------------------------------*/
            prFbmPool =FBM_Alloc((UCHAR)FBM_TYPE_SML);
            if (prFbmPool == NULL)
            {
                return;
            }

            _arFbg[ucFbgId].pFbmSmlPool2 = prFbmPool;

            if (prFbmPool->u4Size > 0)
            {
                _arFbg[ucFbgId].ucSeamless2FbNs = (UCHAR)(prFbmPool->u4Size / (u4SeamlessYSize + u4SeamlessCSize));
                LOG(1, "Seamless Config(4K): FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                    _arFbg[ucFbgId].ucSeamlessFbNs, u4SeamlessYSize, u4SeamlessCSize, prFbmPool->u4Size);

            }
            else
            {
                LOG(0,"Can not Allocate SML buffer\n");
                return;
            }

            if(_arFbg[ucFbgId].ucSeamless2FbNs < u4FbCntLimit)
            {
                LOG(0,"Allocate SML buffer2 cnt %d < %d..\n", _arFbg[ucFbgId].ucSeamlessFbNs,u4FbCntLimit);
            }

            u4Addr = prFbmPool->u4Addr;

            for (ucFbIdx = 0; ((ucFbIdx < _arFbg[ucFbgId].ucSeamless2FbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
            {
                u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                _arFbg[ucFbgId].au4Resize2AddrY[ucFbIdx] = u4Addr;
                FBM_GDMA_MEMSET((VOID*)u4Addr,0x0,u4SeamlessYSize);
                u4Addr += u4SeamlessYSize;

                u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                _arFbg[ucFbgId].au4Resize2AddrC[ucFbIdx] = u4Addr;
                FBM_GDMA_MEMSET((VOID*)u4Addr,0x80808080,u4SeamlessCSize);
                u4Addr += u4SeamlessCSize;

                LOG(1,"4K Seamless Y/C[%d] (0x%lx/0x%lx)\n",
                    ucFbIdx,
                    _arFbg[ucFbgId].au4Resize2AddrY[ucFbIdx],
                    _arFbg[ucFbgId].au4Resize2AddrC[ucFbIdx]);

            }
        }
        else
        {
            u4SeamlessYSize = FBM_FBG_TYPE_1080HD_Y_SIZE;
            u4SeamlessCSize = FBM_FBG_TYPE_1080HD_C_SIZE;
#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
            {
                UINT32 u4Size= 0;
                FBM_GetSeamlessBuffer(&u4Addr,&u4Size);
                if(u4Addr != 0 && u4Size != 0)
                {
                    _arFbg[ucFbgId].ucSeamlessFbNs = (UCHAR)(u4Size / (u4SeamlessYSize + u4SeamlessCSize));
                    if (_arFbg[ucFbgId].ucSeamlessFbNs >= 4)
                    {
                        _arFbg[ucFbgId].ucSeamlessFbNs = 4; // think about FHD case In 4K platform.
                    }
                    LOG(1, "Seamless Config(2K): FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                        _arFbg[ucFbgId].ucSeamlessFbNs, u4SeamlessYSize, u4SeamlessCSize, u4Size);
                }
                else
                {
                    LOG(0,"Can not Get SML buffer\n");
                    return;
                }
            }
#else
            prFbmPool =FBM_Alloc((UCHAR)FBM_TYPE_SML);
            if (prFbmPool == NULL)
            {
                return;
            }
            _arFbg[ucFbgId].pFbmSmlPool = prFbmPool;
            _arFbg[ucFbgId].u4FbResizeMemoryPool = prFbmPool->u4Addr;
            if (prFbmPool->u4Size > 0)
            {
                _arFbg[ucFbgId].ucSeamlessFbNs = (UCHAR)(prFbmPool->u4Size / (u4SeamlessYSize + u4SeamlessCSize));
                if (_arFbg[ucFbgId].ucSeamlessFbNs >= 4)
                {
                    _arFbg[ucFbgId].ucSeamlessFbNs = 4; // think about FHD case In 4K platform.
                }

                LOG(1, "Seamless Config(2K): FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                    _arFbg[ucFbgId].ucSeamlessFbNs, u4SeamlessYSize, u4SeamlessCSize, prFbmPool->u4Size);

            }
            else
            {
                LOG(0,"Can not Allocate SML buffer\n");
                return;
            }

            if(_arFbg[ucFbgId].ucSeamlessFbNs < u4FbCntLimit)
            {
                LOG(0,"Allocate SML buffer cnt %d < %d...\n", _arFbg[ucFbgId].ucSeamlessFbNs,u4FbCntLimit);
            }

            u4Addr = prFbmPool->u4Addr;
#endif

            for (ucFbIdx = 0; ((ucFbIdx < _arFbg[ucFbgId].ucSeamlessFbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
            {

                u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                _arFbg[ucFbgId].au4ResizeAddrY[ucFbIdx] = u4Addr;
                //FBM_GFX_MEMSET((UINT8*)u4Addr, FBM_FBG_1080HD_H, FBM_FBG_1080HD_V, 0x0);
                FBM_GDMA_MEMSET((VOID*)u4Addr,0x0,u4SeamlessYSize);
                u4Addr += u4SeamlessYSize;

                u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                _arFbg[ucFbgId].au4ResizeAddrC[ucFbIdx] = u4Addr;
                //FBM_GFX_MEMSET((UINT8*)u4Addr, FBM_FBG_1080HD_H, (FBM_FBG_1080HD_V >> 1), 0x80);
                FBM_GDMA_MEMSET((VOID*)u4Addr,0x80808080,u4SeamlessCSize);
                u4Addr += u4SeamlessCSize;

                LOG(1,"2K Seamless Y/C[%d] (0x%lx/0x%lx)\n",
                    ucFbIdx,
                    _arFbg[ucFbgId].au4ResizeAddrY[ucFbIdx],
                    _arFbg[ucFbgId].au4ResizeAddrC[ucFbIdx]);
            }
            if (_arFbg[ucFbgId].fgIsGameMode)
            {
                u4SeamlessYSize = FBM_FBG_TYPE_1080HD_Y_SIZE;
                u4SeamlessCSize = FBM_FBG_TYPE_1080HD_C_SIZE;
                prFbmPool =FBM_Alloc((UCHAR)FBM_TYPE_SML);
                if (prFbmPool == NULL)
                {
                    return;
                }
                _arFbg[ucFbgId].pFbmSmlPool2 = prFbmPool;
                _arFbg[ucFbgId].u4FbResizeExtraMemoryPool = prFbmPool->u4Addr;
                if (prFbmPool->u4Size > 0)
                {
                    ucSeamlessExtaFbNs = (UCHAR)(prFbmPool->u4Size / (u4SeamlessYSize + u4SeamlessCSize));
                    if (ucSeamlessExtaFbNs >= 4)
                    {
                        ucSeamlessExtaFbNs = 4; // think about FHD case In 4K platform.
                    }
                    LOG(1, "Seamless Config(2K): Ext FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                        ucSeamlessExtaFbNs, u4SeamlessYSize, u4SeamlessCSize, prFbmPool->u4Size);
                }
                else
                {
                    LOG(0,"Can not Allocate SML buffer\n");
                    return;
                }
                u4ExtraAddr = prFbmPool->u4Addr;
                for (ucFbIdx = _arFbg[ucFbgId].ucSeamlessFbNs; ((ucFbIdx < (_arFbg[ucFbgId].ucSeamlessFbNs + ucSeamlessExtaFbNs))&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
                {

                    u4ExtraAddr = FBM_ALIGN_MASK(u4ExtraAddr, FBM_FMG_Y_ALIGMENT);
                    _arFbg[ucFbgId].au4ResizeAddrY[ucFbIdx] = u4ExtraAddr;
                    FBM_GDMA_MEMSET((VOID*)u4ExtraAddr,0x0,u4SeamlessYSize);
                    u4ExtraAddr += u4SeamlessYSize;

                    u4ExtraAddr = FBM_ALIGN_MASK(u4ExtraAddr, FBM_FMG_Y_ALIGMENT);
                    _arFbg[ucFbgId].au4ResizeAddrC[ucFbIdx] = u4ExtraAddr;
                    FBM_GDMA_MEMSET((VOID*)u4ExtraAddr,0x80808080,u4SeamlessCSize);
                    u4ExtraAddr += u4SeamlessCSize;

                    LOG(1,"2K Seamless Y/C[%d] (0x%lx/0x%lx)\n",
                        ucFbIdx,
                        _arFbg[ucFbgId].au4ResizeAddrY[ucFbIdx],
                        _arFbg[ucFbgId].au4ResizeAddrC[ucFbIdx]);
                }
                _arFbg[ucFbgId].ucSeamlessFbNs += ucSeamlessExtaFbNs;
            }
            else
            {
                LOG(0,"Not jellyfish mode fgIsGameMode(%d)\n",_arFbg[ucFbgId].fgIsGameMode);
            }
            if((_arFbg[ucFbgId].eSeamlessMode & SEAMLESS_TWO_RESIZER) == SEAMLESS_TWO_RESIZER)
            {
                /*------------------------------------------------*/
#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
                {
                    UINT32 u4Size= 0;
                    FBM_GetSeamlessBuffer(&u4Addr,&u4Size);
                    if(u4Addr != 0 && u4Size != 0)
                    {
                        _arFbg[ucFbgId].ucSeamlessFbNs = (UCHAR)(u4Size / (u4SeamlessYSize + u4SeamlessCSize));
                        if (_arFbg[ucFbgId].ucSeamlessFbNs >= 4)
                        {
                            _arFbg[ucFbgId].ucSeamlessFbNs = 4; // think about FHD case In 4K platform.
                        }
                        LOG(1, "Seamless Config(2K): FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                            _arFbg[ucFbgId].ucSeamlessFbNs, u4SeamlessYSize, u4SeamlessCSize, u4Size);
                    }
                    else
                    {
                        LOG(0,"Can not Get SML2 buffer\n");
                        return;
                    }
                }
#else
                prFbmPool =FBM_Alloc((UCHAR)FBM_TYPE_SML);
                if (prFbmPool == NULL)
                {
                    return;
                }

                _arFbg[ucFbgId].pFbmSmlPool2 = prFbmPool;

                if (prFbmPool->u4Size > 0)
                {
                    _arFbg[ucFbgId].ucSeamless2FbNs = (UCHAR)(prFbmPool->u4Size / (u4SeamlessYSize + u4SeamlessCSize));

                    if (_arFbg[ucFbgId].ucSeamless2FbNs >= 4)
                    {
                        _arFbg[ucFbgId].ucSeamless2FbNs = 4; // think about FHD case In 4K platform.
                    }
                    LOG(1, "Seamless2 Config(2K): FbNs(%d) Y,C(0x%8x, 0x%8x) PoolSize(0x%x).\n",
                        _arFbg[ucFbgId].ucSeamless2FbNs, u4SeamlessYSize, u4SeamlessCSize, prFbmPool->u4Size);

                }
                else
                {
                    LOG(0,"Can not Allocate SML2 buffer\n");
                    return;
                }

                if(_arFbg[ucFbgId].ucSeamless2FbNs < u4FbCntLimit)
                {
                    LOG(0,"Allocate SML buffer2 cnt %d < %d....\n", _arFbg[ucFbgId].ucSeamlessFbNs,u4FbCntLimit);
                }

                u4Addr = prFbmPool->u4Addr;
#endif

                for (ucFbIdx = 0; ((ucFbIdx < _arFbg[ucFbgId].ucSeamless2FbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
                {
                    u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                    _arFbg[ucFbgId].au4Resize2AddrY[ucFbIdx] = u4Addr;
                    FBM_GDMA_MEMSET((VOID*)u4Addr,0x0,u4SeamlessYSize);
                    u4Addr += u4SeamlessYSize;

                    u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_FMG_Y_ALIGMENT);
                    _arFbg[ucFbgId].au4Resize2AddrC[ucFbIdx] = u4Addr;
                    FBM_GDMA_MEMSET((VOID*)u4Addr,0x80808080,u4SeamlessCSize);
                    u4Addr += u4SeamlessCSize;

                    LOG(1,"2K Seamless2 Y/C[%d] (0x%lx/0x%lx)\n",
                        ucFbIdx,
                        _arFbg[ucFbgId].au4Resize2AddrY[ucFbIdx],
                        _arFbg[ucFbgId].au4Resize2AddrC[ucFbIdx]);

                }

            }

        }

        // create semaphore for  Resize Empty Q
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyResizeQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)_arFbg[ucFbgId].ucSeamlessFbNs) == OSR_OK);

        // create semaphore, Resize2 Empty Q
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyResize2QSemaphore, _arFbg[ucFbgId].hMutex, (INT32)_arFbg[ucFbgId].ucSeamless2FbNs) == OSR_OK);

        // put frames into for Resize empty Q
        for (ucFbIdx = 0; ucFbIdx < _arFbg[ucFbgId].ucSeamlessFbNs; ucFbIdx++)
        {
            _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, ucFbIdx);
        }

        // put frames into Resize2 empty Q
        for (ucFbIdx = 0; ucFbIdx < _arFbg[ucFbgId].ucSeamless2FbNs; ucFbIdx++)
        {
            _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, ucFbIdx);
        }

        //_arFbg[u4FbgId].fgEnableNewSeamless = TRUE;
    }
    return;
}


#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
static void _FBM_InitSeamlessBuffer(VOID)
{
    FBM_POOL_T* pmpegpool = NULL;
    UINT32 u4SeamlessYSize,u4SeamlessPoolSize;
    UPTR u4CAddr;
    UINT8 i = 0;
    FBM_MEMSET((void*)_arSeamlessInfo, 0, (sizeof(FBM_SEAMLESS_T) * FBM_SEAMLESS_GROUP_COUNT));

    u4SeamlessYSize = (((FBM_FBG_TYPE_1080HD_Y_SIZE + (FBM_FBG_TYPE_1080HD_Y_SIZE>>8) + FBM_8K_SIZE*2)*5)>>2)*2;
    u4SeamlessYSize = FBM_ALIGN_MASK(u4SeamlessYSize,FBM_FMG_Y_ALIGMENT);
    u4SeamlessPoolSize = ((u4SeamlessYSize*3)>>1) + FBM_8K_SIZE*2;

    for (i = 0; i < FBM_SEAMLESS_GROUP_COUNT; i++)
    {
        if(i == 0)
        {
            pmpegpool = FBM_GetPoolInfo(FBM_POOL_TYPE_MPEG);
        }
        else if(i == 1)
        {
            pmpegpool = FBM_GetPoolInfo(FBM_POOL_TYPE_MPEG2);
        }

        if (pmpegpool != NULL)
        {
            u4CAddr = pmpegpool->u4Addr + pmpegpool->u4Size - FBM_VP9_C_TOTAL_SIZE_IN_CHB;
            _arSeamlessInfo[i].u4Addr = u4CAddr - u4SeamlessPoolSize;
            _arSeamlessInfo[i].u4Size = u4SeamlessPoolSize;
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(1,"Seamless Pool Addr(0x%x) size(%x)\n",_arSeamlessInfo[0].u4Addr,_arSeamlessInfo[0].u4Size);
            }
        }
        else
        {
            LOG(0,"Cannot get mpeg info!\n");
        }
    }
}

VOID  FBM_GetSeamlessBuffer(UPTR* pu4Addr,UINT32* pu4Size)
{
    UINT8 i = 0;
    if (pu4Addr == NULL || pu4Size == NULL)
    {
        LOG(0,"%s %d Error!\n",__FUNCTION__,__LINE__);
        return;
    }
    for (i = 0; i < FBM_SEAMLESS_GROUP_COUNT; i++)
    {
        if(_arSeamlessInfo[i].fgInUse == FALSE)
        {
            *pu4Addr = _arSeamlessInfo[i].u4Addr;
            *pu4Size = _arSeamlessInfo[i].u4Size;
            _arSeamlessInfo[i].fgInUse = TRUE;
            LOG(1,"Use seamless %d buffer\n",i);
            break;
        }
    }
    if (i >= FBM_SEAMLESS_GROUP_COUNT)
    {
        *pu4Addr = 0;
        *pu4Size = 0;
        LOG(0,"No seamless buffer to use\n");
    }
    return;
}

VOID  FBM_ReleaseSeamlessBuffer(UPTR u4Addr)
{
    UINT8 i = 0;
    if (u4Addr == 0)
    {
        LOG(0,"%s %d Error!\n",__FUNCTION__,__LINE__);
        return;
    }
    for (i = 0; i < FBM_SEAMLESS_GROUP_COUNT; i++)
    {
        if (_arSeamlessInfo[i].u4Addr == u4Addr)
        {
            LOG(1,"Release seamless %d buffer\n",i);
            _arSeamlessInfo[i].fgInUse = FALSE;
            break;
        }
    }
    if (i >= FBM_SEAMLESS_GROUP_COUNT)
    {
        LOG(0,"Unknown seamless address %x to release\n",u4Addr);
    }
    return;
}

#endif
//---------------------------------------------------------------------------
// Inter-file functions
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Public functions
//---------------------------------------------------------------------------

//-------------------------------------------------------------------------
/** FBM_Init
 *  FBM initialize
 *  @return NONE.
 */
//-------------------------------------------------------------------------
#ifndef USERDRV_KERNEL_MOD
void FBM_Init(void)
{
    if (_FbmInitiated == 0)
    {
        UINT32 u4Idx;
#if defined(CC_SUPPORT_DOLBY_VISION)||defined (CC_SUPPORT_TECHNICOLOR_HDR)
        UPTR u4RpuBuffer = 0;
#endif

        _FbmInitiated = 1;

        LOG(0,"%s %d\n",__FUNCTION__,__LINE__);

        _arFbg = x_mem_alloc(sizeof(FBM_FBG_T) * FBG_MAX_NS);

        if (_arFbg == NULL)
        {
            LOG(0,"alloc fbg instance fail \n");
            ASSERT(0);
            return;
        }
        FBM_MEMSET((void*)_arFbg, 0, (sizeof(FBM_FBG_T) * FBG_MAX_NS));

        FBM_MEMSET((void*)(&_arFbmCbFunc), 0, sizeof(FBM_CB_FUNC_T));

#if defined(CC_SUPPORT_DOLBY_VISION)||defined (CC_SUPPORT_TECHNICOLOR_HDR)
        u4RpuBuffer = _arFbg[0].u4RpuPhysicalAddr;
        if(u4RpuBuffer == 0)
        {
            u4RpuBuffer = BSP_AllocAlignedDmaMemory(FBM_RPU_BUF_MAX_SIZE*FBM_MAX_FB_NS_PER_GROUP, 16);
            if(!u4RpuBuffer)
            {
                LOG(0,"Alloc RPU buffer fail for Dolby playback\n");
            }
            _arFbg[0].u4RpuPhysicalAddr = u4RpuBuffer;
            LOG(0,"Alloc RPU buffer 0x%lx success\n",_arFbg[0].u4RpuPhysicalAddr);
        }
        else
        {
            LOG(0,"Rpu add 0x%lx\n",u4RpuBuffer);
        }            
#endif

        // register GFX_Memset() into FBM module
#if !defined(CC_B2R_EMULATION) && !defined(MPV_SEMI_HOST)
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_MEMSET, (UPTR)GFX_Memset);
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_TASK_MEMSET, (UPTR)GFX_Task_Memset);
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_TASK_MEMSET_DONE, (UPTR)GFX_Task_Check_Done);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_MEMSET, (UPTR)GDMA_MemSet);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_TASK_MEMSET, (UPTR)GDMA_MemSetAnsync);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE, (UPTR)IsMemOptionDone);
#endif

        // create FBG mutex
        VERIFY(x_sema_create(&_hFbgMutex, X_SEMA_TYPE_MUTEX, X_SEMA_STATE_UNLOCK) == OSR_OK);

#ifdef CC_B2R_RES_SUPPORT
        _FBM_B2rResInit();
#endif

        // init frame buffer group
        for (u4Idx = 0; u4Idx < FBG_MAX_NS; u4Idx++)
        {
            _arFbg[u4Idx].ucFbgType = FBM_FBG_TYPE_UNKNOWN;
            _arFbg[u4Idx].ucFbgId = FBM_FBG_ID_UNKNOWN;
            _arFbg[u4Idx].ucFbgCm = FBM_CM_UNKNOWN;

            _arFbg[u4Idx].ucStcSrc = STC_SRC_NS;
            _arFbg[u4Idx].ucAvSyncMode = VID_SYNC_MODE_NS;
            _arFbg[u4Idx].ucPlayMode = FBM_FBG_DTV_MODE;
            _arFbg[u4Idx].u4AvSyncStatus = FBM_FBG_AVSYNC_DISABLE;
#ifdef CC_B2R_RES_SUPPORT
            _arFbg[u4Idx].pt_res = _arB2rHwRes;
#endif

            // create semaphore
            VERIFY(x_sema_create(&_arFbg[u4Idx].hMutex, X_SEMA_TYPE_MUTEX, X_SEMA_STATE_UNLOCK) == OSR_OK);

#ifdef CC_VDP_FULL_ISR
            _arFbg[u4Idx].prState = &_rState;
#endif

            // create semaphore
            VERIFY(_FBM_csema_create(&_arFbg[u4Idx].hEmptyQSemaphore, _arFbg[u4Idx].hMutex, 0) == OSR_OK);

            // create semaphore
            VERIFY(_FBM_csema_create(&_arFbg[u4Idx].hEmptyBQSemaphore, _arFbg[u4Idx].hMutex, 0) == OSR_OK);

            // create semaphore
            VERIFY(_FBM_csema_create(&_arFbg[u4Idx].hEmptyResizeQSemaphore, _arFbg[u4Idx].hMutex, 0) == OSR_OK);

            VERIFY(_FBM_csema_create(&_arFbg[u4Idx].hEmptyResize2QSemaphore, _arFbg[u4Idx].hMutex, 0) == OSR_OK);


#ifdef CC_VDP_FULL_ISR
            _arFbg[u4Idx].hEmptyQSemaphore.prState = &_rState;
            _arFbg[u4Idx].hEmptyBQSemaphore.prState = &_rState;
            _arFbg[u4Idx].hEmptyResizeQSemaphore.prState = &_rState;
#endif
        }

        // initialize frame buffer pool
        _prPool = _FBM_PoolInit();
        ASSERT(_prPool != NULL);

        // initialize frame buffer
        _FBM_FbInit(_arFbg);
#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
        _FBM_InitSeamlessBuffer();
#endif
        //FBM_Inst_Init(); ??
#ifndef NDEBUG
#ifdef CC_FBM_MAPPING_ONE_BY_ONE
        FBM_QueryStatus(0xff);
#endif
#endif
    }
}
#endif


//-------------------------------------------------------------------------
/** FBM_GetFbgNs
 *  Get maximum FBG number
 *  @return NONE.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFbgNs(void)
{
    return FBG_MAX_NS;
}


//-------------------------------------------------------------------------
/** FBM_VMallocMaping
 *  Calc the buffer Ns for w,h
 *  @return Ns.
 */
//-------------------------------------------------------------------------
#ifdef CC_VDEC_FBM_DYNAMIC_MAPPING

VOID * FBM_WorkBufPartMap(UCHAR ucFbgId, UPTR u4Addr, UINT32 u4Size)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return NULL;
    }

    LOG(3," FbgId(%d) MAP Addr 0x%x Size 0x%x\n",ucFbgId,u4Addr,u4Size);

    if (_arFbg[ucFbgId].pWorkBufVirAddr)
    {
        BSP_UnMapReservedMem(_arFbg[ucFbgId].pWorkBufVirAddr);
    }

    //VC1=12.75K;  VP8=16K;  MPEG=4K;  RV=75K; MJPEG=300K
    //ASSERT(u4Size <= 300*1024);

    _arFbg[ucFbgId].pWorkBufVirAddr = BSP_MapReservedMem((VOID *)u4Addr, u4Size);

    if (!_arFbg[ucFbgId].pWorkBufVirAddr)
    {
        LOG(0, "WorkBuf(0x%lx) Map(%d) Virtual Failed!\n", u4Addr, u4Size);
        ASSERT(0);
    }

    return _arFbg[ucFbgId].pWorkBufVirAddr;
}
#endif


//-------------------------------------------------------------------------
/** FBM_CreateGroupExt
 *  Create FBM Group
 *  @param  ucFbgType   FBG type.
 *  @return FBG index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_CreateGroupExt(UCHAR ucFbgType, UINT32 u4VDecFmt,
                         UINT32 u4HSize, UINT32 u4VSize, FBM_CREATE_FBG_PAR_T *prPar)
{
    UCHAR u4FbgId = FBM_FBG_ID_UNKNOWN;
#ifdef CC_B2R_RES_SUPPORT
    B2R_IPT_INFO_T t_b2r_res;
    VDEC_ES_INFO_T *prVdecEsInfo = NULL;
#endif

    HAL_TIME_T rTimeStart;
    HAL_TIME_T rTimeEnd;
    HAL_TIME_T rTimeDelta;
    HAL_GetTime(&rTimeStart);
    if(prPar && (prPar->ucCftFbgId == 0))
    {
        prPar->ucCftFbgId = FBM_FBG_ID_UNKNOWN;
    }
    else if (prPar)
    {
        prPar->ucCftFbgId--;
    }

    VERIFY(x_sema_lock(_hFbgMutex, X_SEMA_OPTION_WAIT) == OSR_OK);
    if ((ucFbgType == FBM_FBG_TYPE_4K2K ) && (u4VDecFmt == FBM_VDEC_JPEG))
    {
        ucFbgType = FBM_FBG_TYPE_4K2K_JPEG;
        LOG(0,"This case is JPEG and revert jpeg from 4k2k video\n");
    }

    if ((ucFbgType == FBM_FBG_TYPE_8K) && (u4VDecFmt == FBM_VDEC_JPEG))
    {
        ucFbgType = FBM_FBG_TYPE_8K_JPEG;
        LOG(0,"This case is JPEG and revert jpeg from 8K video\n");
    }
    u4HSize = FBM_ALIGN_MASK(u4HSize,64-1);
    u4VSize = FBM_ALIGN_MASK(u4VSize,64-1);
    LOG(0,"FBM_CreateGroupExt: FbgType(%d) Codec(%d) HV(%d, %d) 10Bit(%d) UFO(%d) SM(%d) dolby(%d) fps(%d) ref(%d) fgSecureBuf(%d) fgHdrBuffer(%d).\n",
        ucFbgType,u4VDecFmt,u4HSize,u4VSize,
        prPar?prPar->fg10Bit:0,
        prPar?prPar->fgUFO:0,
        prPar?prPar->eSeamlessMode:0,
        prPar?prPar->eDolbyType:FBM_FBG_DOLBY_TYPE_NONE,
        prPar?prPar->u1Fps:0,
        prPar?prPar->u1RefNum:0,
        prPar?prPar->fgSecureBuf:0,
        prPar?prPar->fgHdrBuffer:0);


    // Check frame buffer group type
    if (u4VDecFmt == FBM_VDEC_UNKNOWN)
    {
        LOG(0,"vdec type unknown\n");
        goto create_fbg_fail;
    }
    if(prPar && (prPar->ucCftFbgId != FBM_FBG_ID_UNKNOWN) && (prPar->ucCftFbgId < FBG_MAX_NS))
    {
        u4FbgId = prPar->ucCftFbgId;
        _arFbg[u4FbgId].fgMoreCreateFbg = TRUE;

        FBM_ChangeResolution(u4FbgId,u4HSize,u4VSize,FALSE);
        VERIFY(x_sema_unlock(_hFbgMutex) == OSR_OK);
        return u4FbgId;
    }

    u4FbgId = FBM_InitFbgInfo(prPar);
    if(u4FbgId == FBM_FBG_ID_UNKNOWN)
    {
        goto create_fbg_fail;
    }
    else
    {
        _arFbg[u4FbgId].u4VDecFmt = u4VDecFmt;
        _arFbg[u4FbgId].ucFbgType = ucFbgType;
    }
    if((prPar && (prPar->fgSecureBuf || prPar->eSeamlessMode)) || (u4HSize * u4VSize > FBM_FBG_TYPE_1080HD_Y_SIZE))
    {
        FBM_SetTagQValid(TRUE);
    }
    else
    {
         FBM_SetTagQValid(FALSE);
    }
    // Settings
    if(prPar &&  (prPar->eSeamlessMode & POST_PROCESS_DISPLAY_ROTATE))
    {
        if(prPar->fgUFO || prPar->fg10Bit || (prPar->eSeamlessMode&POST_PROCESS_SEAMLESS)
           || u4HSize > FBM_FBG_1080HD_H || u4VSize > FBM_FBG_1080HD_V)
        {
            prPar->eSeamlessMode = prPar->eSeamlessMode & (~POST_PROCESS_DISPLAY_ROTATE);
            LOG(1,"Disable Rotate Process\n");
        }
#ifndef CC_SUPPORT_DIRECTION_ROTATE
        prPar->eSeamlessMode = prPar->eSeamlessMode & (~POST_PROCESS_DISPLAY_ROTATE);
#endif
    }

    _arFbg[u4FbgId].eSeamlessMode = prPar ? prPar->eSeamlessMode : SEAMLESS_NONE;
    if ((_arFbg[u4FbgId].eSeamlessMode & SEAMLESS_2FBS_2POOL) == SEAMLESS_2FBS_2POOL)
    {
        _arFbg[u4FbgId].eSeamlessMode &= ~(SEAMLESS_2FBS_2POOL);
        _arFbg[u4FbgId].eSeamlessMode |= (SEAMLESS_ONE_FBS);
    }


    if (FBM_ConfigFrameBuffer((UCHAR)(u4FbgId), u4HSize, u4VSize, prPar) != FBM_RETURN_OK)
    {
        goto create_fbg_fail;
    }

    _u1FbgColorMode = FBM_CM_420;

    HAL_GetTime(&rTimeEnd);
    HAL_GetDeltaTime(&rTimeDelta, &rTimeStart, &rTimeEnd);
    LOG(0, "Creat Fbg1 cost -> %d ms\n", (rTimeDelta.u4Seconds * 1000 + (rTimeDelta.u4Micros / 1000)));

    HAL_GetTime(&rTimeStart);

#ifdef CC_B2R_RES_SUPPORT
    if(prPar &&
       !prPar->fgThumbnailMode)
    {
        LOG(1,"[B2R_RES]FBM create fbg b2r_Res enter,u4FbgId(%d)!\n", u4FbgId);

        prVdecEsInfo = _VDEC_GetEsInfo(prPar->u1VdecId);
        if(prVdecEsInfo == NULL)
        {
            LOG(1,"!!!!!!!!!!!Can not get ESinfo with vdecid(%d)\n",prPar->u1VdecId);
        }

        switch(u4VDecFmt)
        {
            case FBM_VDEC_H265:
                t_b2r_res.t_vd.eCodec = VDEC_H265;
                break;
            case FBM_VDEC_JPEG:
                t_b2r_res.t_vd.eCodec = VDEC_JPEG;
                break;
            default:
                t_b2r_res.t_vd.eCodec = VDEC_OTHER;
                break;
        }

        t_b2r_res.t_vd.fgUfoEn = prPar->eSeamlessMode ?
                                 TRUE : prPar->fgUFO;
        t_b2r_res.t_vd.u1PixDepth = prPar->fg10Bit ? 10 : 8;
        t_b2r_res.t_vd.u4Resolution = u4HSize * u4VSize;

        if(prVdecEsInfo != NULL)
        {
            t_b2r_res.u1VdpId = prVdecEsInfo->u4RenderVDPId;
        }

        LOG(1,"[B2R_RES]FBM create fbg b2r_Res info:codec(%d),fgUfoEn(%d),PixelDepth(%d),Resolution(%d) with VDPID(%d)!\n",
            t_b2r_res.t_vd.eCodec,t_b2r_res.t_vd.fgUfoEn,t_b2r_res.t_vd.u1PixDepth,t_b2r_res.t_vd.u4Resolution,t_b2r_res.u1VdpId);

        FBM_B2rResIdAccess(u4FbgId, RES_RW, &t_b2r_res);
    }
#endif

    HAL_GetTime(&rTimeEnd);
    HAL_GetDeltaTime(&rTimeDelta, &rTimeStart, &rTimeEnd);
    LOG(2, "Creat Fbg2 cost -> %d ms\n", (rTimeDelta.u4Seconds * 1000 + (rTimeDelta.u4Micros / 1000)));

    // [LOG] FBM Create
    SYSLOG(FBM_PREFIX + 99, u4FbgId, ucFbgType, 0);

    // Apply global value
    if(FBM_ChkFrameBufferGlobalFlagIsr(0xFF, FBM_FLAG_FB_DECODE_ONLY))
    {
        _arFbg[u4FbgId].u4FbgFlag |= FBM_FLAG_DISP_READY;
    }
    if (prPar && prPar->fgThumbnailMode)
    {
        _arFbg[u4FbgId].u4FbgFlag |= FBM_FLAG_THUMBNAIL_MODE;
        _arFbg[u4FbgId].u4FbgFlag |= FBM_FLAG_DISP_READY;
    }

    ASSERT(_arFbg[u4FbgId].hEmptyQSemaphore.hMutex == _arFbg[u4FbgId].hMutex);
    ASSERT(_arFbg[u4FbgId].hEmptyBQSemaphore.hMutex == _arFbg[u4FbgId].hMutex);

    VERIFY(x_sema_unlock(_hFbgMutex) == OSR_OK);

    return FBM_BYTE(u4FbgId);

create_fbg_fail:
    FBM_ReleaseGroup(u4FbgId);
    _u1FbgColorMode = FBM_CM_420;
    VERIFY(x_sema_unlock(_hFbgMutex) == OSR_OK);
    return FBM_FBG_ID_UNKNOWN;
}

VOID FBM_MemsetFbgInfo(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    _arFbg[ucFbgId].fgEnableNewSeamless = 0;
    _arFbg[ucFbgId].fgAutoSeamless = 0;

    _arFbg[ucFbgId].ucFbgType = 0;
    _arFbg[ucFbgId].ucFbgId = 0;
    _arFbg[ucFbgId].ucFbgCm = 0;
    _arFbg[ucFbgId].ucFbNs = 0;
    _arFbg[ucFbgId].ucFbNsBase = 0;
    _arFbg[ucFbgId].ucFbNsOld = 0;
    _arFbg[ucFbgId].ucFbNsOldBase = 0;
    _arFbg[ucFbgId].ucMvBufNs = 0;
    _arFbg[ucFbgId].ucSeamlessFbNs = 0;
    _arFbg[ucFbgId].fgEnableNewSeamless = 0;
    _arFbg[ucFbgId].ucSeamless2FbNs = 0;
    _arFbg[ucFbgId].ucCurSeamlessTaskId = 0;
    _arFbg[ucFbgId].ucPictureId = 0;
    _arFbg[ucFbgId].ucSeamlessRzId = 0;
    _arFbg[ucFbgId].ucSeamlessRzId2 = 0;
    _arFbg[ucFbgId].ucSeamlessRzMask = 0;
    _arFbg[ucFbgId].ucFbDecode = 0;
    _arFbg[ucFbgId].ucFbFRef = 0;
    _arFbg[ucFbgId].ucFbBRef = 0;
    _arFbg[ucFbgId].ucFbResize = 0;
    _arFbg[ucFbgId].ucFbResize2 = 0;
    _arFbg[ucFbgId].ucFbFRefValid = 0;
    _arFbg[ucFbgId].ucFbBRefValid = 0;
    _arFbg[ucFbgId].ucStcSrc = 0;
    _arFbg[ucFbgId].ucAvSyncMode = 0;
    _arFbg[ucFbgId].ucPlayMode = 0;
    _arFbg[ucFbgId].fgSeqNoEqual = FALSE;
    _arFbg[ucFbgId].fgRlsDispQue = FALSE;
    _arFbg[ucFbgId].u4CrtFbgCnt  = 0;
    _arFbg[ucFbgId].ucPlayMode = 0;
    _arFbg[ucFbgId].ucNewFbId = 0;
    _arFbg[ucFbgId].ucSeqChg = 0;
    _arFbg[ucFbgId].ucSeqChgFbId = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].fgGotFirstSeqChg = 0;
    _arFbg[ucFbgId].fgOMXGetFirstFb = 0;
    _arFbg[ucFbgId].ucOMXPrevFb = 0;
    _arFbg[ucFbgId].ucLastDecodeReference = 0;
    _arFbg[ucFbgId].aucResizeBlockFb = 0;
    _arFbg[ucFbgId].fgIsSeamlessCft = 0;
    _arFbg[ucFbgId].fgCreateFromInst = 0;
    _arFbg[ucFbgId].fgSendEOS = 0;
    _arFbg[ucFbgId].u1DecoderSrcId = 0;
    _arFbg[ucFbgId].u1FbgAppMode = 0;
    _arFbg[ucFbgId].u4VDecFmt = 0;
    _arFbg[ucFbgId].u4FbgFlag = 0;
    _arFbg[ucFbgId].u4FbWidth = 0;
    _arFbg[ucFbgId].u4FbHeight = 0;
    _arFbg[ucFbgId].u4WfdFlag = 0;
    _arFbg[ucFbgId].u4_es_cnt = 0;
    _arFbg[ucFbgId].u4ResidualFb = 0;
    _arFbg[ucFbgId].u4ResidualFree = 0;
    _arFbg[ucFbgId].u4WorkBufSize = 0;
    _arFbg[ucFbgId].u4FbMemoryPool = 0;
    _arFbg[ucFbgId].u4FbMemoryPoolC = 0;
    _arFbg[ucFbgId].u4FbMemoryPoolSize = 0;
    _arFbg[ucFbgId].u4FbMemoryPool2 = 0;
    _arFbg[ucFbgId].u4FbMemoryPool2C = 0;
    _arFbg[ucFbgId].u4FbMemoryPool2Size = 0;
    _arFbg[ucFbgId].u4FbResizeMemoryPoolSize = 0;
    _arFbg[ucFbgId].u4FbResizeMemoryPool = 0;
    _arFbg[ucFbgId].u4FbResizeExtraMemoryPool = 0;
    _arFbg[ucFbgId].u4FbResizeExtraMemoryPoolSize = 0;
    _arFbg[ucFbgId].u4FbResizeMemoryPool2 = 0;
    _arFbg[ucFbgId].u4FbResizeMemoryPool2Size = 0;
    _arFbg[ucFbgId].fgMvAllocate = 0;
    _arFbg[ucFbgId].eResolutionChangeMode = FBM_RESOLUTION_CHANGE_MODE_NONE;
    _arFbg[ucFbgId].u4FbStartPoolYAddr = 0;
    _arFbg[ucFbgId].u4FbEndPoolYAddr = 0;
    _arFbg[ucFbgId].u4FbStartPool2YAddr = 0;
    _arFbg[ucFbgId].u4FbEndPool2YAddr = 0;
    _arFbg[ucFbgId].u4FbStartPoolCAddr = 0;
    _arFbg[ucFbgId].u4AvSyncStatus = 0;
#ifdef CC_B2R_RES_SUPPORT
    _arFbg[ucFbgId].pt_res = 0;
#endif
#ifdef FBM_VIRTUAL_MPEG
    _arFbg[ucFbgId].u4VmStatus = 0;
#endif

    //_arFbg[ucFbgId].pMallocAddr = 0;
    _arFbg[ucFbgId].pWorkBufVirAddr = 0;
    _arFbg[ucFbgId].fg10Bit = 0;
    _arFbg[ucFbgId].fgUFO = 0;
    _arFbg[ucFbgId].fgIsGameMode = 0;
    _arFbg[ucFbgId].u4MvStartAddr = 0;
    _arFbg[ucFbgId].eSeamlessMode = 0;


    _arFbg[ucFbgId].au4MiscTblStartAddr = 0;
    _arFbg[ucFbgId].u4ExtraYBuffer = 0;
    _arFbg[ucFbgId].u4ExtraCBuffer = 0;
    _arFbg[ucFbgId].u4RPRSeamlessBuffer = 0;
    _arFbg[ucFbgId].prPicHdr = 0;
    _arFbg[ucFbgId].eCodecType = 0;
    _arFbg[ucFbgId].fgSeqChgPause = FALSE;

    _arFbg[ucFbgId].u4LastB2rAcquireDispTag = INVALID_DISPTAG;
    _arFbg[ucFbgId].ucLastB2rAcquireFbId = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].u1Fps = 0;
    _arFbg[ucFbgId].eDolbyType = FBM_FBG_DOLBY_TYPE_NONE;
    _arFbg[ucFbgId].fgNonBuf = FALSE;

    _arFbg[ucFbgId].ucFbNsMajorBase = 0;
    _arFbg[ucFbgId].ucFbNsMinorBase = 0;
    _arFbg[ucFbgId].ucFbNsMajor = 0;
    _arFbg[ucFbgId].ucFbNsMinor = 0;


    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rSeqHdr,0x0,sizeof(FBM_SEQ_HDR_T));
    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rEmptyQ,0x0,sizeof(FBM_FBQ_T));
    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rSeqChgPendingQ,0x0,sizeof(FBM_SEQ_CHG_QUE_T));

    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rDisplayQ,0x0,sizeof(FBM_FBQ_T));
    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rResizeEmptyQ,0x0,sizeof(FBM_FBQ_T));
    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rResize2EmptyQ,0x0,sizeof(FBM_FBQ_T));
    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rTagQ,0x0,sizeof(FBM_FBQ_T));

    FBM_MEMSET((VOID*) _arFbg[ucFbgId].arRlResizeFb,0x0,(sizeof(HAL_TIME_T)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].u4DispTag,0x0,(sizeof(UINT64)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].u4DropTag,0x0,(sizeof(UINT64)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4Dbk4pCnt,0x0,(sizeof(UINT32)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4DbkOfstCnt,0x0,(sizeof(UINT32)*FBM_MAX_FB_NS_PER_GROUP));

    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4Resize2AddrC,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4Resize2AddrY,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4ResizeAddrC,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4ResizeAddrY,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4GdmaMemsetCId,0x0,(sizeof(UINT32)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4GdmaMemsetYId,0x0,(sizeof(UINT32)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4GfxMemsetId,0x0,(sizeof(UINT32)*(FBM_MAX_FB_NS_PER_GROUP*2)));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4AddrMv,0x0,(sizeof(UPTR)*(FBM_MAX_FB_NS_PER_GROUP -1)));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4AddrC_Ext,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4AddrC,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4AddrY_Ext,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].au4AddrY,0x0,(sizeof(UPTR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucFbStatus,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucResizeFbStatus,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucResizeTaskId,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucResizeSrcFbId,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucResize2FbStatus,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucResize2TaskId,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucResize2SrcFbId,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucPlayBackNs,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].aucChangeFieldNs,0x0,(sizeof(UCHAR)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].afgRefList,0x0,(sizeof(BOOL)*FBM_MAX_FB_NS_PER_GROUP));
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].afgIsOwner,0x0,(sizeof(BOOL)*FBM_MAX_FB_NS_PER_GROUP));
#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
    FBM_MEMSET((VOID*) _arFbg[ucFbgId].u4SeamlessAddr,0x0,(sizeof(UPTR)*FBM_SEAMLESS_GROUP_COUNT));
#endif

}

//-------------------------------------------------------------------------
/** FBM_ReleaseGroup
 *  Release FBM Group
 *  @param  ucFbgType   FBG type.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_ReleaseGroup(UCHAR ucFbgId)
{
    // Notes about mutex semaphore
    // We will not destroy mutex semaphore at release
    // Because OSAI itself is NOT threadsafe
    // Semaphore release function is dangerous

    void* pWorkBufVirAddr = NULL;
    UPTR u4FbMemoryPool;
    UPTR u4FbMemoryPool2;
    UCHAR    ucFbgType;
    UCHAR    ucIdx = 0;
    BOOL     bIsWaiting = FALSE;
    UCHAR ucEsId;
    static  UINT32 u4WaitingCnt = 0;


    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    ucEsId = _arFbg[ucFbgId].u1DecoderSrcId;

    if (_arFbg[ucFbgId].bByPassMJC)
    {
#if (defined(CC_MT5886)) && !defined(CC_BYPASS_MJC)
        vDrvMJCSetBypassVariable(BYP_MJC_BY_FBM,0);
        vDrvMJCBypassOnOff(0);
        _arFbg[ucFbgId].bByPassMJC = FALSE;
#endif
    }

    if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_MPEG4) || (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8))
    {
        do
        {
            // query emptyQ status
            FBM_MUTEX_LOCK(ucFbgId);
            bIsWaiting = FALSE;
            for(ucIdx = _arFbg[ucFbgId].ucFbNsBase; ucIdx < _arFbg[ucFbgId].ucFbNs; ucIdx++)
            {
                if (_arFbg[ucFbgId].aucFbStatus[ucIdx] != FBM_FB_STATUS_EMPTY && _arFbg[ucFbgId].u4DispTag[ucIdx] != INVALID_DISPTAG)
                {
                    LOG(0,"Need waiting cnt(%d) Release all empty Que Fb(%d) FbStatus(%d)\n",u4WaitingCnt,ucIdx,_arFbg[ucFbgId].aucFbStatus[ucIdx]);
                    u4WaitingCnt++;
                    bIsWaiting = TRUE;

                    if (u4WaitingCnt > 100)
                    {
                        bIsWaiting = FALSE;
                        u4WaitingCnt = 0;
                        LOG(0,"Force stop Waiting Fb Empty\n");
                    }
                    break;
                }

            }

            if (bIsWaiting)
            {
                LOG(0,"Waiting Release all empty Que\n");
                FBM_MUTEX_UNLOCK(ucFbgId);
                x_thread_delay(10);
                continue;
            }
            LOG(0,"Waited Release all empty Que\n");
            FBM_MUTEX_UNLOCK(ucFbgId);
            break;
        }
        while(1);

    }

    LOG(0, "[%s-%d]Fbg(%d) release.\n", __func__, __LINE__, ucFbgId);
    VERIFY(x_sema_lock(_hFbgMutex, X_SEMA_OPTION_WAIT) == OSR_OK);
    FBM_MUTEX_LOCK(ucFbgId);

#ifdef CC_B2R_RES_SUPPORT
    FBM_B2rResIdRelease(ucFbgId);
#endif

    u4FbMemoryPool = _arFbg[ucFbgId].u4FbMemoryPool;
    u4FbMemoryPool2 = _arFbg[ucFbgId].u4FbMemoryPool2;
    ucFbgType = _arFbg[ucFbgId].ucFbgType;
    pWorkBufVirAddr = _arFbg[ucFbgId].pWorkBufVirAddr;

    if (_arFbg[ucFbgId].fgEnableNewSeamless)
    {
        FBM_MUTEX_UNLOCK(ucFbgId); //unlock first for VDP Prescale thread exit normally.
        _VDP_Prescale_Close(_arFbg[ucFbgId].ucSeamlessRzId);
        if( ((_arFbg[ucFbgId].rSeqHdr.eSeamlessMode & SEAMLESS_TWO_RESIZER) == SEAMLESS_TWO_RESIZER)
            && (_arFbg[ucFbgId].ucSeamlessRzId2 != VDP_PRESCALE_RZ_ID_UNKNOWN))
        {
            _VDP_Prescale_Close(_arFbg[ucFbgId].ucSeamlessRzId2);
        }
        FBM_MUTEX_LOCK(ucFbgId);
    }

    if (_arFbg[ucFbgId].pFbmSmlPool)
    {
        FBM_Free(_arFbg[ucFbgId].pFbmSmlPool);
        _arFbg[ucFbgId].pFbmSmlPool = NULL;
    }
    if (_arFbg[ucFbgId].pFbmSmlPool2)
    {
        FBM_Free(_arFbg[ucFbgId].pFbmSmlPool2);
        _arFbg[ucFbgId].pFbmSmlPool2 = NULL;
    }

    if (_arFbg[ucFbgId].pFbmSmlPoolC)
    {
        FBM_Free(_arFbg[ucFbgId].pFbmSmlPoolC);
        _arFbg[ucFbgId].pFbmSmlPoolC = NULL;
    }
    if (_arFbg[ucFbgId].pFbmSmlPool2C)
    {
        FBM_Free(_arFbg[ucFbgId].pFbmSmlPool2C);
        _arFbg[ucFbgId].pFbmSmlPool2C = NULL;
    }

#ifdef CC_VDP_FULL_ISR
    _arFbg[ucFbgId].prState = &_rState;
#endif

    if(u4FbMemoryPool && !_arFbg[ucFbgId].fgNonBuf)
    {
        _FBM_PoolRelease(u4FbMemoryPool);
    }
    if(u4FbMemoryPool2 && !_arFbg[ucFbgId].fgNonBuf)
    {
        _FBM_PoolRelease(u4FbMemoryPool2);
    }

#ifdef CC_VDEC_FBM_DYNAMIC_MAPPING
    if (pWorkBufVirAddr)
    {
        BSP_UnMapReservedMem(pWorkBufVirAddr);
    }
#endif

    VDEC_FbgReleaseHdlr(_arFbg[ucFbgId].u1DecoderSrcId);
#ifdef CC_FBM_4K_SEAMLESS_NOT_SUPPORT
    {
        UINT8 i = 0;
        for (i = 0; i < FBM_SEAMLESS_GROUP_COUNT; i++)
        {
            if (_arFbg[ucFbgId].u4SeamlessAddr[i] != 0)
            {
                FBM_ReleaseSeamlessBuffer(_arFbg[ucFbgId].u4SeamlessAddr[i]);
                _arFbg[ucFbgId].u4SeamlessAddr[i] = 0;
            }
        }
    }
#endif

    // Clear frame buffer group
    FBM_MemsetFbgInfo(ucFbgId);

    // Init Settings, refer to FBM_Init
    _arFbg[ucFbgId].ucFbgType = FBM_FBG_TYPE_UNKNOWN;
    _arFbg[ucFbgId].ucFbgId = FBM_FBG_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbgCm = FBM_CM_UNKNOWN;
    _arFbg[ucFbgId].ucStcSrc = STC_SRC_NS;
    _arFbg[ucFbgId].ucAvSyncMode = VID_SYNC_MODE_NS;
    _arFbg[ucFbgId].ucPlayMode = FBM_FBG_DTV_MODE;
    _arFbg[ucFbgId].u4AvSyncStatus = FBM_FBG_AVSYNC_DISABLE;
    _arFbg[ucFbgId].fgIsSeamlessCft = FALSE;
    _arFbg[ucFbgId].u4PauseType = FBM_PAUSE_TYPE_UNKOWN;

    _arFbmCbFunc.aau4CbFunc[ucFbgId][FBM_CB_FUNC_FB_READY_EX_IND] = 0;
    _arFbmCbFunc.aau4CbFunc[ucFbgId][FBM_CB_FUNC_FBG_CHG_EX_IND] = 0;
    for (ucIdx = 0; ucIdx < _arFbg[ucFbgId].ucFbNs; ucIdx++)
    {
        if (ucIdx >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"Fb Id overflow!!\n");
            break;
        }
        _arFbg[ucFbgId].u4DispTag[ucIdx] = INVALID_DISPTAG;
    }


    LOG(2, "release Done.\n");

    FBM_MUTEX_UNLOCK(ucFbgId);
    VERIFY(x_sema_unlock(_hFbgMutex) == OSR_OK);

    if (FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND], _arFbmCbFunc.au4CbFuncCRC[FBM_CB_FUNC_FBG_CHG_IND]))
    {
        ((FBM_FBG_CHG_IND_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND])(FBM_FBG_ID_UNKNOWN, ucEsId);
    }
    else
    {
        LOG(1,"cb FBM_CB_FUNC_FBG_CHG_IND is NULL\n");
    }

}


//-------------------------------------------------------------------------
/** FBM_ResetGroup
 *  Reset FBM Group
 *  @param  ucFbgType   FBG type.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_ResetGroup(UCHAR ucFbgId)
{
    UCHAR u4FbIdx;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    if (VERIFY_FB_NS(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_arFbg[ucFbgId].fgCreateFromInst)
    {
        ASSERT(0);
        FBM_MUTEX_UNLOCK(ucFbgId);
        return;
    }
    // put all frame buffer into empty queue
    _arFbg[ucFbgId].rEmptyQ.ucCount = 0;
    for (u4FbIdx = _arFbg[ucFbgId].ucFbNsBase;
         ((u4FbIdx < _arFbg[ucFbgId].ucFbNs)&&(u4FbIdx < FBM_MAX_FB_NS_PER_GROUP)); u4FbIdx++)
    {
        FBM_SetFrameBufferStatus(ucFbgId, (UCHAR)(u4FbIdx), FBM_FB_STATUS_EMPTY);
    }

    // put all frame buffer into empty queue
    if (_arFbg[ucFbgId].fgEnableNewSeamless)
    {
        _arFbg[ucFbgId].rResizeEmptyQ.ucCount = 0;
        _arFbg[ucFbgId].rResize2EmptyQ.ucCount = 0;

        for (u4FbIdx = 0; ((u4FbIdx < _arFbg[ucFbgId].ucSeamlessFbNs)&&(u4FbIdx < FBM_MAX_FB_NS_PER_GROUP)); u4FbIdx++)
        {
            _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, (UCHAR)(u4FbIdx));
        }

        for (u4FbIdx = 0; ((u4FbIdx < _arFbg[ucFbgId].ucSeamless2FbNs)&&(u4FbIdx < FBM_MAX_FB_NS_PER_GROUP)); u4FbIdx++)
        {
            _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, (UCHAR)(u4FbIdx));
        }
    }

    if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG))
    {
        // create semaphore, Empty Q
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)_arFbg[ucFbgId].ucFbNs) == OSR_OK);
    }
    else
    {
        // create semaphore, Empty Q
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)_arFbg[ucFbgId].ucFbNs) == OSR_OK);

        // create semaphore, Empty BQ
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyBQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)(_arFbg[ucFbgId].ucFbNs - FBM_REF_FB_NS_PER_GROUP)) == OSR_OK);
    }

    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyResizeQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)_arFbg[ucFbgId].ucSeamlessFbNs) == OSR_OK);

    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyResize2QSemaphore, _arFbg[ucFbgId].hMutex, (INT32)_arFbg[ucFbgId].ucSeamless2FbNs) == OSR_OK);

    // clear display queue
    _arFbg[ucFbgId].rDisplayQ.ucReadIdx = 0;
    _arFbg[ucFbgId].rDisplayQ.ucCount = 0;

    // Init Settings
    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRefValid = 0;
    _arFbg[ucFbgId].ucFbBRefValid = 0;

    // default flag
    _arFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_NOT_READY;

    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyResizeQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyResize2QSemaphore.hMutex == _arFbg[ucFbgId].hMutex);

    FBM_MUTEX_UNLOCK(ucFbgId);
}


//-------------------------------------------------------------------------
/** FBM_InvalidateRefFrameBuffer
 *  Invalidate FBM Group reference frame buffer
 *  @param  ucFbgType   FBG type.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_InvalidateRefFrameBuffer(UCHAR ucFbgId)
{
    // Note about usage
    // When mpv mode change, invalidate refernce
    // Start again at next I picture

    UCHAR ucFbIdx;
    UINT32 u4LockNs;
    UINT32 u4EmptyNs;
    UINT32 u4EmptyRefNs;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    if (VERIFY_FB_NS(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);
    if (_arFbg[ucFbgId].fgCreateFromInst)
    {
        for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase; ((ucFbIdx < _arFbg[ucFbgId].ucFbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
        {
            if (_arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_DECODE ||
                _arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_READY ||
                _arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_FIELD_READY)
            {
                FBM_SetFrameBufferStatus(ucFbgId, ucFbIdx, FBM_FB_STATUS_EMPTY); //flush to displayQ
            }
        }

        _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbFRefValid = 0;
        _arFbg[ucFbgId].ucFbBRefValid = 0;

        FBM_MUTEX_UNLOCK(ucFbgId);
        return;
    }

    // display can lock 1~2 B picture
    u4LockNs = 0;
    for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase;
         ((ucFbIdx < _arFbg[ucFbgId].ucFbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
    {
        if (_arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_LOCK)
        {
            u4LockNs++;
        }
    }

#if 1
    // reset counting Semaphore
    _arFbg[ucFbgId].hEmptyBQSemaphore.i4Count = 0;
    _arFbg[ucFbgId].hEmptyQSemaphore.i4Count = 0;
#endif

    // clear empty queue
    _arFbg[ucFbgId].rEmptyQ.ucReadIdx = 0;
    _arFbg[ucFbgId].rEmptyQ.ucCount = 0;

    // clear display queue
    _arFbg[ucFbgId].rDisplayQ.ucReadIdx = 0;
    _arFbg[ucFbgId].rDisplayQ.ucCount = 0;
    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
//    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRefValid = 0;
    _arFbg[ucFbgId].ucFbBRefValid = 0;

    u4EmptyNs = _arFbg[ucFbgId].ucFbNs - _arFbg[ucFbgId].ucFbNsBase - u4LockNs;

    u4EmptyRefNs = 0;
    if ((_arFbg[ucFbgId].ucFbFRef != FBM_FB_ID_UNKNOWN) &&
        (_arFbg[ucFbgId].aucFbStatus[_arFbg[ucFbgId].ucFbFRef] == FBM_FB_STATUS_LOCK))
    {
    }
    else
    {
        u4EmptyRefNs++;
    }
    if ((_arFbg[ucFbgId].ucFbBRef != FBM_FB_ID_UNKNOWN) &&
        (_arFbg[ucFbgId].aucFbStatus[_arFbg[ucFbgId].ucFbBRef] == FBM_FB_STATUS_LOCK))
    {
    }
    else
    {
        u4EmptyRefNs++;
    }

    // set counting Semaphore
    // Bug fixed 20050708, reference may locked by display
    // _arFbg[ucFbgId].hEmptyBQSemaphore.i4Count = (INT32)(u4EmptyNs - FBM_REF_FB_NS_PER_GROUP) is NOT correct!

    // create semaphore, Empty Q
    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);

    // create semaphore, Empty BQ
    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyBQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)(u4EmptyNs - u4EmptyRefNs)) == OSR_OK);

    for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase;
         ((ucFbIdx < _arFbg[ucFbgId].ucFbNs)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
    {
        if (_arFbg[ucFbgId].aucFbStatus[ucFbIdx] != FBM_FB_STATUS_LOCK)
        {
            if (_arFbg[ucFbgId].fgEnableNewSeamless && _arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_DISPLAYQ)
            {
                if (_arFbg[ucFbgId].prPicHdr[ucFbIdx].ucSeamlessResizeFbid != FBM_FB_ID_UNKNOWN &&
                    _arFbg[ucFbgId].aucResizeFbStatus[_arFbg[ucFbgId].prPicHdr[ucFbIdx].ucSeamlessResizeFbid] != FBM_FB_STATUS_EMPTY)
                {
                    _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, _arFbg[ucFbgId].prPicHdr[ucFbIdx].ucSeamlessResizeFbid);
                    VERIFY(_FBM_csema_unlock(&_arFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
                }
                if (_arFbg[ucFbgId].prPicHdr[ucFbIdx].ucSeamlessResize2Fbid != FBM_FB_ID_UNKNOWN &&
                    _arFbg[ucFbgId].aucResize2FbStatus[_arFbg[ucFbgId].prPicHdr[ucFbIdx].ucSeamlessResize2Fbid] != FBM_FB_STATUS_EMPTY)
                {
                    _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, _arFbg[ucFbgId].prPicHdr[ucFbIdx].ucSeamlessResize2Fbid);
                    VERIFY(_FBM_csema_unlock(&_arFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
                }
            }

            _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbIdx);
        }
    }

    LOG(2, "Invalidate G(%d) S(%d %d %d %d) R(%02x %02x) Q(%d %d %d %d)\n",
        ucFbgId,
        _arFbg[ucFbgId].aucFbStatus[0],
        _arFbg[ucFbgId].aucFbStatus[1],
        _arFbg[ucFbgId].aucFbStatus[2],
        _arFbg[ucFbgId].aucFbStatus[3],
        _arFbg[ucFbgId].ucFbFRef,
        _arFbg[ucFbgId].ucFbBRef,
        _arFbg[ucFbgId].rDisplayQ.ucCount,
        _arFbg[ucFbgId].rEmptyQ.ucCount,
        _arFbg[ucFbgId].hEmptyQSemaphore.i4Count,
        _arFbg[ucFbgId].hEmptyBQSemaphore.i4Count);

    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.i4Count >= 0);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.i4Count >= 0);

    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);

    FBM_MUTEX_UNLOCK(ucFbgId);
}


//-------------------------------------------------------------------------
/** FBM_WaitUnlockFrameBuffer
 *  Wait FBM Group unlock frame buffer
 *  @param  ucFbgType   FBG type.
 *  @param  u4Timeout   time to wait.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_WaitUnlockFrameBuffer(UCHAR ucFbgId, UINT32 u4Timeout)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    if (VERIFY_FB_NS(ucFbgId))
    {
        return;
    }

    if (_arFbg[ucFbgId].fgCreateFromInst)
    {
        return;
    }
    FBM_MUTEX_LOCK(ucFbgId);

    {
        UINT32 u4FbIdx;
        UINT32 u4LockFbNs;
        UINT32 u4EmptyFbNs;

        // unlock frame buffer Ns
        u4LockFbNs = 0;
        u4EmptyFbNs = 0;
        for (u4FbIdx = _arFbg[ucFbgId].ucFbNsBase;
             ((u4FbIdx < _arFbg[ucFbgId].ucFbNs)&&(u4FbIdx < FBM_MAX_FB_NS_PER_GROUP)); u4FbIdx++)
        {
            if (_arFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
            {
                u4LockFbNs++;
            }
            else if (_arFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_EMPTY)
            {
                u4EmptyFbNs++;
            }
        }

        // wait for lock frame buffer
        if (u4LockFbNs != 0)
        {
            u4FbIdx = 0;
            while (u4FbIdx < (u4LockFbNs + u4EmptyFbNs))
            {
                if (_FBM_csema_lock(&_arFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_WAIT, u4Timeout) == OSR_OK)
                {
                    u4FbIdx++;
                }
                else
                {
                    u4FbIdx = _arFbg[ucFbgId].ucFbNs - _arFbg[ucFbgId].ucFbNsBase;
                    LOG(6, "Wait unlock timeout! (%d, %d)\n",u4LockFbNs, u4EmptyFbNs);
                    //FBM_QueryStatus(ucFbgId);
                }
            }
        }
    }

    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);

    FBM_MUTEX_UNLOCK(ucFbgId);
}

static UCHAR _FBM_GetFBFromDispQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

    if (VERIFY_FBG(ucFbgId))
    {
        return FBM_FB_ID_UNKNOWN;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbId = FBM_FB_ID_UNKNOWN;

    if (_arFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        ucFbId = _arFbg[ucFbgId].rDisplayQ.aucQueue[_arFbg[ucFbgId].rDisplayQ.ucReadIdx];
        _arFbg[ucFbgId].rDisplayQ.ucReadIdx =
            (UCHAR)(_arFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;
        _arFbg[ucFbgId].rDisplayQ.ucCount--;

        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId(%d)\n",ucFbId);
            ASSERT(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",ucFbgId,ucFbId, _arFbg[ucFbgId].aucFbStatus[ucFbId]);
        }

        ASSERT(_arFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}


//-------------------------------------------------------------------------
/** FBM_ReleaseDispQ
 *  Release fb in DispQ to EmptyQ.
 *  @param  ucFbgId   FBG index.
 *  @return release fb number.
 */
//-------------------------------------------------------------------------
void FBM_ReleaseDispQ(UCHAR ucFbgId)
{
    UCHAR ucCnt;
    UCHAR ucFbId = FBM_FB_ID_UNKNOWN;
    UCHAR ucIdx;
    UCHAR ucVdpId = VDP_NS;
    UCHAR ucEsId = ES0;
    UCHAR ucThumbnail = 0;
    FBM_PIC_HDR_T* pPicHdr = NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    if (_arFbg[ucFbgId].fgCreateFromInst)
    {
        return;
    }

    FBM_SetFrameBufferFlag(ucFbgId, FBM_FLAG_SEEK_MODE);

    FBM_MUTEX_LOCK(ucFbgId);
    ucThumbnail = FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE);

    if (!ucThumbnail)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        ucEsId = _arFbg[ucFbgId].u1DecoderSrcId;
        ucVdpId = (UCHAR)VDP_Es2Vdp(ucEsId);
        ucFbId = VDP_GetPendingFB(ucVdpId, ucFbgId);
        VDP_SetReleaseDispQ(ucVdpId, ucFbgId);
        FBM_MUTEX_LOCK(ucFbgId);
    }

    if (_arFbg[ucFbgId].fgEnableNewSeamless)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        _VDP_Prescale_Flush(_arFbg[ucFbgId].ucSeamlessRzId, TRUE);
        if( ((_arFbg[ucFbgId].rSeqHdr.eSeamlessMode & SEAMLESS_TWO_RESIZER) == SEAMLESS_TWO_RESIZER)
            && (_arFbg[ucFbgId].ucSeamlessRzId2 != VDP_PRESCALE_RZ_ID_UNKNOWN))
        {
            _VDP_Prescale_Flush(_arFbg[ucFbgId].ucSeamlessRzId2,TRUE);
        }
        FBM_MUTEX_LOCK(ucFbgId);
    }

    ucCnt = FBM_CheckFrameBufferDispQ(ucFbgId);

    LOG(1,"release dispQ cnt(%d)\n",ucCnt);
    for (ucIdx = 0; ucIdx < ucCnt; ucIdx++)
    {
        UCHAR ucDispFbId = FBM_FB_ID_UNKNOWN;
        ucDispFbId = _FBM_GetFBFromDispQ(ucFbgId);
        if(ucDispFbId < FBM_MAX_FB_NS_PER_GROUP)
        {
            pPicHdr = FBM_GetFrameBufferPicHdr(ucFbgId, ucDispFbId);

            if (pPicHdr)
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_SEQCHG) == FBM_ENABLE_LOG_SEQCHG)
                {
                    LOG(1, "Flush FBG/FB(%d,%d)W/H(%d/%d) PicId(%d)\n",
                        ucFbgId,ucDispFbId,pPicHdr->u4SourceWidth,pPicHdr->u4SourceHeight,pPicHdr->ucPicId);
                }
                else
                {
                    LOG(1, "Flush FBG/FB(%d,%d) PicId(%d)\n",ucFbgId,ucDispFbId,pPicHdr->ucPicId);
                }
            }

            FBM_SetFrameBufferStatus(ucFbgId, ucDispFbId, FBM_FB_STATUS_EMPTY);
        }
        else
        {
            LOG(0,"invalid fb(%d)\n",ucDispFbId);
        }
    }

    if ((ucFbId != FBM_FB_ID_UNKNOWN) && (ucFbId < FBM_MAX_FB_NS_PER_GROUP))
    {
        if (_arFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK)
        {
            LOG(1, "Release Display Q with 1 more lock frame buffer!\n");
            FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
            if (!ucThumbnail)
            {
                VDP_CleanPendingFB(ucVdpId, ucFbgId);
            }
        }
    }

    // release seqhdr info
    if ((FBM_ChkSeamlessMode(ucFbgId,(~SEAMLESS_NONE))) &&
        (!FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_RESIZER)))
    {
        FBM_SEQ_HDR_T* pSeqHdr = NULL;
        //FBM_SEQ_HDR_T* pPendingSeqHdr = NULL;
        FBM_SeqChg_T*  pSeqChgQueItem = NULL;

        //save vdp the last show seq hdr info
        pSeqHdr = FBM_GetFrameBufferSeqHdr(ucFbgId);
        //pPendingSeqHdr = FBM_GetFrameBufferSeqHdrByB2R(ucFbgId);
        pSeqChgQueItem = FBM_GetLastSeqChgItem(ucFbgId);
        if (pSeqChgQueItem)
        {
            // save to seqChg Que
            FbmPutToSeqChgQue(ucFbgId,0xFF,pSeqChgQueItem);
        }

        _arFbg[ucFbgId].fgRlsDispQue = TRUE; //B2R use

        if(FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_NPTV) ||
           FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_NONTUNNEL_NPTV))
        {
            B2R_NPTV_PENDING_Q*     pt_pending_q = NULL;
            B2R_NPTV_PENDING_ITEM   t_item;
            pt_pending_q = &(_arFbg[ucFbgId].t_pending_q);

            if (pt_pending_q && (pt_pending_q->ucQSize > 0)&& (pt_pending_q->ucQSize  < PEND_NS))
            {
                _FBM_B2RDumpPendingQ(ucFbgId);
                x_memcpy(&t_item,&pt_pending_q->atPendingQ[pt_pending_q->ucQSize - 1],sizeof(B2R_NPTV_PENDING_ITEM));
                LOG(1,"Last is (%d %d %d) and remove to first\n",t_item.fgPending,t_item.u4PendingWdith,t_item.u4PendingHeight);
                x_memset(pt_pending_q,0,sizeof(B2R_NPTV_PENDING_Q));
                x_memcpy(&pt_pending_q->atPendingQ[0],&t_item,sizeof(B2R_NPTV_PENDING_ITEM));
                pt_pending_q->ucQSize += 1;
                pt_pending_q->atPendingQ[0].fgNeedCheck = TRUE;
            }
        }
    }


    FBM_MUTEX_UNLOCK(ucFbgId);
    FBM_ClrFrameBufferFlag(ucFbgId, FBM_FLAG_SEEK_MODE);

}

static void _FBM_CheckRemainMemSize(BOOL bUfo,UINT32 u4Addr,UINT32 u4Size,UINT32 u4EndPoolAddr)
{
    if (bUfo)
    {
        if ((u4Addr + u4Size + (u4Size>>8)+ FBM_8K_SIZE) > u4EndPoolAddr)
        {
            LOG(1,"FbMemoryPool remain size(0x%x) compensation size for FB (0x%x)\n",
                (u4EndPoolAddr - u4Addr),
                ((u4Addr + u4Size + (u4Size>>8)+ FBM_8K_SIZE)-u4EndPoolAddr));
        }
    }
    else
    {
        if ((u4Addr + u4Size + FBM_8K_SIZE) > u4EndPoolAddr)
        {
            LOG(1,"FbMemoryPool remain size(0x%x) compensation size for FB (0x%x)\n",
                (u4EndPoolAddr - u4Addr),
                ((u4Addr + u4Size + FBM_8K_SIZE)-u4EndPoolAddr));
        }
    }

    return;
}



//-------------------------------------------------------------------------
/** FBM_SetFrameBufferLayout
 *  Fill frame buffer with constant color
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  u4Color   color.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFrameBufferLayout(UCHAR ucFbgId, UCHAR ucFbId, UPTR u4Addr, BOOL fgIsY)
{

    if (u4Addr == 0)
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId) || VERIFY_FB(ucFbgId, ucFbId))
    {
        return;
    }

    if (fgIsY)
    {
        _arFbg[ucFbgId].au4AddrY[ucFbId] = u4Addr;
    }
    else
    {
        _arFbg[ucFbgId].au4AddrC[ucFbId] = u4Addr;
    }

}

//-------------------------------------------------------------------------
/** FBM_SetFrameBufferColor
 *  Fill frame buffer with constant color
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  u4Color   color.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFrameBufferColor(UCHAR ucFbgId, UCHAR ucFbId, UINT32 u4Color)
{
    UCHAR* pucYAddr;
    UCHAR* pucCAddr;
    UINT32 u4YSize;
    UINT32 u4CSize;
    UINT32 u4Idx;
    UCHAR ucY;
    UCHAR ucCb;
    UCHAR ucCr;

    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    switch (_arFbg[ucFbgId].ucFbgType)
    {
        case FBM_FBG_TYPE_1080HD:
            u4YSize = FBM_FBG_TYPE_1080HD_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_1080HD_C_SIZE;
            break;

        case FBM_FBG_TYPE_720HD:
            u4YSize = FBM_FBG_TYPE_720HD_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_720HD_C_SIZE;
            break;

        case FBM_FBG_TYPE_PAL:
            u4YSize = FBM_FBG_TYPE_PAL_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_PAL_C_SIZE;
            break;

        case FBM_FBG_TYPE_NTSC:
            u4YSize = FBM_FBG_TYPE_NTSC_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_NTSC_C_SIZE;
            break;

        default:
            u4YSize = 0;
            u4CSize = 0;
            ASSERT(0);
            break;
    }

    if (_arFbg[ucFbgId].ucFbgCm == FBM_CM_422)
    {
        u4CSize *= 2;
    }
    else if (_arFbg[ucFbgId].ucFbgCm == FBM_CM_444)
    {
        u4CSize *= 4;
    }
    else
    {
    }

    ucY = (UCHAR)((u4Color >> 16) & 0xFF);
    ucCb = (UCHAR)((u4Color >> 8) & 0xFF);
    ucCr = (UCHAR)((u4Color) & 0xFF);

    pucYAddr = (UCHAR*) _arFbg[ucFbgId].au4AddrY[ucFbId];
    pucCAddr = (UCHAR*)_arFbg[ucFbgId].au4AddrC[ucFbId];

    // use Gfx Engine in the future
    FBM_MEMSET(pucYAddr, ucY, u4YSize);

    for (u4Idx = 0; u4Idx < u4CSize; u4Idx += 2)
    {
        pucCAddr[u4Idx + 0] = ucCb;
        pucCAddr[u4Idx + 1] = ucCr;
    }
}


//-------------------------------------------------------------------------
/** FBM_SetFrameBufferZebraColor
 *  Fill frame buffer with constant color
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFrameBufferZebraColor(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR* pucYAddr;
    UCHAR* pucCAddr;
    UCHAR ucYColor;
    UINT32 u4YSize;
    UINT32 u4CSize;
    UINT32 u4Idx;

    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    switch (_arFbg[ucFbgId].ucFbgType)
    {
        case FBM_FBG_TYPE_1080HD:
            u4YSize = FBM_FBG_TYPE_1080HD_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_1080HD_C_SIZE;
            break;

        case FBM_FBG_TYPE_720HD:
            u4YSize = FBM_FBG_TYPE_720HD_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_720HD_C_SIZE;
            break;

        case FBM_FBG_TYPE_PAL:
            u4YSize = FBM_FBG_TYPE_PAL_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_PAL_C_SIZE;
            break;

        case FBM_FBG_TYPE_NTSC:
            u4YSize = FBM_FBG_TYPE_NTSC_Y_SIZE;
            u4CSize = FBM_FBG_TYPE_NTSC_C_SIZE;
            break;

        default:
            u4YSize = 0;
            u4CSize = 0;
            ASSERT(0);
            break;
    }

    if (_arFbg[ucFbgId].ucFbgCm == FBM_CM_422)
    {
        u4CSize *= 2;
    }
    else if (_arFbg[ucFbgId].ucFbgCm == FBM_CM_444)
    {
        u4CSize *= 4;
    }
    else
    {
    }

    pucYAddr = (UCHAR*) _arFbg[ucFbgId].au4AddrY[ucFbId];
    pucCAddr = (UCHAR*)_arFbg[ucFbgId].au4AddrC[ucFbId];

    ucYColor = 0;
    for (u4Idx = 0; u4Idx < u4YSize; u4Idx++)
    {
        pucYAddr[u4Idx] = ucYColor;

        if ((u4Idx & 0x3F) == 0x3F)
        {
            ucYColor = ~ucYColor;
        }
    }

    // use Gfx Engine in the future
    FBM_MEMSET(pucCAddr, 0x80, u4CSize);
}


//-------------------------------------------------------------------------
/** FBM_SetFrameBufferPlayBackNs
 *  Set frame buffer playback number
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  ucPlayBackNs   playback number.
 *  @param  ucChangeFieldNs   change field number.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFrameBufferPlayBackNs(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucPlayBackNs, UCHAR ucChangeFieldNs)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    _arFbg[ucFbgId].aucPlayBackNs[ucFbId] = ucPlayBackNs;
    _arFbg[ucFbgId].aucChangeFieldNs[ucFbId] = ucChangeFieldNs;
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferPlayBackNs
 *  Get frame buffer playback number
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return playback number.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFrameBufferPlayBackNs(UCHAR ucFbgId, UCHAR ucFbId)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return 0;
    }

    return _arFbg[ucFbgId].aucPlayBackNs[ucFbId];
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferChangeFieldNs
 *  Get frame buffer change field number
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return change field number.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFrameBufferChangeFieldNs(UCHAR ucFbgId, UCHAR ucFbId)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return 0;
    }

    return _arFbg[ucFbgId].aucChangeFieldNs[ucFbId];
}


//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferLastPlayBack
 *  Check frame buffer last playback
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return 1/0 for last playback or NOT.
 */
//-------------------------------------------------------------------------
UCHAR FBM_ChkFrameBufferLastPlayBack(UCHAR ucFbgId, UCHAR ucFbId)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return 1;
    }

    if (_arFbg[ucFbgId].aucPlayBackNs[ucFbId] > 1)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

#ifdef __KERNEL__
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/param.h>
#endif

void FBM_SetDumpDir(const CHAR * dir)
{
    if (dir == NULL)
    {
        dumpDir[0]= '\0';
    }
    else
    {
        x_memset(dumpDir,'\0',DUMP_DIR_LENTH);
        x_strncpy(dumpDir,dir,DUMP_DIR_LENTH - 1);
        LOG(0,"dump dir:%s\n",dumpDir);
    }
}

static BOOL _FBM_DumpData(const CHAR* fileName,UPTR u4BufPhyAddr,UINT32 u4Size)
{
#ifdef __KERNEL__
    mm_segment_t oldfs;
#ifdef CC_VDEC_FBM_DYNAMIC_MAPPING
    static VOID* pVirAddr = NULL;
#endif
    struct file *fp  = NULL;
    size_t ret;
    CHAR *buf = NULL;
#ifdef CC_VDEC_FBM_DYNAMIC_MAPPING
    if(pVirAddr)
    {
        BSP_UnMapReservedMem(pVirAddr);
    }
    pVirAddr = BSP_MapReservedMem((VOID *)u4BufPhyAddr, u4Size);
    LOG(1,"Virtual addr %p\n",pVirAddr);
#endif

    buf = (CHAR*)VIRTUAL(u4BufPhyAddr);
    oldfs = get_fs();
    set_fs(KERNEL_DS);
    fp = filp_open (fileName, (O_CREAT | O_WRONLY | O_APPEND), 0);
    if ((IS_ERR (fp)) || (NULL == fp) || (NULL == fp->f_op) || (NULL == fp->f_op->write))
    {
        set_fs(oldfs);
        LOG(3, "Do_Dump error!\n");
        return FALSE;
    }
    fp->f_pos = 0;

    ret = fp->f_op->write (fp, buf, u4Size, &fp->f_pos);

    filp_close (fp, NULL);
    set_fs(oldfs);
    return TRUE;
#else
    return TRUE;
#endif
}

static void _FBM_GetFBWH(UCHAR ucFbgId,UCHAR ucFbId,UINT32* pu4Width,UINT32* pu4Height)
{
    VDEC_HDR_INFO_T rHdrInfo;
    FBM_PIC_HDR_T* pPicHdr = NULL;

    x_memset(&rHdrInfo, 0, sizeof(VDEC_HDR_INFO_T));
    if (pu4Width == NULL || pu4Height == NULL)
    {
        LOG(0,"Error :pu2Width or pu2Height is NULL\n");
        return;
    }
    pPicHdr = FBM_GetFrameBufferPicHdr(ucFbgId, ucFbId);
    if(pPicHdr != NULL)
    {
        //real pic w & h for seamless playback
        *pu4Width = pPicHdr->u4PicPitch;
        *pu4Height = pPicHdr->u4SourceHeight;
        LOG(0,"%d x %d\n",*pu4Width,*pu4Height);
    }
    if (*pu4Width == 0 || *pu4Height== 0)
    {
        LOG(0,"Can not get width & height from pic hdr,query from vdec info\n");
        if (VDEC_QueryInfo((UCHAR)_arFbg[ucFbgId].u1DecoderSrcId, &rHdrInfo))
        {
            if (rHdrInfo.fgResized)
            {
                *pu4Width = (UINT32)rHdrInfo.u2SourceWidth;
                *pu4Height = (UINT32)rHdrInfo.u2SourceHeight;
            }
            else
            {
                *pu4Width = (UINT32)rHdrInfo.u2Width;
                *pu4Height = (UINT32)rHdrInfo.u2Height;
            }
        }
    }
}



void FBM_DumpFB(UCHAR ucFbgId,UCHAR ucFbId)
{
    if ((ucFbgId < FBG_MAX_NS) &&
        (_arFbg[ucFbgId].ucFbgType != FBM_FBG_TYPE_UNKNOWN) &&
        (_arFbg[ucFbgId].ucFbgId != FBM_FBG_ID_UNKNOWN))
    {
        UINT8  u1Depth;
        UPTR u4YStartAddr = 0,u4CStartAddr = 0,u4AddrY_Ext = 0,u4AddrC_Ext = 0;
        UINT32 u4YSize = 0,u4CSize = 0;
        CHAR dumpName[DUMP_DIR_LENTH+1];

        FBM_MUTEX_LOCK(ucFbgId);

#if 0 //all fb is allowed to dump
        if((_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_READY) &&
           (_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ) &&
           (_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK) &&
           (_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_RESIZE) &&
           (_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_RESIZE_DONE))
        {
            LOG(0,"FBG (%d) FB(%d) state is not right\n",ucFbgId,ucFbId);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return;
        }
#endif
        if(dumpDir[0] == '\0')
        {
            LOG(0,"Please use cli:fbm.sdd to set dump dir,default is /mnt/usb/sda1/\n");
            x_snprintf(dumpDir,sizeof(dumpDir) - 1,"/mnt/usb/sda1/");
        }
        if(dumpDir[0] != '\0')
        {
            UINT32 u4Width = 0,u4Height = 0;

            _FBM_GetFBWH(ucFbgId,ucFbId,&u4Width,&u4Height);
            u1Depth = _arFbg[ucFbgId].rSeqHdr.u1Depth;
            if(_arFbg[ucFbgId].rSeqHdr.ucBlockType == 0)
            {
                u4Width = FBM_ALIGN_MASK(u4Width,64-1);
                u4Height = FBM_ALIGN_MASK(u4Height,32-1);
            }
            else if(_arFbg[ucFbgId].rSeqHdr.ucBlockType == 1)
            {
                u4Width = FBM_ALIGN_MASK(u4Width,16-1);
                u4Height = FBM_ALIGN_MASK(u4Height,32-1);
            }
            u4YSize = u4Width*u4Height;
            LOG(1,"Align:W(%d) H(%d)\n",u4Width,u4Height);
            if(u1Depth == 10)
            {
                u4YSize = (u4YSize*10)>>3;
            }
            else
            {
                u1Depth = 8;
            }
            u4CSize = u4YSize >>1;//C size = Y size/2

            u4YStartAddr = _arFbg[ucFbgId].au4AddrY[ucFbId];
            u4CStartAddr = _arFbg[ucFbgId].au4AddrC[ucFbId];

            x_memset(dumpName,'\0',DUMP_DIR_LENTH + 1);
            x_snprintf(dumpName,sizeof(dumpName) - 1,"%s/%d_%d_Y(%dX%d)_%dbit.dump",dumpDir,ucFbgId,ucFbId,u4Width,u4Height,u1Depth);
            _FBM_DumpData(dumpName,u4YStartAddr,u4YSize);

            x_memset(dumpName,'\0',DUMP_DIR_LENTH + 1);
            x_snprintf(dumpName,sizeof(dumpName) - 1,"%s/%d_%d_C(%dX%d)_%dbit.dump",dumpDir,ucFbgId,ucFbId,u4Width,u4Height,u1Depth);
            _FBM_DumpData(dumpName,u4CStartAddr,u4CSize);

            if(_arFbg[ucFbgId].fgUFO)
            {
                u4AddrY_Ext = _arFbg[ucFbgId].au4AddrY_Ext[ucFbId];
                u4AddrC_Ext = _arFbg[ucFbgId].au4AddrC_Ext[ucFbId];

                x_memset(dumpName,'\0',DUMP_DIR_LENTH + 1);
                x_snprintf(dumpName,sizeof(dumpName) - 1,"%s/%d_%d_YU(%dX%d)_%dbit.dump",dumpDir,ucFbgId,ucFbId,u4Width,u4Height,u1Depth);
                _FBM_DumpData(dumpName,u4AddrY_Ext,u4YSize>>8);//Y_UFO size = Y size/256

                x_memset(dumpName,'\0',DUMP_DIR_LENTH + 1);
                x_snprintf(dumpName,sizeof(dumpName) - 1,"%s/%d_%d_CU(%dX%d)_%dbit.dump",dumpDir,ucFbgId,ucFbId,u4Width,u4Height,u1Depth);
                _FBM_DumpData(dumpName,u4AddrC_Ext,u4CSize>>8);//C_UFO size = C size/256
            }
        }
        FBM_MUTEX_UNLOCK(ucFbgId);
        return;
    }
    else
    {
        LOG(0,"Error Fbgid:%d \n",ucFbgId);
        return;
    }
}


void FBM_DumpAllDispQFB(UCHAR ucFbgId)
{
    if ((ucFbgId < FBG_MAX_NS) &&
        (_arFbg[ucFbgId].ucFbgType != FBM_FBG_TYPE_UNKNOWN) &&
        (_arFbg[ucFbgId].ucFbgId != FBM_FBG_ID_UNKNOWN))
    {
        UCHAR ucIdx;
        UINT8 ucCnt;

        FBM_MUTEX_LOCK(ucFbgId);
        for (ucIdx = 0; ucIdx < FBM_MAX_FB_NS_PER_GROUP; ucIdx++)
        {
            if (_arFbg[ucFbgId].aucFbStatus[ucIdx] == FBM_FB_STATUS_LOCK)
            {
                FBM_DumpFB(ucFbgId,ucIdx);//dump locked fb
            }
        }
        FBM_MUTEX_UNLOCK(ucFbgId);

        ucCnt = FBM_CheckFrameBufferDispQ(ucFbgId);
        for (ucIdx = 0; ucIdx < ucCnt; ucIdx++)
        {
            UCHAR ucFbId = FBM_FB_ID_UNKNOWN;

            ucFbId = _arFbg[ucFbgId].rDisplayQ.aucQueue[(_arFbg[ucFbgId].rDisplayQ.ucReadIdx + ucIdx) % FBM_MAX_FB_NS_PER_GROUP];
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"ucFbId(%d)\n",ucFbId);
            }
            else
            {
                if (_arFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
                {
                    LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",
                        ucFbgId,ucFbId,
                        _arFbg[ucFbgId].aucFbStatus[ucFbId]);
                }
                else
                {
                    FBM_DumpFB(ucFbgId,ucFbId);
                }
            }
        }
    }
    else
    {
        LOG(0,"Error Fbgid:%d \n",ucFbgId);
        return;
    }
}

BOOL  FbmSetPauseType(UCHAR ucFbgId,UINT32 u4PauseType)
{
    if (ucFbgId >= FBG_MAX_NS)
    {
        LOG(0,"FbgId(%d) exception\n",ucFbgId);
        return FALSE;
    }
    if (1 == u4PauseType)
    {
        _arFbg[ucFbgId].u4PauseType = FBM_PAUSE_TYPE_1;
    }
    else if (2 == u4PauseType)
    {
        _arFbg[ucFbgId].u4PauseType = FBM_PAUSE_TYPE_2;
    }
    else if (3 == u4PauseType)
    {
        _arFbg[ucFbgId].u4PauseType = FBM_PAUSE_TYPE_3;
    }
    else
    {
        LOG(0,"Set Pasue Type Unkown!!\n");
        _arFbg[ucFbgId].u4PauseType = FBM_PAUSE_TYPE_UNKOWN;

        return FALSE;
    }

    _arFbg[ucFbgId].u4StepCmd = FBM_STEP_CMD_DEFALUT;


    LOG(1,"FbgId(%d) PauseType(%d)\n",ucFbgId,u4PauseType);

    return TRUE;
}

BOOL  FbmStep(UCHAR ucFbgId,UINT32 u4Theshold)
{
    UINT8 ucStcId;
    UINT8 ucAdecId;
    UINT8 ucVdecId;
    UINT32 u4SyncMode;

    if (ucFbgId >= FBG_MAX_NS)
    {
        LOG(0,"FbgId(%d) exception\n",ucFbgId);
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _arFbg[ucFbgId].u4StepCmd = FBM_STEP_CMD_SETTING;
    _arFbg[ucFbgId].u4StepCnt = 0;
    _arFbg[ucFbgId].u4StepThreshold = u4Theshold;

    ucStcId = _arFbg[ucFbgId].ucStcSrc;
    ucVdecId = _arFbg[ucFbgId].u1DecoderSrcId;
    ucAdecId = 0;
    u4SyncMode = 0;

    STC_SetSyncMode(ucStcId,ucAdecId,ucVdecId,u4SyncMode);

    LOG(1,"FbgId(%d) u4Theshold(%d) StcId-VdecId-AdecId-SyncMode [%d-%d-%d-%d]\n",
        ucFbgId,u4Theshold,ucStcId,ucVdecId,ucAdecId,u4SyncMode);


    FBM_MUTEX_UNLOCK(ucFbgId);

    return TRUE;
}

BOOL  FbmContinue(UCHAR ucFbgId)
{
    if (ucFbgId >= FBG_MAX_NS)
    {
        LOG(0,"FbgId(%d) exception\n",ucFbgId);
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _arFbg[ucFbgId].u4StepCmd = FBM_STEP_CMD_DEFALUT;
    _arFbg[ucFbgId].u4StepCnt = 0;
    _arFbg[ucFbgId].u4StepThreshold = 0;
    _arFbg[ucFbgId].fgSeqChgPause = FALSE;

    LOG(1,"Continue playback \n");

    FBM_MUTEX_UNLOCK(ucFbgId);
    return TRUE;

}

//-------------------------------------------------------------------------
/** FBM_QueryStatus
 *  Query FBM status
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_QueryStatus(UCHAR ucFbgId)
{
    UCHAR ucIdx;

    if ((ucFbgId < FBG_MAX_NS) &&
        (_arFbg[ucFbgId].ucFbgType != FBM_FBG_TYPE_UNKNOWN) &&
        (_arFbg[ucFbgId].ucFbgId != FBM_FBG_ID_UNKNOWN))
    {
        _FbgStatus(_arFbg[ucFbgId].ucFbgId);
        return;
    }

    for (ucIdx = 0; ucIdx < FBG_MAX_NS; ucIdx++)
    {
        if ((_arFbg[ucIdx].ucFbgType != FBM_FBG_TYPE_UNKNOWN) &&
            (_arFbg[ucIdx].ucFbgId != FBM_FBG_ID_UNKNOWN))
        {
            _FbgStatus(_arFbg[ucIdx].ucFbgId);
        }
    }

    _FBM_PoolStatus();
}

//-------------------------------------------------------------------------
/** FBM_RegCbFunc
 */
//-------------------------------------------------------------------------
void FBM_RegCbFunc(FBM_CB_FUNC_ENUM_T eFuncType, UPTR u4FuncPtr)
{
    if (eFuncType < FBM_CB_FUNC_NS)
    {
        if (u4FuncPtr == 0)
        {
            _arFbmCbFunc.au4CbFunc[eFuncType] = u4FuncPtr;
            _arFbmCbFunc.au4CbFuncCRC[eFuncType] = u4FuncPtr;
        }
        else
        {
            _arFbmCbFunc.au4CbFunc[eFuncType] = u4FuncPtr;
            _arFbmCbFunc.au4CbFuncCRC[eFuncType] = ~u4FuncPtr;
        }
    }
    else
    {
        ASSERT(0);
    }
}

//-------------------------------------------------------------------------
/** FBM_RegFbgCbFunc
 */
//-------------------------------------------------------------------------
void FBM_RegFbgCbFunc(UCHAR ucFbgId, FBM_CB_FUNC_ENUM_T eFuncType, UPTR u4FuncPtr, UINT32 u4Tag)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    if (eFuncType < FBM_CB_FUNC_NS)
    {
        if (u4FuncPtr == 0)
        {
            _arFbmCbFunc.aau4CbFunc[ucFbgId][eFuncType] = u4FuncPtr;
            _arFbmCbFunc.aau4CbFuncCRC[ucFbgId][eFuncType] = u4FuncPtr;
            _arFbmCbFunc.aau4CbFuncTag[ucFbgId][eFuncType] = u4Tag;
        }
        else
        {
            _arFbmCbFunc.aau4CbFunc[ucFbgId][eFuncType] = u4FuncPtr;
            _arFbmCbFunc.aau4CbFuncCRC[ucFbgId][eFuncType] = ~u4FuncPtr;
            _arFbmCbFunc.aau4CbFuncTag[ucFbgId][eFuncType] = u4Tag;
        }
    }
    else
    {
        ASSERT(0);
    }
}

//-------------------------------------------------------------------------
/** FBM_GetCbFuncTbl
 */
//-------------------------------------------------------------------------
FBM_CB_FUNC_T* FBM_GetCbFuncTbl(void)
{
    return (&_arFbmCbFunc);
}

//-------------------------------------------------------------------------
/** FBM_FbgChgNotify
 *  FBM notify (MPEG to VDP)
 *  @param  ucFbgId   FBG index.
 *  @param  ucEsId   ESindex.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_FbgChgNotify(UCHAR ucFbgId, UCHAR ucEsId)
{
    UCHAR ucPlayMode = FBM_FBG_MODE_NS;
    UCHAR ucPreFbgId = FBM_FBG_ID_UNKNOWN;

    VDEC_ES_INFO_KEEP_T *prVdecEsInfoKeep = NULL;

    // Note about usage
    // This function is called back by mpeg decode to indicate that
    // Frame buffer group ID is change.
    // It will by pass this notify to video plane driver

    if(ucFbgId != FBM_FBG_ID_UNKNOWN && (ucFbgId<FBG_MAX_NS))
    {
        _arFbg[ucFbgId].u1DecoderSrcId = ucEsId;

        // the same fbgid ,do not need notfiy b2r
        if (_arFbg[ucFbgId].fgMoreCreateFbg)
        {
            return;
        }
    }

    prVdecEsInfoKeep = _VDEC_GetEsInfoKeep(ucEsId);

    if (prVdecEsInfoKeep && prVdecEsInfoKeep->fgFrameToUser)
    {
        LOG(0, "czg fgFrameToUser is true\n");
        if(ucFbgId != FBM_FBG_ID_UNKNOWN && (ucFbgId<FBG_MAX_NS))
        {
            FBM_SetFrameBufferGlobalFlag(ucFbgId, FBM_FLAG_FB_NO_TIMEOUT);
            _arFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_DISP_READY;
        }
        return ;
    }
    if (FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        return;
    }

    ucPreFbgId = FBM_GetFbgByEs(ucEsId);

    FBM_GetPlayMode(ucFbgId,&ucPlayMode);
    if (ucPlayMode == FBM_FBG_NOTDISPLAY_MODE)
    {
        LOG(5, "FBM_FBG_NOTDISPLAY_MODE\n");
        _VdpCheckFbgReady(ucFbgId, ucEsId);
        return;
    }

    if (FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND], _arFbmCbFunc.au4CbFuncCRC[FBM_CB_FUNC_FBG_CHG_IND]))
    {
#if defined(CC_53XX_SWDMX_V2) && defined(CC_MT5365)
        VDP_CONF_T* prVdpConf = VDP_GetConf(VDP_1); // get which decoder is connect to vdp1
#endif

        ((FBM_FBG_CHG_IND_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND])(ucFbgId, ucEsId);

#if defined(CC_53XX_SWDMX_V2) && defined(CC_MT5365)
        if(prVdpConf != NULL)
        {
            if(ucFbgId == FBM_FBG_ID_UNKNOWN && prVdpConf->ucInputPort[0] == ucEsId)
            {
                UINT8 u1Idx;
                UINT8 u1TargetEsId = MAX_ES_NS;
                UINT8 u1FbgId = FBM_FBG_ID_UNKNOWN;
                UCHAR ucEs2FbgId = FBM_FBG_ID_UNKNOWN;

                for(u1Idx=0 ; u1Idx < MAX_ES_NS ; u1Idx++)
                {
                    ucEs2FbgId = FBM_GetFbgByEs(u1Idx);
                    if((ucEs2FbgId != FBM_FBG_ID_UNKNOWN) && (u1Idx != ucEsId))
                    {
                        u1FbgId = ucEs2FbgId;
                        u1TargetEsId = u1Idx;
                    }
                }

                if(u1FbgId != FBM_FBG_ID_UNKNOWN)
                {
                    ((FBM_FBG_CHG_IND_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND])(FBM_FBG_ID_UNKNOWN, u1TargetEsId);
                    VDP_SetInput(VDP_1,u1TargetEsId,0);
                    ((FBM_FBG_CHG_IND_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND])(u1FbgId, u1TargetEsId);
                }
            }
        }
#endif
    }
    else
    {
        ASSERT(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_FBG_CHG_IND] == 0);
    }

    if  ((ucFbgId != FBM_FBG_ID_UNKNOWN && (ucFbgId<FBG_MAX_NS)) && (FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.aau4CbFunc[ucFbgId][FBM_CB_FUNC_FBG_CHG_EX_IND],
            _arFbmCbFunc.aau4CbFuncCRC[ucFbgId][FBM_CB_FUNC_FBG_CHG_EX_IND])))
    {
        ((FBM_FB_READY_IND_FUNC_EX)_arFbmCbFunc.aau4CbFunc[ucFbgId][FBM_CB_FUNC_FBG_CHG_EX_IND])(
            _arFbmCbFunc.aau4CbFuncTag[ucFbgId][FBM_CB_FUNC_FBG_CHG_EX_IND],
            0);
    }
    if (ucFbgId == FBM_FBG_ID_UNKNOWN  && ucPreFbgId != FBM_FBG_ID_UNKNOWN)
    {
        if (_arFbg[ucPreFbgId].fgEnableNewSeamless)
        {
            _VDP_Prescale_Flush(_arFbg[ucPreFbgId].ucSeamlessRzId, TRUE);
            if(((_arFbg[ucPreFbgId].rSeqHdr.eSeamlessMode & SEAMLESS_TWO_RESIZER) == SEAMLESS_TWO_RESIZER)
               && (_arFbg[ucPreFbgId].ucSeamlessRzId2 != VDP_PRESCALE_RZ_ID_UNKNOWN))
            {
                _VDP_Prescale_Flush(_arFbg[ucPreFbgId].ucSeamlessRzId2,TRUE);
            }
        }
    }

    if (ucFbgId < FBG_MAX_NS)
    {
        VDEC_FbgChgHdlr(ucEsId,ucFbgId, _arFbg[ucFbgId].u4FbMemoryPool,
                        (_arFbg[ucFbgId].u4FbMemoryPool + _arFbg[ucFbgId].u4FbMemoryPoolSize));
    }
}

//-------------------------------------------------------------------------
/** FBM_PicStructChgNotify
 *  FBM notify (MPEG to VDP)
 *  @param  ucEsId   ESindex.
 *  @param  ucPicStruct   Frame/Field.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_PicStructChgNotify(UCHAR ucEsId, UCHAR ucPicStruct)
{
    // Note about usage
    // This function is called back by mpeg decode to indicate that
    // Picture structure is change. (frame/field)
    // It will by pass this notify to video plane driver

    if (FBM_CHECK_CB_FUNC_VERIFY(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_PICSTRUCT_CHG_IND], _arFbmCbFunc.au4CbFuncCRC[FBM_CB_FUNC_PICSTRUCT_CHG_IND]))
    {
        ((FBM_PICSTRUCT_CHG_IND_FUNC)_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_PICSTRUCT_CHG_IND])(ucEsId, ucPicStruct);
    }
    else
    {
        ASSERT(_arFbmCbFunc.au4CbFunc[FBM_CB_FUNC_PICSTRUCT_CHG_IND] == 0);
    }
}

//-------------------------------------------------------------------------
/** FBM_SetSyncStc
 *  Set AV Sync Info
 *  @param  ucFbgId   FBG index
 *  @param  ucMode   AV Sync Mode
 *  @param  ucStcId   AV Sync Source
  *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetSyncStc(UCHAR ucFbgId, UCHAR ucMode, UCHAR ucStcId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    ASSERT(ucMode < VID_SYNC_MODE_NS);
    //ASSERT(ucStcId < STC_SRC_NS);
    if (ucStcId < STC_SRC_NS)
    {
        _arFbg[ucFbgId].ucStcSrc = ucStcId;
    }
    else
    {
        LOG(0,"StcId maxStcid(%d %d)\n",ucStcId,STC_SRC_NS);
    }



#if defined(CC_B2R_EMULATION)
    _arFbg[ucFbgId].ucAvSyncMode = VID_SYNC_MODE_NONE;
#else
    _arFbg[ucFbgId].ucAvSyncMode = ucMode;
#endif
}


//-------------------------------------------------------------------------
/** FBM_GetSyncStc
 *  GetV Sync Info
 *  @param  ucFbgId   FBG index
 *  @param  pucMode   AV Sync Mode pointer
 *  @param  pucStcId   AV Sync Source pointer
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetSyncStc(UCHAR ucFbgId, UCHAR* pucMode, UCHAR* pucStcId)
{
    if ((pucMode == NULL) || (pucStcId == NULL))
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        *pucMode = VID_SYNC_MODE_NS;
        *pucStcId = STC_SRC_NS;
        return;
    }

    *pucMode = _arFbg[ucFbgId].ucAvSyncMode;
    *pucStcId = _arFbg[ucFbgId].ucStcSrc;
}

//-------------------------------------------------------------------------
/** FBM_GetSynMode
 *  GetV Sync Info
 *  @param  ucFbgId   FBG index
 *  @return SyncMode.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetSyncMode(UCHAR ucFbgId)
{
    UCHAR pucMode = VID_SYNC_MODE_NS;
    
    if (VERIFY_FBG(ucFbgId))
    {
        return VID_SYNC_MODE_NS;
    }

    pucMode = _arFbg[ucFbgId].ucAvSyncMode;
    return pucMode;
    
}

//-------------------------------------------------------------------------
/** FBM_SetAVSyncStatus
 *  Set AV Sync status (Repeat or Drop or ...)
 *  @param  ucFbgId   FBG index
 *  @param  u4AVSyncStatus   A/V sync mode
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetAVSyncStatus(UCHAR ucFbgId, UINT32 u4AVSyncStatus)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    _arFbg[ucFbgId].u4AvSyncStatus = u4AVSyncStatus;
}

//-------------------------------------------------------------------------
/** FBM_GetAVSyncStatus
 *  Get AV Sync status (Repeat or Drop or ...)
 *  @param  ucFbgId   FBG index
 *  @param  pu4AVSyncStatus   A/V sync mode
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetAVSyncStatus(UCHAR ucFbgId, UINT32* pu4AVSyncStatus)
{
    if (pu4AVSyncStatus == NULL)
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pu4AVSyncStatus = _arFbg[ucFbgId].u4AvSyncStatus;
}

//-------------------------------------------------------------------------
/** FBM_GetEmptyQCount
 *  Get Empty Queue Count
 *  @param  ucFbgId   FBG index
 *  @param  pucCount   Pointer of return results
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetEmptyQCount(UCHAR ucFbgId, UCHAR* pucCount)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pucCount = _arFbg[ucFbgId].rEmptyQ.ucCount;
}

UINT8 FBM_GetDecoderSrcId(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0xFF;
    }

    return _arFbg[ucFbgId].u1DecoderSrcId;
}

UINT8 FBM_GetFbgAppMode(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0xFF;
    }

    return _arFbg[ucFbgId].u1FbgAppMode;
}

//-------------------------------------------------------------------------
/** FBM_SetPlayMode
 *  Set Play Mode (DTV or MM or ...)
 *  @param  ucFbgId   FBG index
 *  @param  ucPlayMode   Play Mode
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetPlayMode(UCHAR ucFbgId, UCHAR ucPlayMode)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    _arFbg[ucFbgId].ucPlayMode = ucPlayMode;
}

void FBM_SetDecoderFB(UINT8 u1DecoderType,UINT8 u1NumOfFB)
{
    _fgSetDecoderFb = TRUE;
    _u1DecoderType = u1DecoderType;
    _u1NumOfFb = u1NumOfFB;
}

void FBM_SetColorMode(UINT8 u1ColorMode)
{
    if(u1ColorMode == FBM_CM_420 || u1ColorMode ==FBM_CM_422 )
    {
        LOG(1, "Color mode %d is selected.\n", u1ColorMode);
        _u1FbgColorMode = u1ColorMode;
    }
}

//-------------------------------------------------------------------------
/** FBM_GetPlayMode
 *  Get Play Mode (DTV or MM or ...)
 *  @param  ucFbgId   FBG index
 *  @param  pucPlayMode   Play Mode pointer
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetPlayMode(UCHAR ucFbgId, UCHAR* pucPlayMode)
{
    if ((pucPlayMode == NULL))
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pucPlayMode = _arFbg[ucFbgId].ucPlayMode;
}

//-------------------------------------------------------------------------
/** FBM_CheckPadding
 *  Check if pool memory corruption
 *  @param NONE
 *  @return NONE.
 */
//-------------------------------------------------------------------------

void FBM_CheckPadding(void)
{
#ifndef __KERNEL__
    UINT32 u4PoolIdx;
    UINT32 u4Idx;
    UPTR u4PadAddr;
    UINT32 u4PadLen;
    UPTR u4Addr;
    UINT32 u4Valid;

    u4Valid = 1;
    for (u4PoolIdx = 1 ; u4PoolIdx < (UINT32)FBM_POOL_TYPE_NS; u4PoolIdx++)
    {
        if ((_prPool[u4PoolIdx].u4Inherit == 0) &&
            (_prPool[u4PoolIdx].u4Addr > DRVCUST_OptGet(eFbmMemAddr)))
        {
            u4PadAddr = _prPool[u4PoolIdx].u4Addr - FBM_POOL_PADDING_SIZE;
            u4PadLen = FBM_POOL_PADDING_SIZE;

            for (u4Idx = 0; u4Idx < u4PadLen; u4Idx++)
            {
                u4Addr = u4PadAddr + u4Idx;

                if (*(UCHAR*)u4Addr != FBM_POOL_PADDING)
                {
                    LOG(1, "Pool(%s) memory corruption! addr=0x%x, val=0x%x\n", FBM_GetPoolName((UCHAR)u4PoolIdx), u4Addr, *(UCHAR*)u4Addr);

                    u4Valid = 0;

                    u4Idx = u4PadLen;
                }
            }
        }
    }

    if (u4Valid)
    {
        LOG(1, "No memory corruption\n");
    }
#else
    LOG(1, "NOT Support!\n");
#endif
}


//-------------------------------------------------------------------------
/** FBM_ResetFbChangeField
 *  Wait Frame buffer change field
 *  @param  ucFbgType   FBG type.
 *  @return lock status.
 */
//-------------------------------------------------------------------------
INT32 FBM_ResetFbChangeField(UCHAR ucFbgId)
{

    if (VERIFY_FBG(ucFbgId))
    {
        return OSR_INV_ARG;
    }

    if (x_sema_lock(_arFbg[ucFbgId].hChgFieldSema, X_SEMA_OPTION_NOWAIT) == OSR_OK)
    {
    }
    else
    {
    }

    return OSR_OK;
}


//-------------------------------------------------------------------------
/** FBM_WaitFbChangeField
 *  Wait Frame buffer change field
 *  @param  ucFbgType   FBG type.
 *  @param  u4Timeout   time to wait.
 *  @return lock status.
 */
//-------------------------------------------------------------------------
INT32 FBM_WaitFbChangeField(UCHAR ucFbgId, UINT32 u4Timeout)
{
    INT32 i4Ret;

    if (VERIFY_FBG(ucFbgId))
    {
        return OSR_INV_ARG;
    }

    i4Ret = x_sema_lock_timeout(_arFbg[ucFbgId].hChgFieldSema, u4Timeout);

    return i4Ret;
}


//-------------------------------------------------------------------------
/** FBM_FbChangeField
 *  Frame buffer change field
 *  @param  ucFbgType   FBG type.
 *  @return unlock status.
 */
//-------------------------------------------------------------------------
void FBM_FbChangeField(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if ((ucFbgId == FBM_FBG_ID_UNKNOWN) ||
        (_arFbg[ucFbgId].hChgFieldSema == 0))
    {
        return;
    }

    if (_arFbg[ucFbgId].hChgFieldSema)
    {
        VERIFY(x_sema_unlock(_arFbg[ucFbgId].hChgFieldSema) == OSR_OK);
    }
}


//-------------------------------------------------------------------------
/** FBM_SetFbNextFieldPlayBackNs
 *  Set frame buffer next field playback number
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  ucPlayBackNs   playback number.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFbNextFieldPlayBackNs(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucPlayBackNs)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    _arFbg[ucFbgId].aucChgFldPlayBackNs[ucFbId] = ucPlayBackNs;

}


//-------------------------------------------------------------------------
/** FBM_GetFbNextFieldPlayBackNs
 *  Get frame buffer next field playback number
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return playback number.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFbNextFieldPlayBackNs(UCHAR ucFbgId, UCHAR ucFbId)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return 0;
    }

    return _arFbg[ucFbgId].aucChgFldPlayBackNs[ucFbId];
}

UINT32 FBM_GetVDecMemSize(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0;
    }
    return _arFbg[ucFbgId].u4FbMemoryPoolSize;
}

UPTR  FBM_GetMiscMemAddr(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0;
    }

    return _arFbg[ucFbgId].au4MiscTblStartAddr;

    // default size FBM_WORK_BUF_VP9_MISC_TBL_SIZE

}

UINT32 FBM_GetRunningVdecMemSize(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0;
    }
    if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264)
    {
        return _arFbg[ucFbgId].u4FbMemoryPoolSize;
    }
    else
    {
        return _arFbg[ucFbgId].ucFbNs * ( (_arFbg[ucFbgId].u4FbWidth * _arFbg[ucFbgId].u4FbHeight *3) >>1) + FBM_WORK_BUF_SIZE;
    }
}

BOOL FBM_ChkFbgCreateFromInst(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }

#ifdef CC_HWCOMP_UT
    return TRUE;
#else
    return _arFbg[ucFbgId].fgCreateFromInst;
#endif
}
#ifdef FBM_CS_LOG
void FBM_FlushFbCsLog(void)
{
    _FbmCsLog(24, 0, _u4EQHandle);

}
#endif

#if defined(CC_MT5890) && defined(CC_FBM_FOUR_INST_SUPPORT)
//For Video Texture mode(backgroud capture) dst addr
UPTR FBM_GetCaptureDstAddr(void)
{
    FBM_POOL_T* prFbmPool = NULL;
    prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG4_C);

    if (prFbmPool->u4Addr && (prFbmPool->u4Size >= FBM_FBG_1080HD_H * FBM_FBG_1080HD_V * 4 * 2))
    {
        if (prFbmPool->u4Size < FBM_FBG_1080HD_H * FBM_FBG_1080HD_V * 4 * 2) //*4 ARGB8888 *2 TWO instance
        {
            LOG(1, "MPEG4_C size not enough");
        }
        return prFbmPool->u4Addr;  //ARGB8888
    }

    return (UPTR)NULL;
}
#else
UPTR FBM_GetCaptureDstAddr(void)
{
    LOG(1, "Not implement while NOT defined(CC_MT5890) && defined(CC_FBM_FOUR_INST_SUPPORT).\n");
    return (UPTR)NULL;
}

#endif

#if 1
void FBM_SetCodecInfo(UCHAR ucFbgId, ENUM_CODEC_INFO_T eCodecInfo)
{
    _arFbg[ucFbgId].eCodecType = eCodecInfo;
}

ENUM_CODEC_INFO_T FBM_GetCodecInfo(UCHAR ucFbgId)
{
    ENUM_CODEC_INFO_T eCodecInfo;
    if (VERIFY_FBG(ucFbgId))
    {
        return E_VDEC_CODEC_UNKNOWN;
    }
    eCodecInfo=_arFbg[ucFbgId].eCodecType;
    return  eCodecInfo;
}
BOOL FBM_GetCodecResolution(UCHAR ucFbgId,FBM_CODEC_RESOLUTION_T* rResolution)
{
    FBM_SEQ_HDR_T *prSeqHdr;

    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }
    prSeqHdr = &_arFbg[ucFbgId].rSeqHdr;

    if((_arFbg[ucFbgId].eSeamlessMode& POST_PROCESS_DISPLAY_ROTATE)
       && !(_arFbg[ucFbgId].eSeamlessMode& SEAMLESS_BY_RESIZER))
    {
        if(prSeqHdr->u4DispDirection == 90 || prSeqHdr->u4DispDirection == 270)
        {
            rResolution->u4Width  = prSeqHdr->u4CropHeight ? prSeqHdr->u4CropHeight : prSeqHdr->u4SourceHeight;
            rResolution->u4Height = prSeqHdr->u4CropWidth  ? prSeqHdr->u4CropWidth : prSeqHdr->u4SourceWidth;
        }
        else
        {
            rResolution->u4Width  = prSeqHdr->u4CropWidth  ? prSeqHdr->u4CropWidth : prSeqHdr->u4SourceWidth;
            rResolution->u4Height = prSeqHdr->u4CropHeight ? prSeqHdr->u4CropHeight : prSeqHdr->u4SourceHeight;
        }
        rResolution->u4OrgWidth  = prSeqHdr->u4CropWidth  ? prSeqHdr->u4CropWidth : prSeqHdr->u4SourceWidth;
        rResolution->u4OrgHeight = prSeqHdr->u4CropHeight ? prSeqHdr->u4CropHeight : prSeqHdr->u4SourceHeight;
    }
    else
    {
        rResolution->u4Width = prSeqHdr->u4ResizeWidth;
        rResolution->u4Height = prSeqHdr->u4ResizeHeight;
        rResolution->u4OrgWidth = prSeqHdr->u4SourceWidth;
        rResolution->u4OrgHeight = prSeqHdr->u4SourceHeight;
    }

    LOG(2,"u4Width %d u4Height %d u4OrgWidth %d u4OrgHeight %d\n",
        rResolution->u4Width,
        rResolution->u4Height,
        rResolution->u4OrgWidth,
        rResolution->u4OrgHeight);

    return TRUE;
}

#endif

UCHAR FBM_GetFbgByEs(UCHAR ucEsId)
{
    UCHAR ucFbgId = FBM_FBG_ID_UNKNOWN;
    UCHAR ucFbgIdx;

    do
    {
        if(ucEsId >= MAX_ES_NS)
        {
            break;
        }

        for(ucFbgIdx = 0; ucFbgIdx < FBG_MAX_NS; ucFbgIdx ++)
        {
            if(VERIFY_FBG(ucFbgIdx))
            {
                continue;
            }

            if(_arFbg[ucFbgIdx].u1DecoderSrcId == ucEsId)
            {
                ucFbgId = ucFbgIdx;
                break;
            }
        }
    }
    while(0);

    return ucFbgId;
}

#ifdef CC_B2R_RES_SUPPORT
B2R_HW_RES_T* _FBM_B2rResGetObj(UINT8 u1HwId)
{
    UINT8 i;
    B2R_HW_RES_T *ptRet = NULL;

    for (i = 0; i < B2R_HW_MAX_ID; i++)
    {
        if (_arB2rHwRes[i].t_cfg.u1HwId == u1HwId)
        {
            ptRet = &_arB2rHwRes[i];
            break;
        }
    }

    return ptRet;
}

void _FBM_B2rResPrmInit(B2R_HW_RES_T* pt_this)
{
    do
    {
        if(!pt_this)
        {
            break;
        }

        pt_this->t_prm.b_used  = FALSE;
        pt_this->t_prm.u1FbgId = FBG_MAX_NS;
        pt_this->t_prm.u1VdpId = VDP_MAX;
    }
    while(0);
}

void _FBM_B2rResInit(void)
{
    UINT8 i;
    B2R_HW_RES_T* pt_this = NULL;

    for(i = 0; i < B2R_HW_MAX_ID; i ++)
    {
        pt_this = &_arB2rHwRes[i];
        if(pt_this)
        {
            pt_this->t_cfg.u1HwId   = i;
            pt_this->t_cfg.u1GrpId  = i / 2;
            pt_this->t_cfg.u1AsscId = B2R_HW_MAX_ID - (i + 1);
            pt_this->t_cfg.u4MaxRes = FHD_TIMING;

            _FBM_B2rResPrmInit(pt_this);
        }
    }

    _arB2rHwRes[2].t_cfg.u4MaxRes = UHD_TIMING;
}

BOOL _FBM_B2rResInUsing(UCHAR ucFbgId,
                        UINT8* pu1B2rId)
{
    BOOL b_used = FALSE;
    UINT8 i;
    B2R_HW_RES_T* pt_this = NULL;

    do
    {
        if(ucFbgId >= FBG_MAX_NS || !pu1B2rId)
        {
            break;
        }

        if(VERIFY_FBG(ucFbgId))
        {
            break;
        }


        for(i = 0; i < B2R_HW_MAX_ID; i ++)
        {
            pt_this = _FBM_B2rResGetObj(i);
            if(pt_this &&
               pt_this->t_prm.u1FbgId == ucFbgId &&
               pt_this->t_prm.b_used)
            {
                *pu1B2rId = pt_this->t_cfg.u1HwId;
                b_used = TRUE;
                break;
            }
        }

        LOG(6,"FbgId(%d) B2rId(%d) use status(%d)!\n", ucFbgId,*pu1B2rId, b_used);
    }
    while(0);

    return b_used;
}

UINT8 FBM_B2rResGetPeerId(UINT8 u1HwId)
{
    UINT8 u1GrpId;
    UINT8 u1RetId = B2R_HW_MAX_ID;
    UINT8 i;
    B2R_HW_RES_T* pt_this = NULL;

    do
    {
        if(u1HwId >= B2R_HW_MAX_ID)
        {
            break;
        }

        pt_this = _FBM_B2rResGetObj(u1HwId);
        if(!pt_this)
        {
            break;
        }

        u1GrpId = pt_this->t_cfg.u1GrpId;
        for(i = 0; i < B2R_HW_MAX_ID; i++)
        {
            pt_this = _FBM_B2rResGetObj(i);
            if(pt_this &&
               pt_this->t_cfg.u1GrpId == u1GrpId &&
               pt_this->t_cfg.u1HwId != u1HwId)
            {
                u1RetId = i;
                break;
            }
        }
    }
    while(0);

    return u1RetId;
}

UINT8 FBM_B2rResGrpSelect(B2R_IPT_INFO_T* pt_src)
{
    UINT8 u1GrpId = GRP_MAX;

    do
    {
        if(!pt_src)
        {
            break;
        }

        if(pt_src->t_vd.eCodec == VDEC_JPEG)
        {
            u1GrpId = GRP_1;
            break;
        }
        else if(pt_src->t_vd.fgUfoEn ||
                pt_src->t_vd.eCodec == VDEC_H265 ||
                pt_src->t_vd.u1PixDepth == 10 ||
                pt_src->t_vd.u4Resolution > FHD_TIMING)
        {
            u1GrpId = GRP_2;
            break;
        }

        u1GrpId = GRP_1;
    }
    while(0);

    return u1GrpId;
}

BOOL FBM_B2rResHwIsReady(B2R_IPT_INFO_T* pt_src,
                         UINT8 u1HwId)
{
    BOOL b_chosen = FALSE;
    UINT8 u1AsscId;
    UINT8 u1PeerId;
    B2R_HW_RES_T* pt_this = NULL;
    B2R_HW_RES_T* pt_assc = NULL;
    B2R_HW_RES_T* pt_peer = NULL;

    do
    {
        if(u1HwId >= B2R_HW_MAX_ID || !pt_src)
        {
            LOG(0,"Invalid hwid(%d) or pt_src == NULL\n",u1HwId);
            break;
        }

        pt_this = _FBM_B2rResGetObj(u1HwId);
        if(!pt_this)
        {
            LOG(0,"Can not get object with hwid(%d)\n",u1HwId);
            break;
        }

        if((pt_src->t_vd.eCodec == VDEC_JPEG) && (u1HwId != 0 )&&(pt_src->t_vd.u4Resolution > pt_this->t_cfg.u4MaxRes) )
        {
            LOG(0,"4K Photo can only use B2R_ID0\n",u1HwId);
            break;
        }

        if((pt_src->t_vd.u4Resolution > pt_this->t_cfg.u4MaxRes)&&(pt_src->t_vd.eCodec != VDEC_JPEG))
        {
            LOG(0,"Capbility exceed: now(%d) > cap(%d)\n",pt_src->t_vd.u4Resolution,pt_this->t_cfg.u4MaxRes);
            break;
        }

        if(pt_this->t_prm.b_used)
        {
            LOG(1,"The hwid(%d) is used!!!\n",u1HwId);
            break;
        }

        u1AsscId = pt_this->t_cfg.u1AsscId;
        pt_assc = _FBM_B2rResGetObj(u1AsscId);
        if(pt_assc &&
           pt_assc->t_prm.b_used)
        {
            LOG(1,"Conflict hwid(%d) with now(%d) is used!!!\n",u1AsscId,u1HwId);
            break;
        }

        u1PeerId = FBM_B2rResGetPeerId(u1HwId);
        pt_peer = _FBM_B2rResGetObj(u1PeerId);
        if(pt_peer &&
           pt_peer->t_prm.b_used &&
           (pt_peer->t_src.eCodec == pt_src->t_vd.eCodec &&
            (pt_peer->t_src.u1PixDepth == 10 ||
             pt_src->t_vd.u1PixDepth == 10)))
        {
            LOG(1,"The same group(%d %d) has conflict!!!\n",u1PeerId,u1HwId);
            break;
        }

        b_chosen = TRUE;
    }
    while(0);

    return b_chosen;
}

UINT8 FBM_B2rResAlloc(B2R_IPT_INFO_T* pt_src)
{
    UINT8 u1HwId;
    UINT8 u1B2rHwId = B2R_HW_MAX_ID;
    UINT8 u1GrpId;
    INT8  i;

    do
    {
        if(!pt_src)
        {
            LOG(0,"The pt_src == NULL\n");
            break;
        }

        u1GrpId = FBM_B2rResGrpSelect(pt_src);

        LOG(1,"B2r Res GroupId(%d) with Vdpid(%d)!\n", u1GrpId,pt_src->u1VdpId);

        switch(pt_src->u1VdpId)
        {
            case VDP_MAIN:
            {
                for(i = 0; i < 2 ; i++)
                {
                    u1HwId = u1GrpId*2 + i;
                    if(FBM_B2rResHwIsReady(pt_src, u1HwId))
                    {
                        u1B2rHwId = u1HwId;
                        break;
                    }
                }
                break;
            }

            case VDP_SUB:
            {
                for(i = 1; i >= 0 ; i--)
                {
                    u1HwId = u1GrpId*2 + i;
                    if(FBM_B2rResHwIsReady(pt_src, u1HwId))
                    {
                        u1B2rHwId = u1HwId;
                        break;
                    }
                }
                break;
            }

            default:
                LOG(0,"Invalid VDPID(%d)\n",pt_src->u1VdpId);
                break;
        }
    }
    while(0);

    return u1B2rHwId;
}

void FBM_B2rResHdrVdpId(UCHAR ucFbgId,
                        B2R_IPT_INFO_T* pt_src)
{
    UINT8 i = 0;
    UCHAR ucMVdpId = VDP_MAX;
    UCHAR ucSVdpId = VDP_MAX;
    BOOL  b_MainUsed = FALSE;
    BOOL  b_SubUsed  = FALSE;
    B2R_HW_RES_T* pt_this = NULL;
    INT32         i4Ret     = B2R_OK;

    do
    {
        if(ucFbgId >= FBG_MAX_NS || !pt_src)
        {
            LOG(1,"The fbgid(%d) is invalid or pt_src = NULL!\n",ucFbgId);
            break;
        }

        i4Ret = B2R_MainSubStatus(&ucMVdpId, &ucSVdpId);
        if(i4Ret != B2R_OK)
        {
            LOG(1,"Call B2R_MainSubStatus returns(%d)!\n",i4Ret);
            return;
        }

        if(ucMVdpId != VDP_MAX)
        {
            for(i = 0; i < B2R_HW_MAX_ID; i ++)
            {
                pt_this = _FBM_B2rResGetObj(i);
                if(pt_this && (pt_this->t_prm.u1VdpId == ucMVdpId))
                {
                    b_MainUsed = TRUE;
                    break;
                }
            }

            if(!b_MainUsed &&
               (pt_src->u1VdpId == 0xFF ||
                pt_src->u1VdpId == VDP_MAIN))
            {
                pt_src->u1VdpId = (UINT8)ucMVdpId;
                LOG(1,"Main use VDP_MAIN!\n");
                break;
            }
        }

        if(ucSVdpId != VDP_MAX)
        {
            for(i = 0; i < B2R_HW_MAX_ID; i ++)
            {
                pt_this = _FBM_B2rResGetObj(i);
                if(pt_this && (pt_this->t_prm.u1VdpId == ucSVdpId))
                {
                    b_SubUsed = TRUE;
                    break;
                }
            }

            if(!b_SubUsed &&
               (pt_src->u1VdpId == 0xFF ||
                pt_src->u1VdpId == VDP_SUB))
            {
                pt_src->u1VdpId = (UINT8)ucSVdpId;
                LOG(1,"Sub use VDP_SUB!\n");
                break;
            }
        }

        if(pt_src->u1VdpId == 0xFF ||
           (pt_src->u1VdpId != VDP_MAIN &&
            pt_src->u1VdpId != VDP_SUB))
        {
            pt_src->u1VdpId = VDP_MAIN;

            LOG(1,"Default use VDP_MAIN!\n");
            break;
        }

    }
    while(0);
}

void _FBM_B2rResGetSrcInfo(UCHAR ucFbgId,
                           B2R_IPT_INFO_T* pt_src,
                           FBM_CREATE_FBG_PAR_T* ptPar)
{
    VDEC_ES_INFO_T*      ptVdecEsInfo = NULL;
    VDEC_ES_INFO_KEEP_T* ptVdecEsInfoKeep = NULL;

    do
    {
        if(VERIFY_FBG(ucFbgId))
        {
            break;
        }

        if(!pt_src || !ptPar)
        {
            break;
        }

        ptVdecEsInfo = _VDEC_GetEsInfo(_arFbg[ucFbgId].u1DecoderSrcId);
        if(!ptVdecEsInfo)
        {
            break;
        }

        ptVdecEsInfoKeep = _VDEC_GetEsInfoKeep(_arFbg[ucFbgId].u1DecoderSrcId);
        if(!ptVdecEsInfoKeep)
        {
            break;
        }

        pt_src->t_vd.eCodec = ptVdecEsInfoKeep->eCurFMT;
        pt_src->t_vd.fgUfoEn = ptVdecEsInfo->fgEnableUFO;
        pt_src->t_vd.u1PixDepth = (UINT8)(ptVdecEsInfo->u4BitDepth);
        pt_src->t_vd.u4Resolution = ptVdecEsInfo->u2OrgHSize * ptVdecEsInfo->u2OrgVSize;

        LOG(1,"eCodec(%d), UfoEn(%d), Depth(%d), Res(%d)!\n", pt_src->t_vd.eCodec,
            pt_src->t_vd.fgUfoEn, pt_src->t_vd.u1PixDepth, pt_src->t_vd.u4Resolution);
    }
    while(0);
}

void FBM_B2rResNotifyClient(UCHAR ucFbgId,
                            B2R_CHG_INFO_T*  pt_change)
{

    FBM_CB_FUNC_T* pt_cb_func = NULL;
    VDEC_ES_INFO_KEEP_T* ptVdecEsInfoKeep;

    do
    {
        if(VERIFY_FBG(ucFbgId) || pt_change == NULL)
        {
            LOG(0,"Invalid argument!\n");
            break;
        }

        pt_cb_func = FBM_GetCbFuncTbl();
        if(!pt_cb_func)
        {
            LOG(1,"pt_cb_func = NULL!\n");
            break;
        }

        if (FBM_CHECK_CB_FUNC_VERIFY(pt_cb_func->au4CbFunc[FBM_CB_FUNC_B2R_HW_CHG_CB],
                                     pt_cb_func->au4CbFuncCRC[FBM_CB_FUNC_B2R_HW_CHG_CB]))
        {
            LOG(1,"Send Hw change Notify with vdp(%d) and change(%d)!\n",
                pt_change->u1VdpId,pt_change->b_change);
            ((FBM_B2R_RES_CHG_FUNC)pt_cb_func->au4CbFunc[FBM_CB_FUNC_B2R_HW_CHG_CB])(ucFbgId, pt_change);
        }

        ptVdecEsInfoKeep = _VDEC_GetEsInfoKeep(_arFbg[ucFbgId].u1DecoderSrcId);
        if(!ptVdecEsInfoKeep)
        {
            LOG(1,"Es info Null!\n");
            break;
        }

        if (ptVdecEsInfoKeep->pfnVdecSetParam &&
            ((pt_change->u1B2rId == 2) ||
             (pt_change->u1B2rId == 3)))
        {
            ptVdecEsInfoKeep->pfnVdecSetParam(_arFbg[ucFbgId].u1DecoderSrcId, (UINT32)VDEC_BLK_MODE, 0, 0, 0);
        }

    }
    while(0);
}

UINT8 FBM_B2rResIdAccess(UCHAR ucFbgId,
                         UINT32 u4Mask,
                         B2R_IPT_INFO_T* pt_src)
{
    UINT8 u1B2rId = B2R_HW_MAX_ID;
    B2R_HW_RES_T* pt_this = NULL;
    B2R_CHG_INFO_T  t_change;

    if(VERIFY_FBG(ucFbgId))
    {
        LOG(0,"Unvalid fbgid(%d)!\n",ucFbgId);
        return u1B2rId;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    do
    {

        if(!pt_src &&
           u4Mask & RES_RW)
        {
            LOG(0,"It is RW mode but the src == NULL!\n");
            break;
        }

        /*use fbgid to check b2r resource is in use or not*/
        if(_FBM_B2rResInUsing(ucFbgId, &u1B2rId))
        {
            LOG(9,"The fbgid(%d) with b2rid(%d) is in using now!",ucFbgId,u1B2rId);
            break;
        }

        if(u4Mask & RES_RW)
        {
            FBM_B2rResHdrVdpId(ucFbgId, pt_src);

            LOG(3,"B2r Res get VdpId(%d)!\n", pt_src->u1VdpId);

            u1B2rId = FBM_B2rResAlloc(pt_src);

            LOG(3,"Alloc B2r(%d) hardware resource!\n", u1B2rId);

            pt_this = _FBM_B2rResGetObj(u1B2rId);
            if(pt_this)
            {
                pt_this->t_prm.u1FbgId = (UINT8)ucFbgId;
                pt_this->t_prm.b_used  = TRUE;
                pt_this->t_prm.u1VdpId = pt_src->u1VdpId;

                x_memcpy(&pt_this->t_src, &pt_src->t_vd, sizeof(B2R_VD_INFO_T));

                x_memset(&t_change,0,sizeof(B2R_CHG_INFO_T));

                t_change.u1VdpId = pt_this->t_prm.u1VdpId;
                t_change.u1B2rId = u1B2rId;
                t_change.b_change = TRUE;

                LOG(0,"Alloc B2r(%d) OK with fbgid(%d) and vdpid(%d)!\n", u1B2rId,ucFbgId,pt_src->u1VdpId);

                FBM_B2rResNotifyClient(ucFbgId, &t_change);
            }

        }


    }
    while(0);

    FBM_MUTEX_UNLOCK(ucFbgId);

    return u1B2rId;
}

UINT8 FBM_B2rResIdRelease(UCHAR ucFbgId)
{
    UINT8 u1B2rId = B2R_HW_MAX_ID;
    B2R_HW_RES_T* pt_this = NULL;
    B2R_CHG_INFO_T  t_change;

    do
    {
        if(ucFbgId >= FBG_MAX_NS)
        {
            break;
        }

        if(VERIFY_FBG(ucFbgId))
        {
            break;
        }

        if(_FBM_B2rResInUsing(ucFbgId, &u1B2rId))
        {
            pt_this = _FBM_B2rResGetObj(u1B2rId);
            if(pt_this != NULL)
            {
                x_memset(&t_change,0,sizeof(B2R_CHG_INFO_T));

                t_change.u1VdpId = pt_this->t_prm.u1VdpId;
                t_change.b_change = TRUE;

                _FBM_B2rResPrmInit(pt_this);

                FBM_B2rResNotifyClient(ucFbgId, &t_change);
                LOG(1,"Release B2r(%d) hardware resource!\n", u1B2rId);
            }
        }

    }
    while(0);

    return u1B2rId;
}



#endif


static VOID _FBM_B2RDumpPendingQ(UCHAR ucFbgId)
{
    B2R_NPTV_PENDING_Q* pt_pending_q = NULL;
    UCHAR               ucIdx        = 0;

    if(ucFbgId >= FBG_MAX_NS)
    {
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    if(VERIFY_FBG(ucFbgId))
    {
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    pt_pending_q = &(_arFbg[ucFbgId].t_pending_q);

    for(ucIdx = 0; ucIdx <PEND_NS; ucIdx++)
    {
        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_PENDINGQ) == FBM_ENABLE_LOG_PENDINGQ)
        {
            if (pt_pending_q->atPendingQ[ucIdx].fgPending)
            {
                LOG(1,"Pending[%d/%d]:SOC = %d / width = %d / height = %d .\n",
                    ucIdx,pt_pending_q->ucQSize,pt_pending_q->atPendingQ[ucIdx].u4ItemSOC,
                    pt_pending_q->atPendingQ[ucIdx].u4PendingWdith,
                    pt_pending_q->atPendingQ[ucIdx].u4PendingHeight);
            }
        }
    }

    return;
}

/*This API should not use FBM mutex, because it already in FBM mutex protect scope, it run in VDEC thread*/
VOID FBM_B2RNTPVSavePendingItem(UCHAR ucFbgId,B2R_NPTV_PENDING_ITEM t_pending_item)
{
    UCHAR               ucQsize      = 0;
    B2R_NPTV_PENDING_Q* pt_pending_q = NULL;

    if(ucFbgId >= FBG_MAX_NS)
    {
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    if(VERIFY_FBG(ucFbgId))
    {
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    pt_pending_q = &(_arFbg[ucFbgId].t_pending_q);

    _FBM_B2RDumpPendingQ(ucFbgId);

    ucQsize = pt_pending_q->ucQSize;

    LOG(6,"The pending-Q size = %d at %d.\n",pt_pending_q->ucQSize,__LINE__);

    if(ucQsize >= PEND_NS)
    {
        LOG(6,"Pending-Q is not enough.\n");
        return;
    }

    x_memcpy(&(pt_pending_q->atPendingQ[ucQsize]),&t_pending_item,sizeof(B2R_NPTV_PENDING_ITEM));

    pt_pending_q->ucQSize++;

    LOG(6,"The pending-Q size = %d at %d.\n",pt_pending_q->ucQSize,__LINE__);

    _FBM_B2RDumpPendingQ(ucFbgId);

    return;
}

/*This API should not use FBM mutex, because it already in FBM mutex protect scope, it run in VDEC thread*/
VOID FBM_B2RNTPVGetPendingQSize(UCHAR ucFbgId,UCHAR* pucQsize)
{
    B2R_NPTV_PENDING_Q*     pt_pending_q = NULL;

    if(pucQsize == NULL)
    {
        LOG(0,"pucQsize == NULL.\n");
        return;
    }

    if(ucFbgId >= FBG_MAX_NS )
    {
        *pucQsize = 0;
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    if(VERIFY_FBG(ucFbgId))
    {
        *pucQsize = 0;
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    pt_pending_q = &(_arFbg[ucFbgId].t_pending_q);

    *pucQsize = pt_pending_q->ucQSize;

    return;
}

/*This API should use FBM mutex, because it not in FBM mutex protect scope, it run in Vsync thread*/
VOID FBM_B2RNTPVRemovePendingItem(UCHAR ucFbgId,B2R_NPTV_PENDING_ITEM* pt_pending_item)
{
    UCHAR                   ucQsize         = 0;
    UCHAR                   ucIdx           = 0;
    B2R_NPTV_PENDING_Q*     pt_pending_q = NULL;

    if(pt_pending_item == NULL)
    {
        LOG(0,"pt_pending_item == NULL.\n");
        return;
    }

    if(ucFbgId >= FBG_MAX_NS )
    {
        pt_pending_item->fgPending = FALSE;
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    if(VERIFY_FBG(ucFbgId))
    {
        pt_pending_item->fgPending = FALSE;
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    do
    {

        pt_pending_q = &(_arFbg[ucFbgId].t_pending_q);

        ucQsize = pt_pending_q->ucQSize;

        LOG(7,"The pending-Q size = %d at %d.\n",pt_pending_q->ucQSize,__LINE__);

        if(ucQsize == 0)
        {
            pt_pending_item->fgPending = FALSE;
            LOG(7,"Pending-Q is empty now.\n");
            break;;
        }

        _FBM_B2RDumpPendingQ(ucFbgId);

        x_memcpy(pt_pending_item,&(pt_pending_q->atPendingQ[0]),sizeof(B2R_NPTV_PENDING_ITEM));

        if(pt_pending_item->fgPending != TRUE)
        {
            LOG(0,"Error:::No pending to get and size(%d) != 0.\n",ucQsize);
        }
        else
        {
            LOG(3,"The pending info: (%d %d %d).\n",
                pt_pending_item->fgPending,
                pt_pending_item->u4PendingWdith,
                pt_pending_item->u4PendingHeight);
        }

        /*move fore-head*/
        for (ucIdx = 1; ucIdx < ucQsize; ucIdx ++)
        {
            x_memcpy(&(pt_pending_q->atPendingQ[ucIdx - 1]),
                     &(pt_pending_q->atPendingQ[ucIdx]),
                     sizeof(B2R_NPTV_PENDING_ITEM));
        }

        pt_pending_q->ucQSize--;

        LOG(7,"The pending-Q size = %d at %d.\n",pt_pending_q->ucQSize,__LINE__);

        /*reset the last one*/
        x_memset(&(pt_pending_q->atPendingQ[pt_pending_q->ucQSize]),0,sizeof(B2R_NPTV_PENDING_ITEM));

        _FBM_B2RDumpPendingQ(ucFbgId);

    }
    while(0);

    FBM_MUTEX_UNLOCK(ucFbgId);

    return;
}
/*This API should use FBM mutex, because it not in FBM mutex protect scope, it run in Vsync thread*/
VOID FBM_B2RNTPVGetFirstPendingInfo(UCHAR ucFbgId,B2R_NPTV_PENDING_ITEM* pt_pending_item)
{
    UCHAR                   ucQsize         = 0;
    B2R_NPTV_PENDING_Q*     pt_pending_q = NULL;

    if(pt_pending_item == NULL)
    {
        LOG(0,"pt_pending_item == NULL.\n");
        return;
    }

    if(ucFbgId >= FBG_MAX_NS )
    {
        pt_pending_item->fgPending = FALSE;
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    if(VERIFY_FBG(ucFbgId))
    {
        pt_pending_item->fgPending = FALSE;
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    do
    {

        pt_pending_q = &(_arFbg[ucFbgId].t_pending_q);

        _FBM_B2RDumpPendingQ(ucFbgId);

        ucQsize = pt_pending_q->ucQSize;

        LOG(3,"The pending-Q size = %d at %d.\n",pt_pending_q->ucQSize,__LINE__);

        if(ucQsize == 0)
        {
            pt_pending_item->fgPending = FALSE;
            LOG(3,"Pending-Q is empty now.\n");
            break;;
        }

        x_memcpy(pt_pending_item,&(pt_pending_q->atPendingQ[0]),sizeof(B2R_NPTV_PENDING_ITEM));

        if(pt_pending_item->fgPending != TRUE)
        {
            LOG(0,"Error:::No pending to get and size(%d) != 0.\n",ucQsize);
        }
        else
        {
            LOG(3,"The pending info: (%d %d %d).\n",
                pt_pending_item->fgPending,
                pt_pending_item->u4PendingWdith,
                pt_pending_item->u4PendingHeight);
        }

        _FBM_B2RDumpPendingQ(ucFbgId);

    }
    while(0);

    FBM_MUTEX_UNLOCK(ucFbgId);

    return;
}

VOID FBM_B2RNTPVClrPendingQ(UCHAR ucFbgId)
{
    if(ucFbgId >= FBG_MAX_NS )
    {
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    if(VERIFY_FBG(ucFbgId))
    {
        LOG(3,"FBGID invalid (%d).\n",ucFbgId);
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    x_memset(&(_arFbg[ucFbgId].t_pending_q),0,sizeof(B2R_NPTV_PENDING_Q));

    FBM_MUTEX_UNLOCK(ucFbgId);

    return;
}


VOID FBM_ActiveMajorFrameBuffer(UCHAR ucFbgId)
{
    UCHAR ucFbIdx = 0;

    if(VERIFY_FBG(ucFbgId))
    {
        return;
    }

    LOG(0,"%s\n",__FUNCTION__);
    _arFbg[ucFbgId].eFbIdType  = FBM_FBID_TYPE_MAJOR;
    _arFbg[ucFbgId].ucFbNs     = _arFbg[ucFbgId].ucFbNsMajor;
    _arFbg[ucFbgId].ucFbNsBase = _arFbg[ucFbgId].ucFbNsMajorBase;
    FBM_MEMSET((VOID *)&_arFbg[ucFbgId].rEmptyQ, 0, sizeof(_arFbg[ucFbgId].rEmptyQ));
    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, 0) == OSR_OK);

    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;

    if (_arFbg[ucFbgId].fgFirstCreateFbg)
    {
        for (ucFbIdx = _arFbg[ucFbgId].ucFbNsMajorBase; ucFbIdx < _arFbg[ucFbgId].ucFbNsMajor; ucFbIdx++)
        {
            if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx %d overflow!!\n",ucFbIdx);
                break;
            }
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(1,"Major:Pre put emptyQ(%d-%d)\n",ucFbgId,ucFbIdx);
            }
            _FBM_PutFrameBufferToEmptyQ(ucFbgId,ucFbIdx);
        }

        _arFbg[ucFbgId].fgFirstCreateFbg = FALSE;

    }
    else
    {
        for (ucFbIdx = _arFbg[ucFbgId].ucFbNsMajorBase; ucFbIdx < _arFbg[ucFbgId].ucFbNsMajor; ucFbIdx++)
        {
            if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx %d overflow!!\n",ucFbIdx);
                break;
            }
            _arFbg[ucFbgId].afgWaitUse[ucFbIdx] = FALSE;

        }

        for (ucFbIdx = _arFbg[ucFbgId].ucFbNsMinorBase; ucFbIdx < _arFbg[ucFbgId].ucFbNsMinor; ucFbIdx++)
        {
            if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx %d overflow!!\n",ucFbIdx);
                break;
            }
            if (_arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_EMPTY)
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                {
                    LOG(1,"Major:Pre put emptyQ(%d-%d)\n",ucFbgId,ucFbIdx);
                }
                _FBM_PutFrameBufferToEmptyQ(ucFbgId,ucFbIdx);
            }

        }
    }
    return;

}
VOID FBM_ActiveMinorFrameBuffer(UCHAR ucFbgId)
{
    UCHAR ucFbIdx = 0;

    if(VERIFY_FBG(ucFbgId))
    {
        return;
    }

    LOG(0,"%s\n",__FUNCTION__);
    _arFbg[ucFbgId].eFbIdType  = FBM_FBID_TYPE_MINOR;
    _arFbg[ucFbgId].ucFbNs     = _arFbg[ucFbgId].ucFbNsMinor;
    _arFbg[ucFbgId].ucFbNsBase = _arFbg[ucFbgId].ucFbNsMinorBase;
    FBM_MEMSET((VOID *)&_arFbg[ucFbgId].rEmptyQ, 0, sizeof(_arFbg[ucFbgId].rEmptyQ));
    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, 0) == OSR_OK);

    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;

    if (_arFbg[ucFbgId].fgFirstCreateFbg)
    {
        for (ucFbIdx = _arFbg[ucFbgId].ucFbNsMinorBase; ucFbIdx < _arFbg[ucFbgId].ucFbNsMinor; ucFbIdx++)
        {
            if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx %d overflow!!\n",ucFbIdx);
                break;
            }
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(1,"Minor:Pre put emptyQ(%d-%d)\n",ucFbgId,ucFbIdx);
            }
            _FBM_PutFrameBufferToEmptyQ(ucFbgId,ucFbIdx);
        }

        _arFbg[ucFbgId].fgFirstCreateFbg = FALSE;

    }
    else
    {
        for (ucFbIdx = _arFbg[ucFbgId].ucFbNsMajorBase; ucFbIdx < _arFbg[ucFbgId].ucFbNsMajor; ucFbIdx++)
        {
            if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx %d overflow!!\n",ucFbIdx);
                break;
            }

            if (_arFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_EMPTY)
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                {
                    LOG(1,"Minor:Pre put emptyQ(%d-%d)\n",ucFbgId,ucFbIdx);
                }
                _FBM_PutFrameBufferToEmptyQ(ucFbgId,ucFbIdx);
            }

        }
    }
    return;

}


VOID FBM_ActiveMinorMv(UCHAR ucFbgId)
{
    if(VERIFY_FBG(ucFbgId))
    {
        return;
    }

    LOG(0,"%s\n",__FUNCTION__);
    FBM_CfgMvbuffer(ucFbgId,(_arFbg[ucFbgId].u4TargetSize>>1),_arFbg[ucFbgId].ucMinorMvBufNs);
    _arFbg[ucFbgId].ucMvBufNs = _arFbg[ucFbgId].ucMinorMvBufNs;

    return;
}
VOID FBM_ActiveMajorMv(UCHAR ucFbgId)
{
    if(VERIFY_FBG(ucFbgId))
    {
        return;
    }
    LOG(0,"%s\n",__FUNCTION__);
    FBM_CfgMvbuffer(ucFbgId,_arFbg[ucFbgId].u4TargetSize,_arFbg[ucFbgId].ucMajorMvBufNs);

    _arFbg[ucFbgId].ucMvBufNs = _arFbg[ucFbgId].ucMajorMvBufNs;

    return;
}

static UINT32 FBM_CfgMvbuffer(UCHAR ucFbgId,UINT32 u4YSize,UCHAR ucMvBufNs)
{
    UINT32 u4MvSize;
    UPTR u4Addr = 0;
    UPTR u4FbStartPoolYAddr = 0,u4FbEndPoolYAddr = 0;
    UCHAR u4FbIdx;

    if(VERIFY_FBG(ucFbgId))
    {
        return FBM_RETURN_ERROR;
    }

    _arFbg[ucFbgId].u4WorkBufSize = 0;

    if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264)
    {
        if ((_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_1080HD_RR) &&
            (_arFbg[ucFbgId].eResolutionChangeMode == FBM_RESOLUTION_CHANGE_MODE_NONE))
        {
            u4MvSize = u4YSize >> 1;
        }
        else
        {
            u4MvSize = u4YSize >> 2;
        }

        if (ucMvBufNs > FBM_MAX_FB_NS_PER_GROUP-1)
        {
            ASSERT(ucMvBufNs <= FBM_MAX_FB_NS_PER_GROUP-1);
            return FBM_RETURN_ERROR;
        }
        if (_arFbg[ucFbgId].u4MvStartAddr)
        {
            u4Addr = _arFbg[ucFbgId].u4MvStartAddr; // From prepareMvBuffer got it.

            if ((u4Addr >= _arFbg[ucFbgId].u4FbStartPoolYAddr)
                && (u4Addr < _arFbg[ucFbgId].u4FbEndPoolYAddr))
            {
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
            }
            else if((u4Addr >= _arFbg[ucFbgId].u4FbStartPool2YAddr) &&
                    (u4Addr < _arFbg[ucFbgId].u4FbEndPool2YAddr))
            {
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPool2YAddr;
            }
        }
        else
        {
            LOG(0,"Error MV buffer not allocated\n");
            return FBM_RETURN_ERROR;
        }

        for (u4FbIdx = 0;
             ((u4FbIdx < ucMvBufNs)&&(u4FbIdx < (FBM_MAX_FB_NS_PER_GROUP-1))); u4FbIdx++)
        {

            u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_B2R_H_PITCH); // H264 mv start addr need 64 align

            _arFbg[ucFbgId].au4AddrMv[u4FbIdx] = u4Addr;

            FBM_Check_AddrIsOverLap(u4Addr,u4MvSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
            _arFbg[ucFbgId].u4WorkBufSize += u4MvSize;
            u4Addr += u4MvSize;
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(1,"H264:AddrMv[%d] 0x%lx\n",u4FbIdx,_arFbg[ucFbgId].au4AddrMv[u4FbIdx]);
            }

        }

    }
    else if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265)||
             (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
    {
        u4MvSize = u4YSize >> 4;

        if (ucMvBufNs>FBM_MAX_FB_NS_PER_GROUP-1)
        {
            ASSERT(ucMvBufNs<=FBM_MAX_FB_NS_PER_GROUP-1);
            return FBM_RETURN_ERROR;
        }

        if (_arFbg[ucFbgId].u4MvStartAddr)
        {
            u4Addr = _arFbg[ucFbgId].u4MvStartAddr; // From prepareMvBuffer got it.

            if ((u4Addr >= _arFbg[ucFbgId].u4FbStartPoolYAddr)
                && (u4Addr < _arFbg[ucFbgId].u4FbEndPoolYAddr))
            {
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
            }
            else if((u4Addr >= _arFbg[ucFbgId].u4FbStartPool2YAddr) &&
                    (u4Addr < _arFbg[ucFbgId].u4FbEndPool2YAddr))
            {
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPool2YAddr;
            }
        }
        else
        {
            LOG(0,"Error MV buffer not allocated\n");
            return FBM_RETURN_ERROR;
        }

        for (u4FbIdx = 0;
             ((u4FbIdx < ucMvBufNs)&&(u4FbIdx < (FBM_MAX_FB_NS_PER_GROUP-1))); u4FbIdx++)
        {
            u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_VDEC_WORKING_ALIGNMENT);
            _arFbg[ucFbgId].au4AddrMv[u4FbIdx] = u4Addr; //YAddr End Storge MV buffer

            FBM_Check_AddrIsOverLap(u4Addr,u4MvSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)
            _arFbg[ucFbgId].u4WorkBufSize += u4MvSize;
            u4Addr += u4MvSize;
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(1,"H265:AddrMv[%d] 0x%lx\n",u4FbIdx,_arFbg[ucFbgId].au4AddrMv[u4FbIdx]);
            }
        }

    }
    return FBM_RETURN_OK;
}

VOID FBM_MemReset(VOID *pAddr, UINT32 u4Data, UINT32 u4Size)
{
    FBM_GDMA_MEMSET((VOID*)pAddr,u4Data,u4Size);
    return;
}

static UINT32 FBM_Alloc4KJpegPool(UCHAR ucFbgId,UINT32 u4Ysize, UINT32 u4Csize,FBM_CREATE_FBG_PAR_T *prPar)
{
    UINT8 u1FbCount = 4;

    if (prPar && (prPar->u1RefNum != 0))
    {
        u1FbCount = prPar->u1RefNum;
    }
    
    if(_arFbg[ucFbgId].fg10Bit)
    {
        u4Ysize = FBM_ALIGN_MASK(((u4Ysize*5)>>2), FBM_FMG_Y_ALIGMENT);
        u4Csize = FBM_ALIGN_MASK(((u4Csize*5)>>2), FBM_FMG_Y_ALIGMENT);
    }
    
    if(u1FbCount <= 2)
    {
#if defined(CC_ENABLE_CMA_SUPPORT)
        CMA_POOL_T*prcmaPool;
#else
        FBM_POOL_T* prFbmPool = NULL;
#endif


        // Query decoder Buffer for photo,use other MPEG pool to display
        if (FBM_GetPanelModel() >= 3)
        {
#if defined(CC_ENABLE_CMA_SUPPORT)
            prcmaPool = CMA_GetPool((UINT8)FBM_POOL_TYPE_MPEG);
            if (prcmaPool)
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prcmaPool->u4PhyAlignAddr+ prcmaPool->u4Size) - FBM_FBG_TYPE_4K2K_1FB_SIZE;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_TYPE_4K2K_1FB_C_SIZE;
                LOG(0,"Use cma MPEG\n");
            }
            if(prcmaPool && (prcmaPool->u4Size > FBM_100M_SIZE))
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prcmaPool->u4PhyAlignAddr+ prcmaPool->u4Size) - FBM_FBG_TYPE_4K2K_1FB_SIZE*2;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_TYPE_4K2K_1FB_C_SIZE*2;
                _arFbg[ucFbgId].fg8KMpeg = TRUE;
                LOG(0,"8K mpeg %d\n",__LINE__);
            }
            else
            {
                prcmaPool = CMA_GetPool((UINT8)FBM_POOL_TYPE_MPEG2);

                if (prcmaPool)
                {
                    _arFbg[ucFbgId].u4FbMemoryPool2 = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_TYPE_4K2K_1FB_SIZE;
                    _arFbg[ucFbgId].u4FbMemoryPool2C = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_TYPE_4K2K_1FB_C_SIZE;
                    LOG(0,"Use cma MPEG\n");
                }
            }
            if (_arFbg[ucFbgId].fg8KMpeg)
            {
                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + (u4Csize << 1);
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = (u4Ysize + u4Csize) << 1;
                LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] PoolSize(%d)\n",
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
                LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
            }
            else
            {
                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + u4Csize;

                _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
                _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C + u4Csize;
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = (u4Ysize + u4Csize) << 1;

                LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
                    _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
                LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
            }
        }
#else
        #if defined(CC_MT5893)
            prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG);
            if (prFbmPool)
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prFbmPool->u4Addr + prFbmPool->u4Size) - (u4Ysize + u4Csize);
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prFbmPool->u4Addr + prFbmPool->u4Size) - u4Csize;
                LOG(0,"Use MPEG\n");
            }
            if(prFbmPool && (prFbmPool->u4Size > FBM_100M_SIZE))
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prFbmPool->u4Addr+ prFbmPool->u4Size) - ((u4Ysize + u4Csize) << 1);
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prFbmPool->u4Addr + prFbmPool->u4Size) - (u4Csize << 1);
                _arFbg[ucFbgId].fg8KMpeg = TRUE;
                LOG(0,"8K mpeg %d\n",__LINE__);
            }
            else
            {
                prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG2);

                if (prFbmPool)
                {
                    _arFbg[ucFbgId].u4FbMemoryPool2 = (prFbmPool->u4Addr + prFbmPool->u4Size) - (u4Ysize + u4Csize);
                    _arFbg[ucFbgId].u4FbMemoryPool2C = (prFbmPool->u4Addr + prFbmPool->u4Size) - u4Csize;
                    LOG(0,"Use MPEG\n");
                }
            }

            if (_arFbg[ucFbgId].fg8KMpeg)
            {
                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + (u4Csize << 1);
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = (u4Ysize + u4Csize) << 1;
                LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] PoolSize(%d)\n",
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
                LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
            }
            else
            {
                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + u4Csize;

                _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
                _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C + u4Csize;
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = (u4Ysize + u4Csize) << 1;

                LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
                    _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
                LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
            }
    	}
    #else
            //For M5 use the end address of MPEG2C for photo
            prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG2_C);
            if (prFbmPool)
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prFbmPool->u4Addr + prFbmPool->u4Size) - ((u4Ysize + u4Csize) << 1) - 4*FBM_8K_SIZE;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prFbmPool->u4Addr + prFbmPool->u4Size) - u4Csize - (u4Ysize + u4Csize) - 3*FBM_8K_SIZE;
                _arFbg[ucFbgId].u4FbMemoryPool2 = (prFbmPool->u4Addr + prFbmPool->u4Size) - (u4Ysize + u4Csize) - 2*FBM_8K_SIZE;
                _arFbg[ucFbgId].u4FbMemoryPool2C = (prFbmPool->u4Addr + prFbmPool->u4Size) - u4Csize - FBM_8K_SIZE;
                _arFbg[ucFbgId].fg8KMpeg = FALSE;

                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + u4Csize + FBM_8K_SIZE;

                _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
                _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C + u4Csize + FBM_8K_SIZE;
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = ((u4Ysize + u4Csize) << 1) + 4*FBM_8K_SIZE;

                LOG(0,"%s Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",__FUNCTION__,
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
                    _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
            }
        }
    #endif
#endif
    }
    else
    {
        UINT32 u4PoolSize = 0;
        MPEG_POOL_INFO_T rMpegPoolInfo;
        UINT32 u4MpegTotalYSize;
        UINT32 u4MpegTotalCSize;

        FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
        u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
        _arFbg[ucFbgId].u4FbMemoryPool  = rMpegPoolInfo.u4FbMemoryPool;
        _arFbg[ucFbgId].u4FbMemoryPoolC = rMpegPoolInfo.u4FbMemoryPoolC;
        u4MpegTotalYSize                 = rMpegPoolInfo.u4MpegTotalYSize;
        u4MpegTotalCSize                 = rMpegPoolInfo.u4MpegTotalCSize;

        if(u4MpegTotalYSize > FBM_100M_SIZE)
        {
            _arFbg[ucFbgId].fg8KMpeg = TRUE;
            _arFbg[ucFbgId].u4FbMemoryPoolC = _arFbg[ucFbgId].u4FbMemoryPool + FBM_FBG_TYPE_4K2K_JPEG_SIZE*2 - FBM_FBG_TYPE_4K2K_JPEG_C_SIZE*2;
            _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
            _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
            _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
            _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbStartPoolCAddr + FBM_FBG_TYPE_4K2K_JPEG_C_SIZE*2;
            if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool) || (!_arFbg[ucFbgId].u4FbMemoryPoolC))
            {
                LOG(0,"alloc jpeg buffer 1 fail\n");
                return FBM_RETURN_ERROR;
            }
            _arFbg[ucFbgId].u4FbMemoryPoolSize = (_arFbg[ucFbgId].u4FbEndPoolYAddr - _arFbg[ucFbgId].u4FbStartPoolYAddr) + \
                                                 (_arFbg[ucFbgId].u4FbEndPoolCAddr - _arFbg[ucFbgId].u4FbStartPoolCAddr);
            LOG(1,"8K mpeg Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] PoolSize(%d)\n",
                _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                _arFbg[ucFbgId].u4FbMemoryPoolSize);
            LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
        }
        else
        {
            _arFbg[ucFbgId].u4FbMemoryPoolC = _arFbg[ucFbgId].u4FbMemoryPool + FBM_FBG_TYPE_4K2K_JPEG_SIZE - FBM_FBG_TYPE_4K2K_JPEG_C_SIZE;
            _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
            _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
            _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
            _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbStartPoolCAddr + FBM_FBG_TYPE_4K2K_JPEG_C_SIZE;

            if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool) || (!_arFbg[ucFbgId].u4FbMemoryPoolC))
            {
                LOG(0,"alloc jpeg buffer 1 fail\n");
                return FBM_RETURN_ERROR;
            }


            _arFbg[ucFbgId].u4FbMemoryPoolSize = (_arFbg[ucFbgId].u4FbEndPoolYAddr - _arFbg[ucFbgId].u4FbStartPoolYAddr) + \
                                                 (_arFbg[ucFbgId].u4FbEndPoolCAddr - _arFbg[ucFbgId].u4FbStartPoolCAddr);


            //in order to not distinguish linux (4 FB) and android (2 FB) ,now using max (5 FB) case
            FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
            u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
            _arFbg[ucFbgId].u4FbMemoryPool2  = rMpegPoolInfo.u4FbMemoryPool;
            _arFbg[ucFbgId].u4FbMemoryPool2C = rMpegPoolInfo.u4FbMemoryPoolC;
            u4MpegTotalYSize                 = rMpegPoolInfo.u4MpegTotalYSize;
            u4MpegTotalCSize                 = rMpegPoolInfo.u4MpegTotalCSize;

            _arFbg[ucFbgId].u4FbMemoryPool2C =  _arFbg[ucFbgId].u4FbMemoryPool2 + FBM_FBG_TYPE_4K2K_JPEG_SIZE - FBM_FBG_TYPE_4K2K_JPEG_C_SIZE;
            _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
            _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C;
            _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
            _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbStartPool2CAddr + FBM_FBG_TYPE_4K2K_JPEG_C_SIZE;

            if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool2) || (!_arFbg[ucFbgId].u4FbMemoryPool2C))
            {
                _FBM_PoolRelease(_arFbg[ucFbgId].u4FbMemoryPool);
                LOG(0,"alloc jpeg buffer 2 fail\n");
                return FBM_RETURN_ERROR;
            }


            _arFbg[ucFbgId].u4FbMemoryPoolSize += (_arFbg[ucFbgId].u4FbEndPool2YAddr - _arFbg[ucFbgId].u4FbStartPool2YAddr) + \
                                                  (_arFbg[ucFbgId].u4FbEndPool2CAddr - _arFbg[ucFbgId].u4FbStartPool2CAddr);

            LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
                _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
                _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
                _arFbg[ucFbgId].u4FbMemoryPoolSize);
            LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
        }

    }
    return FBM_RETURN_OK;
}
static UINT32 FBM_Alloc8KJpegPool(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar)
{
    UINT8 u1FbCount = 4;
    if (prPar && (prPar->u1RefNum != 0))
    {
        u1FbCount = prPar->u1RefNum;
    }
    if(u1FbCount <= 2)
    {
#if defined(CC_ENABLE_CMA_SUPPORT)
        CMA_POOL_T*prcmaPool;
#else
        FBM_POOL_T* prFbmPool = NULL;
#endif
        if (FBM_GetPanelModel() >= 3)
        {
#if defined(CC_ENABLE_CMA_SUPPORT)
            prcmaPool = CMA_GetPool((UINT8)FBM_POOL_TYPE_MPEG);
            if (prcmaPool)
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prcmaPool->u4PhyAlignAddr+ prcmaPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*2 - 0x4000;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE - 0x2000;
                LOG(0,"Use cma MPEG\n");
            }
            if(prcmaPool && (prcmaPool->u4Size > FBM_100M_SIZE))
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prcmaPool->u4PhyAlignAddr+ prcmaPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*4 - 0x8000;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*2 - 0x4000;
                _arFbg[ucFbgId].fg8KMpeg = TRUE;
                LOG(0,"8K mpeg %d\n",__LINE__);
            }
            else
            {
                prcmaPool = CMA_GetPool((UINT8)FBM_POOL_TYPE_MPEG2);
                if (prcmaPool)
                {
                    _arFbg[ucFbgId].u4FbMemoryPool2 = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*2 - 0x4000;
                    _arFbg[ucFbgId].u4FbMemoryPool2C = (prcmaPool->u4PhyAlignAddr + prcmaPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE - 0x2000;
                    LOG(0,"Use cma MPEG\n");
                }
            }
#else
            prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG);
            if (prFbmPool)
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prFbmPool->u4Addr + prFbmPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*2 - 0x4000;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prFbmPool->u4Addr + prFbmPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE - 0x2000;
                LOG(0,"Use MPEG\n");
            }
            if(prFbmPool && (prFbmPool->u4Size > FBM_100M_SIZE))
            {
                _arFbg[ucFbgId].u4FbMemoryPool = (prFbmPool->u4Addr+ prFbmPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*4 - 0x8000;
                _arFbg[ucFbgId].u4FbMemoryPoolC = (prFbmPool->u4Addr + prFbmPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*2 - 0x4000;
                _arFbg[ucFbgId].fg8KMpeg = TRUE;
                LOG(0,"8K mpeg %d\n",__LINE__);
            }
            else
            {
                prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG2);
                if (prFbmPool)
                {
                    _arFbg[ucFbgId].u4FbMemoryPool2 = (prFbmPool->u4Addr + prFbmPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE*2 - 0x4000;
                    _arFbg[ucFbgId].u4FbMemoryPool2C = (prFbmPool->u4Addr + prFbmPool->u4Size) - FBM_FBG_JPEG_8K_Y_SIZE - 0x2000;
                    LOG(0,"Use MPEG\n");
                }
            }
#endif
            if (_arFbg[ucFbgId].fg8KMpeg)
            {
                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + FBM_FBG_JPEG_8K_Y_SIZE*2 + 0x4000;
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = FBM_FBG_JPEG_8K_Y_SIZE*4 + 0x8000;
                LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] PoolSize(%d)\n",
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
                LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
            }
            else
            {
                _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
                _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
                _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + FBM_FBG_JPEG_8K_Y_SIZE + 0x2000;
                _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
                _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
                _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C + FBM_FBG_JPEG_8K_Y_SIZE + 0x2000;
                _arFbg[ucFbgId].u4FbMemoryPoolSize  = FBM_FBG_JPEG_8K_Y_SIZE *4 + 0x8000;
                LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
                    _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                    _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                    _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
                    _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
                    _arFbg[ucFbgId].u4FbMemoryPoolSize);
                LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
            }
        }
    }
    else
    {
        UINT32 u4PoolSize = 0;
        MPEG_POOL_INFO_T rMpegPoolInfo;
        UINT32 u4MpegTotalYSize;
        UINT32 u4MpegTotalCSize;
        FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
        u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
        _arFbg[ucFbgId].u4FbMemoryPool  = rMpegPoolInfo.u4FbMemoryPool;
        _arFbg[ucFbgId].u4FbMemoryPoolC = rMpegPoolInfo.u4FbMemoryPoolC;
        u4MpegTotalYSize                 = rMpegPoolInfo.u4MpegTotalYSize;
        u4MpegTotalCSize                 = rMpegPoolInfo.u4MpegTotalCSize;
        _arFbg[ucFbgId].u4FbMemoryPoolC = _arFbg[ucFbgId].u4FbMemoryPool + FBM_FBG_JPEG_8K_Y_SIZE*2 + 0x4000;
        _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
        _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
        _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
        _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbStartPoolCAddr + FBM_FBG_JPEG_8K_Y_SIZE*2 + 0x4000;
        if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool) || (!_arFbg[ucFbgId].u4FbMemoryPoolC))
        {
            LOG(0,"alloc jpeg buffer 1 fail\n");
            return FBM_RETURN_ERROR;
        }
        _arFbg[ucFbgId].u4FbMemoryPoolSize = (_arFbg[ucFbgId].u4FbEndPoolYAddr - _arFbg[ucFbgId].u4FbStartPoolYAddr) + \
                                             (_arFbg[ucFbgId].u4FbEndPoolCAddr - _arFbg[ucFbgId].u4FbStartPoolCAddr);
        FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
        u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
        _arFbg[ucFbgId].u4FbMemoryPool2  = rMpegPoolInfo.u4FbMemoryPool;
        _arFbg[ucFbgId].u4FbMemoryPool2C = rMpegPoolInfo.u4FbMemoryPoolC;
        u4MpegTotalYSize                 = rMpegPoolInfo.u4MpegTotalYSize;
        u4MpegTotalCSize                 = rMpegPoolInfo.u4MpegTotalCSize;
        _arFbg[ucFbgId].u4FbMemoryPool2C =  _arFbg[ucFbgId].u4FbMemoryPool2 + FBM_FBG_JPEG_8K_Y_SIZE*2 + 0x4000;
        _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
        _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C;
        _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
        _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbStartPool2CAddr + FBM_FBG_JPEG_8K_Y_SIZE*2 + 0x4000;
        if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool2) || (!_arFbg[ucFbgId].u4FbMemoryPool2C))
        {
            _FBM_PoolRelease(_arFbg[ucFbgId].u4FbMemoryPool);
            LOG(0,"alloc jpeg buffer 2 fail\n");
            return FBM_RETURN_ERROR;
        }
        _arFbg[ucFbgId].u4FbMemoryPoolSize += (_arFbg[ucFbgId].u4FbEndPool2YAddr - _arFbg[ucFbgId].u4FbStartPool2YAddr) + \
                                              (_arFbg[ucFbgId].u4FbEndPool2CAddr - _arFbg[ucFbgId].u4FbStartPool2CAddr);
        LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
            _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
            _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
            _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
            _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
            _arFbg[ucFbgId].u4FbMemoryPoolSize);
        LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
    }
    return FBM_RETURN_OK;
}

static UINT32 FBM_Alloc4K8KVideoPool(UCHAR ucFbgId, FBM_CREATE_FBG_PAR_T *prPar)
{
    MPEG_POOL_INFO_T rMpegPoolInfo;
    UINT32 u4MpegTotalYSize;
    UINT32 u4MpegTotalCSize;
    UINT32 u4PoolSize;

    FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
    if(prPar && (prPar->u1Fps >= 45) && !(prPar->fgThumbnailMode))
    {
        LOG(1,"fps (%d) is over 45\n",prPar->u1Fps);
#if (defined(CC_MT5886)) && !defined(CC_BYPASS_MJC)
        vDrvMJCSetBypassVariable(BYP_MJC_BY_FBM,1);
        vDrvMJCBypassOnOff(1);
        _arFbg[ucFbgId].bByPassMJC = TRUE;
        rMpegPoolInfo.fgUseDynBuf = TRUE;
#endif
    }
    u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
    _arFbg[ucFbgId].u4FbMemoryPool   = rMpegPoolInfo.u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbMemoryPoolC  = rMpegPoolInfo.u4FbMemoryPoolC;
    u4MpegTotalYSize                 = rMpegPoolInfo.u4MpegTotalYSize;
    u4MpegTotalCSize                 = rMpegPoolInfo.u4MpegTotalCSize;

    if (u4MpegTotalYSize > FBM_100M_SIZE)
    {
        _arFbg[ucFbgId].fg8KMpeg = TRUE;
    }
    _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPool + u4MpegTotalYSize ;
    _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
    _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + u4MpegTotalCSize;

    if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool) || (!_arFbg[ucFbgId].u4FbMemoryPoolC))
    {
        LOG(0,"alloc 4K buffer 1 fail\n");
        return FBM_RETURN_ERROR;
    }

    _arFbg[ucFbgId].u4FbMemoryPoolSize = u4MpegTotalYSize + u4MpegTotalCSize;
    if ((_arFbg[ucFbgId].fg8KMpeg == TRUE)&&(_arFbg[ucFbgId].ucFbgType != FBM_FBG_TYPE_8K))
    {
        LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx]PoolSize(%d)\n",
            _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
            _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
            _arFbg[ucFbgId].u4FbMemoryPoolSize);
        LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
        return FBM_RETURN_OK;
    }

    FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
    if(prPar && (prPar->u1Fps >= 45) && !(prPar->fgThumbnailMode))
    {
        LOG(1,"fps (%d) is over 45\n",prPar->u1Fps);
#if (defined(CC_MT5886)) && !defined(CC_BYPASS_MJC)
        vDrvMJCSetBypassVariable(BYP_MJC_BY_FBM,1);
        vDrvMJCBypassOnOff(1);
        _arFbg[ucFbgId].bByPassMJC = TRUE;
        rMpegPoolInfo.fgUseDynBuf = TRUE;
#endif
    }
    u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
    _arFbg[ucFbgId].u4FbMemoryPool2   = rMpegPoolInfo.u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbMemoryPool2C  = rMpegPoolInfo.u4FbMemoryPoolC;
    u4MpegTotalYSize                 = rMpegPoolInfo.u4MpegTotalYSize;
    u4MpegTotalCSize                 = rMpegPoolInfo.u4MpegTotalCSize;

    _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
    _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2 + u4MpegTotalYSize ;
    _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
    _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C + u4MpegTotalCSize;

    if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool2) || (!_arFbg[ucFbgId].u4FbMemoryPool2C))
    {
        _FBM_PoolRelease(_arFbg[ucFbgId].u4FbMemoryPool);
        LOG(0,"alloc 4K buffer 2 fail\n");
        return FBM_RETURN_ERROR;
    }

    _arFbg[ucFbgId].u4FbMemoryPoolSize += u4MpegTotalYSize + u4MpegTotalCSize;

    LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
        _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
        _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
        _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
        _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
        _arFbg[ucFbgId].u4FbMemoryPoolSize);
    LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);

    return FBM_RETURN_OK;
}


static UINT32 FBM_Alloc2KVideoAndJpegPool(UCHAR ucFbgId, FBM_CREATE_FBG_PAR_T *prPar)
{
    MPEG_POOL_INFO_T rMpegPoolInfo;
    UINT32 u4MpegTotalYSize;
    UINT32 u4MpegTotalCSize;

    FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));
    _arFbg[ucFbgId].u4FbMemoryPoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
    _arFbg[ucFbgId].u4FbMemoryPool    = rMpegPoolInfo.u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbMemoryPoolC   = rMpegPoolInfo.u4FbMemoryPoolC;
    u4MpegTotalYSize                  = rMpegPoolInfo.u4MpegTotalYSize;
    u4MpegTotalCSize                  = rMpegPoolInfo.u4MpegTotalCSize;

    _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbEndPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool + u4MpegTotalYSize ;
    _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
    _arFbg[ucFbgId].u4FbEndPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC + u4MpegTotalCSize;

    if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)
    {
        u4MpegTotalCSize = 0;
        _arFbg[ucFbgId].u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbEndPoolCAddr = 0;
    }


    if ((_arFbg[ucFbgId].u4FbMemoryPoolSize == 0) ||
        (!_arFbg[ucFbgId].u4FbMemoryPool) || (!_arFbg[ucFbgId].u4FbMemoryPoolC))
    {
        LOG(0,"alloc 2K buffer fail\n");
        return FBM_RETURN_ERROR;
    }

    _arFbg[ucFbgId].u4FbMemoryPoolSize = u4MpegTotalYSize + u4MpegTotalCSize;

    LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
        _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
        _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
        _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
        _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
        _arFbg[ucFbgId].u4FbMemoryPoolSize);
    LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);
    return FBM_RETURN_OK;
}

static UINT32 FBM_AllocFakePool(UCHAR ucFbgId, FBM_CREATE_FBG_PAR_T *prPar)
{
    UINT32 u4MpegTotalYSize;
    UINT32 u4MpegTotalCSize;
    
    _arFbg[ucFbgId].u4FbMemoryPool   = 0x0 + FBM_8K_SIZE;
    _arFbg[ucFbgId].u4FbMemoryPoolC  = _arFbg[ucFbgId].u4FbMemoryPool + 500*1024*1024;
    u4MpegTotalYSize                 = 500*1024*1024;
    u4MpegTotalCSize                 = 250*1024*1024;

    _arFbg[ucFbgId].u4FbMemoryPoolSize = u4MpegTotalYSize + u4MpegTotalCSize;
    
    _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPool + u4MpegTotalYSize ;
    _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
    _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + u4MpegTotalCSize;

    LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
        _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
        _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
        _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
        _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
        _arFbg[ucFbgId].u4FbMemoryPoolSize);
    LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);

    return FBM_RETURN_OK;
}

static VOID FBM_ChangeResolution(UCHAR ucFbgId,UINT32 u4HSize,UINT32 u4VSize,BOOL fgFirstCreate)
{
    CRIT_STATE_T _rEmptyQState;

    _arFbg[ucFbgId].fgFirstCreateFbg = fgFirstCreate;


    if (FBM_RESOLUTION_CHANGE_MODE_SEAMLESS == _arFbg[ucFbgId].eResolutionChangeMode)
    {
        if((u4HSize * u4VSize) <= (_arFbg[ucFbgId].u4TargetSize >>1))
        {
            if ((FBM_FBID_TYPE_MINOR != _arFbg[ucFbgId].eFbIdType) || fgFirstCreate)
            {
                _rEmptyQState = x_crit_start();
                FBM_ActiveMinorFrameBuffer(ucFbgId);
                FBM_ActiveMinorMv(ucFbgId);
                x_crit_end(_rEmptyQState);
            }
            else
            {
                LOG(0,"Current Minor type \n");
            }
        }
        else
        {
            if ((FBM_FBID_TYPE_MAJOR != _arFbg[ucFbgId].eFbIdType) || fgFirstCreate)
            {
                _rEmptyQState = x_crit_start();
                FBM_ActiveMajorFrameBuffer(ucFbgId);
                FBM_ActiveMajorMv(ucFbgId);
                x_crit_end(_rEmptyQState);
            }
            else
            {
                LOG(0,"Current Major type\n");
            }
        }
    }
}

static UINT32 FBM_CalcMaxFBNum(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,UINT32 u4HSize,UINT32 u4VSize)
{
    UCHAR ucFbCount = 0;
    
    if(prPar && prPar->fgStillImage)
    {
        ucFbCount = 1;
        LOG(2,"Still image case,Fb count %d\n",ucFbCount);
        return ucFbCount;
    }
    
    switch(_arFbg[ucFbgId].u4VDecFmt)
    {
        case FBM_VDEC_H264:
        case FBM_VDEC_H265:
            break;
        case FBM_VDEC_VP9:
            _arFbg[ucFbgId].ucMvBufNs = 2;
            #if 0
            if (u4HSize*u4VSize > FBM_FBG_TYPE_2048_Y_SIZE)
            {
                ucFbCount = 7;
            }
            else
            {
                ucFbCount = 11;
            }
            if(prPar && (prPar->u1RefNum > 0))
            {
                ucFbCount = prPar->u1RefNum + 3;
            }
            #endif
            break;
		case FBM_VDEC_AV1:
            _arFbg[ucFbgId].ucMvBufNs = 0;
            if (!ucFbCount)
            {
                ucFbCount = 11;
            }
            break;
        case FBM_VDEC_JPEG:
            ucFbCount = 4;
            if(prPar && (prPar->u1RefNum > 0))
            {
                ucFbCount = prPar->u1RefNum;
            }
            break;
        case FBM_VDEC_MPEG2:
            ucFbCount = 10;
            break;
        case FBM_VDEC_VC1:
            ucFbCount = 8;
            break;
        case FBM_VDEC_RV:
            ucFbCount = 8;
            break;
        case FBM_VDEC_VP6:
            ucFbCount = 6;
            break;
        case FBM_VDEC_VP8:
            ucFbCount = 8;
            break;
        case FBM_VDEC_MPEG4:
            ucFbCount = 8;
            break;
        case FBM_VDEC_AVS:
            ucFbCount = 8;
            break;
        case FBM_VDEC_MJPEG:
            ucFbCount = 4;
            break;
        case FBM_VDEC_AVS2:
        {
            if(prPar && (prPar->u1RefNum == 0))
            {
                LOG(0,"ref number is 0,need AVS2 VDEC check\n");
            }
            else if(prPar && (prPar->u1RefNum > 0))
            {
                ucFbCount = prPar->u1RefNum + 3;
            }
            break;
        }
        default:
            LOG(0,"Unkonwn dectype(%d)\n",_arFbg[ucFbgId].u4VDecFmt);
            ucFbCount = 8;
            break;

    }

    if(_fgSetDecoderFb && (_u1DecoderType == _arFbg[ucFbgId].u4VDecFmt))
    {
        ucFbCount = _u1NumOfFb;
        _fgSetDecoderFb = FALSE;
        LOG(0,"decoder fb is set to %d\n",ucFbCount);
    }

    LOG(2,"fb count %d\n",ucFbCount);
    return ucFbCount;
}

static UINT32 FBM_AllocPool2(UCHAR ucFbgId)
{
    MPEG_POOL_INFO_T rMpegPoolInfo;
    UINT32 u4PoolSize,u4MpegTotalYSize,u4MpegTotalCSize;

    FBM_MEMSET(&rMpegPoolInfo, 0x0, sizeof(MPEG_POOL_INFO_T));

    u4PoolSize = _FBM_PoolAllocate(&rMpegPoolInfo);
    _arFbg[ucFbgId].u4FbMemoryPool2   = rMpegPoolInfo.u4FbMemoryPool;
    _arFbg[ucFbgId].u4FbMemoryPool2C  = rMpegPoolInfo.u4FbMemoryPoolC;
    u4MpegTotalYSize                  = rMpegPoolInfo.u4MpegTotalYSize;
    u4MpegTotalCSize                  = rMpegPoolInfo.u4MpegTotalCSize;

    _arFbg[ucFbgId].u4FbStartPool2YAddr  = _arFbg[ucFbgId].u4FbMemoryPool2;
    _arFbg[ucFbgId].u4FbEndPool2YAddr    = _arFbg[ucFbgId].u4FbMemoryPool2 + u4MpegTotalYSize ;
    _arFbg[ucFbgId].u4FbStartPool2CAddr  = _arFbg[ucFbgId].u4FbMemoryPool2C;
    _arFbg[ucFbgId].u4FbEndPool2CAddr    = _arFbg[ucFbgId].u4FbMemoryPool2C + u4MpegTotalCSize;


    if (u4PoolSize == 0 || (!_arFbg[ucFbgId].u4FbMemoryPool2) || (!_arFbg[ucFbgId].u4FbMemoryPool2C))
    {
        _FBM_PoolRelease(_arFbg[ucFbgId].u4FbMemoryPool);
        LOG(0,"alloc buffer 2 fail %s (%d)\n",__FUNCTION__,__LINE__);
        return FBM_RETURN_ERROR;
    }
    _arFbg[ucFbgId].u4FbMemoryPoolSize += u4MpegTotalYSize + u4MpegTotalCSize;

    LOG(1,"Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Y2[0x%lx-0x%lx] C2[0x%lx-0x%lx] PoolSize(%d)\n",
        _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
        _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
        _arFbg[ucFbgId].u4FbStartPool2YAddr,_arFbg[ucFbgId].u4FbEndPool2YAddr,
        _arFbg[ucFbgId].u4FbStartPool2CAddr,_arFbg[ucFbgId].u4FbEndPool2CAddr,
        _arFbg[ucFbgId].u4FbMemoryPoolSize);
    LOG(1,"%s line(%d)\n",__FUNCTION__,__LINE__);

    return FBM_RETURN_OK;
}


static UINT32 FBM_Alloc4KJpegFB(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,
                                UINT32 u4YSize,UINT32 u4CSize,UINT32 u4HSize,UINT32 u4VSize,UCHAR ucFbMax)
{
    UCHAR ucFbIdx;
    UINT32 u4PoolSize;
    UPTR u4Addr,u4AddrC;
    UPTR u4FbStartPoolYAddr,u4FbEndPoolYAddr;
    UPTR u4FbStartPoolCAddr,u4FbEndPoolCAddr;

    u4Addr = _arFbg[ucFbgId].u4FbMemoryPool;
    u4AddrC = _arFbg[ucFbgId].u4FbMemoryPoolC;
    u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;
    u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPoolCAddr;

    _arFbg[ucFbgId].u4FbWidth = u4HSize;
    _arFbg[ucFbgId].u4FbHeight = u4VSize;

    if(_arFbg[ucFbgId].fg10Bit)
    {
        u4YSize = FBM_ALIGN_MASK(((u4YSize * 5) >> 2), FBM_FMG_Y_ALIGMENT);
        u4CSize = FBM_ALIGN_MASK(((u4CSize * 5) >> 2), FBM_FMG_Y_ALIGMENT);
    }
    
    if(prPar && (prPar->u1RefNum <= 2 && prPar->u1RefNum != 0))
    {
        if(_arFbg[ucFbgId].fg8KMpeg == FALSE)
        {
            u4PoolSize = (u4YSize + u4CSize);
        }
        else
        {
            u4PoolSize = (u4YSize + u4CSize) << 1;
        }
    }
    else
    {
        if(_arFbg[ucFbgId].fg8KMpeg == FALSE)
        {
            u4PoolSize = FBM_FBG_TYPE_4K2K_JPEG_SIZE;
        }
        else
        {
            u4PoolSize = FBM_FBG_TYPE_4K2K_JPEG_SIZE*2;
        }
    }

    if(prPar && (prPar->u1RefNum <= 2 && prPar->u1RefNum != 0))
    {
        for (ucFbIdx = 0; ((ucFbIdx < ucFbMax)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
        {
            if ((u4PoolSize < (u4YSize + u4CSize)) && (_arFbg[ucFbgId].fg8KMpeg == FALSE))
            {
                u4Addr = _arFbg[ucFbgId].u4FbMemoryPool2;
                u4AddrC = _arFbg[ucFbgId].u4FbMemoryPool2C;
                u4PoolSize = u4YSize + u4CSize;

                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPool2YAddr;
                u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPool2CAddr;
                LOG(0,"Allocate from MPEG2 ucFbNs(%d)\n",ucFbIdx);
            }
            u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_GFX_Y_ALIGMENT);

            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4Addr;

            FBM_GDMA_MEMSET((VOID*)u4Addr,0x00000000,u4YSize);

            FBM_Check_AddrIsOverLap(u4Addr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)

            u4Addr += u4YSize;

            u4AddrC = FBM_ALIGN_MASK(u4AddrC, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4AddrC;
            FBM_GDMA_MEMSET((VOID*)u4AddrC,0x80808080,u4CSize);

            FBM_Check_AddrIsOverLap(u4AddrC,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr)

            u4AddrC += u4CSize;

            LOG(2, "FBG_TYPE_4K2K(%d): AddrY/C(0x%lx/0x%lx) SizeY/C(0x%x/0x%x) Pool/Pool2(0x%lx/0x%lx) Size(0x%x).\n",
                ucFbgId, _arFbg[ucFbgId].au4AddrY[ucFbIdx], _arFbg[ucFbgId].au4AddrC[ucFbIdx],
                u4YSize, u4CSize, _arFbg[ucFbgId].u4FbMemoryPool, _arFbg[ucFbgId].u4FbMemoryPool2, u4PoolSize);

            if (u4PoolSize >= u4YSize + u4CSize)
            {
                u4PoolSize -= (u4YSize + u4CSize);
            }
            else
            {
                u4PoolSize = 0;
            }
        }
    }
    else
    {
        for (ucFbIdx = 0; ((ucFbIdx < ucFbMax)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
        {
            if ((u4PoolSize < (u4YSize + u4CSize)) && (_arFbg[ucFbgId].fg8KMpeg == FALSE))
            {
                u4Addr = _arFbg[ucFbgId].u4FbMemoryPool2;
                u4AddrC = _arFbg[ucFbgId].u4FbMemoryPool2C;
                u4PoolSize = FBM_FBG_TYPE_4K2K_JPEG_SIZE;

                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPool2YAddr;
                u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPool2CAddr;
            }
            u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4Addr;
            _arFbg[ucFbgId].au4GfxMemsetId[ucFbIdx] = (UINT32)FBM_GFX_MEMSET_ASYNC(u4Addr, (_arFbg[ucFbgId].u4FbWidth), _arFbg[ucFbgId].u4FbHeight, 0x0);

            FBM_Check_AddrIsOverLap(u4Addr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)

            u4Addr += u4YSize;

            u4AddrC = FBM_ALIGN_MASK(u4AddrC, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4AddrC;
            _arFbg[ucFbgId].au4GfxMemsetId[ucFbIdx] = (UINT32)FBM_GFX_MEMSET_ASYNC(u4AddrC, (_arFbg[ucFbgId].u4FbWidth), (_arFbg[ucFbgId].u4FbHeight >> 1), 0x80);
            FBM_Check_AddrIsOverLap(u4AddrC,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr)

            u4AddrC += u4CSize;

            LOG(2, "FBG_TYPE_4K2K(%d): AddrY/C(0x%lx/0x%lx) SizeY/C(0x%x/0x%x) Pool/Pool2(0x%lx/0x%lx) Size(0x%x).\n",
                ucFbIdx, _arFbg[ucFbgId].au4AddrY[ucFbIdx], _arFbg[ucFbgId].au4AddrC[ucFbIdx],
                u4YSize, u4CSize, _arFbg[ucFbgId].u4FbMemoryPool, _arFbg[ucFbgId].u4FbMemoryPool2, u4PoolSize);

            if (u4PoolSize >= u4YSize + u4CSize)
            {
                u4PoolSize -= (u4YSize + u4CSize);
            }
            else
            {
                u4PoolSize = 0;
            }
        }
    }

    _arFbg[ucFbgId].ucFbNsBase = 0;
    _arFbg[ucFbgId].ucFbNs = ucFbIdx;


    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);
    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;
    for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase; ucFbIdx < _arFbg[ucFbgId].ucFbNs; ucFbIdx++)
    {
        _FBM_PutFrameBufferToEmptyQ(ucFbgId, (UCHAR)(ucFbIdx));
    }
    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);

    return FBM_RETURN_OK;
}

static UINT32 FBM_Alloc8KJpegFB(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,
                                UINT32 u4YSize,UINT32 u4CSize,UINT32 u4HSize,UINT32 u4VSize,UCHAR ucFbMax)
{
    UCHAR ucFbIdx;
    UINT32 u4PoolSize;
    UPTR u4Addr,u4AddrC;
    UPTR u4FbStartPoolYAddr,u4FbEndPoolYAddr;
    UPTR u4FbStartPoolCAddr,u4FbEndPoolCAddr;
    u4Addr = _arFbg[ucFbgId].u4FbMemoryPool;
    u4AddrC = _arFbg[ucFbgId].u4FbMemoryPoolC;
    u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;
    u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPoolCAddr;
    u4YSize = FBM_FBG_JPEG_8K_Y_SIZE;
    u4CSize = FBM_FBG_JPEG_8K_Y_SIZE;
    _arFbg[ucFbgId].u4FbWidth = FBM_FBG_8K_JPEG_H;
    _arFbg[ucFbgId].u4FbHeight = FBM_FBG_8K_JPEG_V;
    if(prPar && (prPar->u1RefNum <= 2 && prPar->u1RefNum != 0))
    {
        if(_arFbg[ucFbgId].fg8KMpeg == FALSE)
        {
            u4PoolSize = FBM_FBG_JPEG_8K_Y_SIZE*2;
        }
        else
        {
            u4PoolSize = FBM_FBG_JPEG_8K_Y_SIZE*4;
        }
    }
    else
    {
        u4PoolSize = FBM_FBG_JPEG_8K_Y_SIZE*4;
    }
    if(prPar && (prPar->u1RefNum <= 2 && prPar->u1RefNum != 0))
    {
        for (ucFbIdx = 0; ((ucFbIdx < ucFbMax)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
        {
            if ((u4PoolSize < (u4YSize + u4CSize)) && (_arFbg[ucFbgId].fg8KMpeg == FALSE))
            {
                u4Addr = _arFbg[ucFbgId].u4FbMemoryPool2;
                u4AddrC = _arFbg[ucFbgId].u4FbMemoryPool2C;
                u4PoolSize = FBM_FBG_JPEG_8K_Y_SIZE*2;
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPool2YAddr;
                u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPool2CAddr;
                LOG(0,"Allocate from MPEG2 ucFbNs(%d)\n",ucFbIdx);
            }
            u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4Addr;
            FBM_GDMA_MEMSET((VOID*)u4Addr,0x00000000,u4YSize);
            FBM_Check_AddrIsOverLap(u4Addr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)
            u4Addr += u4YSize;
            u4AddrC = FBM_ALIGN_MASK(u4AddrC, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4AddrC;
            FBM_GDMA_MEMSET((VOID*)u4AddrC,0x80808080,u4CSize);
            FBM_Check_AddrIsOverLap(u4AddrC,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr)
            u4AddrC += u4CSize;
            LOG(2, "FBG_TYPE_4K2K(%d): AddrY/C(0x%lx/0x%lx) SizeY/C(0x%x/0x%x) Pool/Pool2(0x%lx/0x%lx) Size(0x%x).\n",
                ucFbgId, _arFbg[ucFbgId].au4AddrY[ucFbIdx], _arFbg[ucFbgId].au4AddrC[ucFbIdx],
                u4YSize, u4CSize, _arFbg[ucFbgId].u4FbMemoryPool, _arFbg[ucFbgId].u4FbMemoryPool2, u4PoolSize);
            if (u4PoolSize >= u4YSize + u4CSize)
            {
                u4PoolSize -= (u4YSize + u4CSize);
            }
            else
            {
                u4PoolSize = 0;
            }
        }
    }
    else
    {
        for (ucFbIdx = 0; ((ucFbIdx < ucFbMax)&&(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP)); ucFbIdx++)
        {
            if (u4PoolSize < (u4YSize + u4CSize))
            {
                u4Addr = _arFbg[ucFbgId].u4FbMemoryPool2;
                u4AddrC = _arFbg[ucFbgId].u4FbMemoryPool2C;
                u4PoolSize = FBM_FBG_JPEG_8K_Y_SIZE*4;
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPool2YAddr;
                u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPool2CAddr;
            }
            u4Addr = FBM_ALIGN_MASK(u4Addr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4Addr;
            _arFbg[ucFbgId].au4GfxMemsetId[ucFbIdx] = (UINT32)FBM_GFX_MEMSET_ASYNC(u4Addr, (_arFbg[ucFbgId].u4FbWidth), _arFbg[ucFbgId].u4FbHeight, 0x0);
            FBM_Check_AddrIsOverLap(u4Addr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)
            u4Addr += u4YSize;
            u4AddrC = FBM_ALIGN_MASK(u4AddrC, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4AddrC;
            _arFbg[ucFbgId].au4GfxMemsetId[ucFbIdx] = (UINT32)FBM_GFX_MEMSET_ASYNC(u4AddrC, (_arFbg[ucFbgId].u4FbWidth), (_arFbg[ucFbgId].u4FbHeight >> 1), 0x80);
            FBM_Check_AddrIsOverLap(u4AddrC,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr)
            u4AddrC += u4CSize;
            LOG(2, "FBG_TYPE_4K2K(%d): AddrY/C(0x%lx/0x%lx) SizeY/C(0x%x/0x%x) Pool/Pool2(%lx/%lx) Size(0x%x).\n",
                ucFbIdx, _arFbg[ucFbgId].au4AddrY[ucFbIdx], _arFbg[ucFbgId].au4AddrC[ucFbIdx],
                u4YSize, u4CSize, _arFbg[ucFbgId].u4FbMemoryPool, _arFbg[ucFbgId].u4FbMemoryPool2, u4PoolSize);
            if (u4PoolSize >= u4YSize + u4CSize)
            {
                u4PoolSize -= (u4YSize + u4CSize);
            }
            else
            {
                u4PoolSize = 0;
            }
        }
    }
    _arFbg[ucFbgId].ucFbNsBase = 0;
    _arFbg[ucFbgId].ucFbNs = ucFbIdx;
    VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);
    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;
    for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase; ucFbIdx < _arFbg[ucFbgId].ucFbNs; ucFbIdx++)
    {
        _FBM_PutFrameBufferToEmptyQ(ucFbgId, (UCHAR)(ucFbIdx));
    }
    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    return FBM_RETURN_OK;
}
static BOOL FBM_CheckMemsetOption(FBM_FBG_MEMSET_TYPE u4MemsetOption, UCHAR ucFbIdx)
{
    BOOL fgNeedMemset = FALSE;
    
    if(((FBM_FBG_MEMSET_1ST == u4MemsetOption)&&(ucFbIdx == 0))
        ||(FBM_FBG_MEMSET_ALL == u4MemsetOption))
    {
        fgNeedMemset = TRUE;
    }
    else
    {
        fgNeedMemset = FALSE;
    }

    return fgNeedMemset;
}

static UINT32 FBM_AllocStillImageFB(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,
                                UINT32 u4YSize,UINT32 u4CSize,UINT32 u4HSize,UINT32 u4VSize,UCHAR ucFbMax)
{
    UCHAR ucFbIdx = 0;
    UPTR u4YAddr,u4CAddr;
    UINT32 u4MvSize =0;
    UINT32 u4OriYSize = u4YSize;
    UPTR u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    UPTR u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    UPTR u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;
    UPTR u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPoolCAddr;

    u4YAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    u4CAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;

    if(_arFbg[ucFbgId].fg10Bit)
    {
        u4YSize = FBM_ALIGN_MASK(((u4YSize*5)>>2), FBM_FMG_Y_ALIGMENT);
        u4CSize = FBM_ALIGN_MASK(((u4CSize*5)>>2), FBM_FMG_Y_ALIGMENT);
    }
    
    if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265)
    {
        u4MvSize = u4YSize >> 4;
        u4MvSize = FBM_ALIGN_MASK(u4MvSize, FBM_B2R_H_PITCH);
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr - u4MvSize - FBM_8K_SIZE;
    }
    
    u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
    _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
    
    if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
    {
        FBM_GDMA_MEMSET((void*)(u4YAddr),0x00000000,u4YSize);
    }
    FBM_Check_AddrIsOverLap(u4YAddr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)
    u4YAddr += u4YSize;

    u4CAddr = FBM_ALIGN_MASK(u4CAddr, FBM_GFX_C_ALIGMENT);
    _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4CAddr;
    
    if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
    {
        FBM_GDMA_MEMSET((VOID*)u4CAddr,0x80808080,u4CSize);
    }
    FBM_Check_AddrIsOverLap(u4CAddr,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr)
    u4CAddr += u4CSize;

    LOG(0,"ucFbgId(%d) au4AddrY[%d] 0x%lx au4AddrC[%d] 0x%lx\n",
            ucFbgId,ucFbIdx,_arFbg[ucFbgId].au4AddrY[ucFbIdx],
            ucFbIdx,_arFbg[ucFbgId].au4AddrC[ucFbIdx]);

    _arFbg[ucFbgId].u4MvStartAddr = u4YAddr;
    _arFbg[ucFbgId].ucFbNs = 1;

    if ((u4FbEndPoolYAddr >= _arFbg[ucFbgId].u4FbStartPoolYAddr) &&
        (u4FbEndPoolYAddr <= _arFbg[ucFbgId].u4FbEndPoolYAddr))
    {
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    }
    else if ((u4FbEndPoolYAddr >= _arFbg[ucFbgId].u4FbStartPool2YAddr) &&
             (u4FbEndPoolYAddr <= _arFbg[ucFbgId].u4FbEndPool2YAddr))
    {
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPool2YAddr;
    }
    else
    {
        LOG(0,"u4FbEndPoolYAddr is out of pool\n");
    }

    //MV buffer
    if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265)
    {
        if(prPar && prPar->fgStillImage)
        {
            _arFbg[ucFbgId].ucMvBufNs = 1;
        }
        else
        {
            goto alloc_fb_fail;
        }
        if(FBM_CfgMvbuffer(ucFbgId,u4OriYSize,_arFbg[ucFbgId].ucMvBufNs) != FBM_RETURN_OK)
        {
            goto alloc_fb_fail;
        }
    }

    _arFbg[ucFbgId].u4ExtraYBuffer =0;
    _arFbg[ucFbgId].u4ExtraCBuffer =0;

    if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8)||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6)||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))

    {
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);
    }
    else
    {
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);

        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyBQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)(_arFbg[ucFbgId].ucFbNs - FBM_REF_FB_NS_PER_GROUP)) == OSR_OK);

#ifdef CC_VDP_FULL_ISR
        _arFbg[ucFbgId].hEmptyQSemaphore.prState = &_rState;
        _arFbg[ucFbgId].hEmptyBQSemaphore.prState = &_rState;
#endif
    }

    // Nivia and William Co-design
    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;

    for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase; ucFbIdx < _arFbg[ucFbgId].ucFbNs; ucFbIdx++)
    {
        LOG(0,"Put to empty bufferQ\n");
        _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbIdx);
    }

    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);

    return FBM_RETURN_OK;

alloc_fb_fail:
    return FBM_RETURN_ERROR;
}
      
static UINT32 FBM_AllocSeamlessFB(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,
                                  UINT32 u4YSize,UINT32 u4CSize,UINT32 u4HSize,UINT32 u4VSize)
{
    UINT32 u4MvReservedSize = 0;
    UCHAR ucFbIdx = 0,ucFbIdxMinor = 0;
    UCHAR ucMaxFb = MINJOR_BASE_FBID;
    UPTR u4YAddr,u4CAddr;
    UINT32 u4MvSize =0;
    UCHAR ucPoolCount = 2;
    BOOL fgPool2Used = FALSE;
    UINT32 u4MinorYSize,u4MinorCSize;
    UINT32 u4MiscSize,u4VP9MVSize;
    UPTR u4MinorYAddr = 0;
    UPTR u4MinorCAddr = 0;
    UPTR u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    UPTR u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    UPTR u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;
    UPTR u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPoolCAddr;

    if(prPar == NULL)
    {
        LOG(0,"Error ,seamless playback, prPar is NULL\n");
        goto alloc_fb_fail;
    }

    u4MiscSize = FBM_MISC_BUFFER_SIZE(prPar->u4TargetW,prPar->u4TargetH);
    u4VP9MVSize = FBM_VP9_MV_BUFFER_SIZE(prPar->u4TargetW,prPar->u4TargetH);

    _arFbg[ucFbgId].ucMajorMvBufNs = 0;
    _arFbg[ucFbgId].ucMinorMvBufNs = 0;
    _arFbg[ucFbgId].ucFbNsBase = 0;
    _arFbg[ucFbgId].ucFbNs = 0;

    if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264)
    {
        u4MvSize = u4YSize >> 2;
        u4MvSize = FBM_ALIGN_MASK(u4MvSize, FBM_B2R_H_PITCH);
    }
    else if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265)
    {
        u4MvSize = u4YSize >> 4;
        u4MvSize = FBM_ALIGN_MASK(u4MvSize, FBM_B2R_H_PITCH);
    }
    else if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9)
    {
        u4MvReservedSize += (u4VP9MVSize<<1);
        u4MvReservedSize += u4MiscSize;
        u4MvReservedSize += FBM_VDEC_WORKING_ALIGNMENT;
    }
    else if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1)
    {
        u4MvReservedSize += FBM_MISC_BUFFER_SIZE_AV1;
        u4MvReservedSize += FBM_VDEC_WORKING_ALIGNMENT;
    }

    u4YAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    u4CAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;

    if((_arFbg[ucFbgId].u4FbEndPool2YAddr == _arFbg[ucFbgId].u4FbStartPool2YAddr)
       || (_arFbg[ucFbgId].u4FbEndPool2YAddr == 0))
    {
        ucPoolCount = 1;
    }

    //if(_arFbg[ucFbgId].fg10Bit) //seamless always open 10bit
    {
        u4YSize = FBM_ALIGN_MASK(((u4YSize*5)>>2), FBM_FMG_Y_ALIGMENT);
        u4CSize = FBM_ALIGN_MASK(((u4CSize*5)>>2), FBM_FMG_Y_ALIGMENT);
    }

    u4MinorYSize = u4YSize>>1;
    u4MinorYSize = ((u4MinorYSize>>13)<<13);//8k align
    u4MinorCSize = u4CSize>>1;
    u4MinorCSize = ((u4MinorCSize>>13)<<13);//8k align

    LOG(2,"MajYC(%x %x),MinYC(%x %x)\n",u4YSize,u4CSize,u4MinorYSize,u4MinorCSize);


    if(_arFbg[ucFbgId].u4FbEndPoolCAddr == _arFbg[ucFbgId].u4FbStartPoolCAddr)
    {
        //no mpegC
        UINT32 u4FBSize = u4YSize + u4CSize;
        LOG(0,"No mepgC case\n");
        if(ucPoolCount == 1)
        {
            u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr - u4MvReservedSize;
        }

        for (ucFbIdx = 0; ucFbIdx < ucMaxFb; ucFbIdx++)
        {
            if(((u4YAddr + u4FBSize + (u4FBSize>>8)+ FBM_8K_SIZE*8) > u4FbEndPoolYAddr) &&
               (!fgPool2Used))
            {
                _FBM_CheckRemainMemSize(TRUE,u4YAddr,u4FBSize,u4FbEndPoolYAddr);
                if (ucPoolCount == 1)
                {
                    LOG(0,"Seamless playback,fbm alloc max (%d) fb OK\n",ucFbIdx);
                    break;
                }
                u4YAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPool2YAddr - u4MvReservedSize;
                fgPool2Used = TRUE;
            }
            else if ((u4YAddr + u4FBSize + (u4FBSize>>8)+ FBM_8K_SIZE*8) > u4FbEndPoolYAddr)
            {
                LOG(0,"Seamless playback,fbm alloc max (%d) fb OK\n",ucFbIdx);
                break;
            }

            ucFbIdxMinor = FBM_MAJOR2MINORSTARTFBID(ucFbIdx);

            //Major Y
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
            u4YAddr += u4YSize;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrY[ucFbIdx],0x00000000,u4YSize);
            }
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            //Major Y_EXT
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx] = u4YAddr;
            u4YAddr += (u4YSize>>8);
            
      
            FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],0xFFFFFFFF,(u4YSize>>8));
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],(u4YSize>>8),u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_C_ALIGMENT);
            u4YAddr += FBM_8K_SIZE;

            //Major C
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4YAddr;
            u4YAddr += u4CSize;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrC[ucFbIdx],0x80808080,u4CSize);
            }
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4CSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            //Major C_EXT
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx] = u4YAddr;
            u4YAddr += (u4CSize>>8);
            
   
            FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],0xFFFFFFFF,(u4CSize>>8));
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],(u4CSize>>8),u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_C_ALIGMENT);
            u4YAddr += FBM_8K_SIZE;

            //alloc Minor buffer
            u4MinorYAddr = _arFbg[ucFbgId].au4AddrY[ucFbIdx];
            u4MinorCAddr = _arFbg[ucFbgId].au4AddrC[ucFbIdx];

            //Minor Y
            _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor] = u4MinorYAddr;
            u4MinorYAddr += u4MinorYSize;
            //Minor Y_EXT
            u4MinorYAddr = FBM_ALIGN_MASK(u4MinorYAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor] = u4MinorYAddr;
            u4MinorYAddr += (u4MinorYSize>>8);
            //Minor Y
            u4MinorYAddr = FBM_ALIGN_MASK(u4MinorYAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor+1] = u4MinorYAddr;
            u4MinorYAddr += u4MinorYSize;
            //Minor Y_EXT
            u4MinorYAddr = FBM_ALIGN_MASK(u4MinorYAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor+1] = u4MinorYAddr;
            u4MinorYAddr += (u4MinorYSize>>8);

            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY[ucFbIdxMinor],
                                    u4MinorYSize,_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4MinorCAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY[ucFbIdxMinor+1],
                                    u4MinorYSize,_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4MinorCAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor],
                                    (u4MinorYSize>>8),_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4MinorCAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor+1],
                                    (u4MinorYSize>>8),_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4MinorCAddr);

            //Minor C
            _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor] = u4MinorCAddr;
            u4MinorCAddr += u4MinorCSize;
            //Minor C_EXT
            u4MinorCAddr = FBM_ALIGN_MASK(u4MinorCAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor] = u4MinorCAddr;
            u4MinorCAddr += (u4MinorCSize>>8);
            //Minor C
            u4MinorCAddr = FBM_ALIGN_MASK(u4MinorCAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor+1] = u4MinorCAddr;
            u4MinorCAddr += u4MinorCSize;
            //Minor C_EXT
            u4MinorCAddr = FBM_ALIGN_MASK(u4MinorCAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor+1] = u4MinorCAddr;
            u4MinorCAddr += (u4MinorCSize>>8);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC[ucFbIdxMinor],
                                    u4MinorCSize,_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4YAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC[ucFbIdxMinor+1],
                                    u4MinorCSize,_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4YAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor],
                                    (u4MinorCSize>>8),_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4YAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor+1],
                                    (u4MinorCSize>>8),_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4YAddr);

            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(0,"ucFbgId(%d) fb(%d) Y[0x%lx] Y_EXT[0x%lx] C[0x%lx] C_EXT[0x%lx]\n",
                    ucFbgId,  ucFbIdx,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdx],
                    _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],
                    _arFbg[ucFbgId].au4AddrC[ucFbIdx],
                    _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx]);
                LOG(0,"ucFbgId(%d) fb(%d) Y[0x%lx] Y_EXT[0x%lx] C[0x%lx] C_EXT[0x%lx]\n",
                    ucFbgId,  ucFbIdxMinor,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor],
                    _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor],
                    _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor],
                    _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor]);
                LOG(0,"ucFbgId(%d) fb(%d) Y[0x%lx] Y_EXT[0x%lx] C[0x%lx] C_EXT[0x%lx]\n",
                    ucFbgId,  ucFbIdxMinor+1,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor+1],
                    _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor+1],
                    _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor+1],
                    _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor+1]);
            }
            u4MvReservedSize += u4MvSize;
            if ((ucPoolCount == 1) || fgPool2Used)
            {
                u4FbEndPoolYAddr = u4FbEndPoolYAddr - u4MvSize;
            }
        }

    }
    else
    {
        //YC
        if(ucPoolCount == 1)
        {
            u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr - u4MvReservedSize;
        }

        for (ucFbIdx = 0; ucFbIdx < ucMaxFb; ucFbIdx++)
        {
            if((((u4YAddr + u4YSize + (u4YSize>>8)+ FBM_8K_SIZE*4) > u4FbEndPoolYAddr) ||
                ((u4CAddr + u4CSize + (u4CSize>>8)+ FBM_8K_SIZE*4) > u4FbEndPoolCAddr))&&
               (!fgPool2Used))
            {
                _FBM_CheckRemainMemSize(TRUE,u4YAddr,u4YSize,u4FbEndPoolYAddr);
                _FBM_CheckRemainMemSize(TRUE,u4CAddr,u4CSize,u4FbEndPoolCAddr);
                if (ucPoolCount == 1)
                {
                    LOG(0,"Seamless playback, fbm alloc max (%d) fb OK\n",ucFbIdx);
                    break;
                }
                u4YAddr             = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4CAddr             = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbEndPool2YAddr - u4MvReservedSize;
                u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbEndPool2CAddr;
                fgPool2Used         = TRUE;
            }
            else if (((u4YAddr + u4YSize + (u4YSize>>8)+ FBM_8K_SIZE*4) > u4FbEndPoolYAddr) ||
                     ((u4CAddr + u4CSize + (u4CSize>>8)+ FBM_8K_SIZE*4) > u4FbEndPoolCAddr))
            {
                LOG(0,"Seamless playback, fbm alloc max (%d) fb OK\n",ucFbIdx);
                break;
            }

            ucFbIdxMinor = FBM_MAJOR2MINORSTARTFBID(ucFbIdx);

            //Major Y
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((void*)(u4YAddr),0x00000000,u4YSize);
            }
            FBM_Check_AddrIsOverLap(u4YAddr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)
            u4YAddr += u4YSize;

            //Major Y_EXT
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx] = u4YAddr;
            u4YAddr += (u4YSize>>8);
            
            FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],0xFFFFFFFF,(u4YSize>>8));
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],(u4YSize>>8),u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            u4YAddr += FBM_8K_SIZE;

            //Major C
            u4CAddr = FBM_ALIGN_MASK(u4CAddr, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4CAddr;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((VOID*)u4CAddr,0x80808080,u4CSize);
            }
            FBM_Check_AddrIsOverLap(u4CAddr,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr);
            u4CAddr += u4CSize;

            //Major C_EXT
            u4CAddr = FBM_ALIGN_MASK(u4CAddr, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx] = u4CAddr;
            u4CAddr += (u4CSize>>8);
            
            FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],0xFFFFFFFF,(u4CSize>>8));
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],(u4CSize>>8),u4FbStartPoolCAddr,u4FbEndPoolCAddr);

            u4CAddr = FBM_ALIGN_MASK(u4CAddr, FBM_GFX_Y_ALIGMENT);
            u4CAddr += FBM_8K_SIZE;

            //alloc Minor buffer
            u4MinorYAddr = _arFbg[ucFbgId].au4AddrY[ucFbIdx];
            u4MinorCAddr = _arFbg[ucFbgId].au4AddrC[ucFbIdx];

            //Minor Y
            _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor] = u4MinorYAddr;
            u4MinorYAddr += u4MinorYSize;
            //Minor Y_EXT
            u4MinorYAddr = FBM_ALIGN_MASK(u4MinorYAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor] = u4MinorYAddr;
            u4MinorYAddr += (u4MinorYSize>>8);
            //Minor Y
            u4MinorYAddr = FBM_ALIGN_MASK(u4MinorYAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor+1] = u4MinorYAddr;
            u4MinorYAddr += u4MinorYSize;
            //Minor Y_EXT
            u4MinorYAddr = FBM_ALIGN_MASK(u4MinorYAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor+1] = u4MinorYAddr;
            u4MinorYAddr += (u4MinorYSize>>8);

            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY[ucFbIdxMinor],
                                    u4MinorYSize,_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4YAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY[ucFbIdxMinor+1],
                                    u4MinorYSize,_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4YAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor],
                                    (u4MinorYSize>>8),_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4YAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor+1],
                                    (u4MinorYSize>>8),_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4YAddr);


            //Minor C
            _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor] = u4MinorCAddr;
            u4MinorCAddr += u4MinorCSize;
            //Minor C_EXT
            u4MinorCAddr = FBM_ALIGN_MASK(u4MinorCAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor] = u4MinorCAddr;
            u4MinorCAddr += (u4MinorCSize>>8);
            //Minor C
            u4MinorCAddr = FBM_ALIGN_MASK(u4MinorCAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor+1] = u4MinorCAddr;
            u4MinorCAddr += u4MinorCSize;
            //Minor C_EXT
            u4MinorCAddr = FBM_ALIGN_MASK(u4MinorCAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor+1] = u4MinorCAddr;
            u4MinorCAddr += (u4MinorCSize>>8);

            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC[ucFbIdxMinor],
                                    u4MinorCSize,_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4CAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC[ucFbIdxMinor+1],
                                    u4MinorCSize,_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4CAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor],
                                    (u4MinorCSize>>8),_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4CAddr);
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor+1],
                                    (u4MinorCSize>>8),_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4CAddr);

            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(0,"ucFbgId(%d) fb(%d) Y[0x%lx] Y_EXT[0x%lx] C[0x%lx] C_EXT[0x%lx]\n",
                    ucFbgId,  ucFbIdx,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdx],
                    _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],
                    _arFbg[ucFbgId].au4AddrC[ucFbIdx],
                    _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx]);
                LOG(0,"ucFbgId(%d) fb(%d) Y[0x%lx] Y_EXT[0x%lx] C[0x%lx] C_EXT[0x%lx]\n",
                    ucFbgId,  ucFbIdxMinor,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor],
                    _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor],
                    _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor],
                    _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor]);
                LOG(0,"ucFbgId(%d) fb(%d) Y[0x%lx] Y_EXT[0x%lx] C[0x%lx] C_EXT[0x%lx]\n",
                    ucFbgId,  ucFbIdxMinor+1,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdxMinor+1],
                    _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdxMinor+1],
                    _arFbg[ucFbgId].au4AddrC[ucFbIdxMinor+1],
                    _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdxMinor+1]);
            }
            u4MvReservedSize += u4MvSize;
            if ((ucPoolCount == 1) || fgPool2Used)
            {
                u4FbEndPoolYAddr = u4FbEndPoolYAddr - u4MvSize;
            }
        }
    }

    if ((u4FbEndPoolYAddr >= _arFbg[ucFbgId].u4FbStartPoolYAddr) &&
        (u4FbEndPoolYAddr <= _arFbg[ucFbgId].u4FbEndPoolYAddr))
    {
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    }
    else if ((u4FbEndPoolYAddr >= _arFbg[ucFbgId].u4FbStartPool2YAddr) &&
             (u4FbEndPoolYAddr <= _arFbg[ucFbgId].u4FbEndPool2YAddr))
    {
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPool2YAddr;
    }
    else
    {
        LOG(0,"u4FbEndPoolYAddr is out of pool\n");
    }

    _arFbg[ucFbgId].u4MvStartAddr = u4YAddr;

    if ((_arFbg[ucFbgId].u4MvStartAddr >= _arFbg[ucFbgId].u4FbStartPoolYAddr) &&
        (_arFbg[ucFbgId].u4MvStartAddr <= _arFbg[ucFbgId].u4FbEndPoolYAddr))
    {
        if ((_arFbg[ucFbgId].u4MvStartAddr + u4MvReservedSize > _arFbg[ucFbgId].u4FbEndPoolYAddr) &&
            (ucPoolCount == 2))
        {
            LOG(2,"alloc mv in pool2\n");
            _arFbg[ucFbgId].u4MvStartAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
        }
    }
    _arFbg[ucFbgId].ucFbNsMajorBase = 0;
    _arFbg[ucFbgId].ucFbNsMinorBase = MINJOR_BASE_FBID;
    _arFbg[ucFbgId].ucFbNsMajor = ucFbIdx;
    _arFbg[ucFbgId].ucFbNsMinor = ucFbIdxMinor + 2;
    if(ucFbIdx > 2)
    {
        _arFbg[ucFbgId].ucMajorMvBufNs = ucFbIdx - 2;
        _arFbg[ucFbgId].ucMinorMvBufNs = (_arFbg[ucFbgId].ucMajorMvBufNs<<1);
    }
    else
    {
        LOG(0,"fb count is %d\n",ucFbIdx);
        goto alloc_fb_fail;
    }

    if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9)
    {
        _arFbg[ucFbgId].ucMvBufNs = 2;
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_VP9_MV_ALIGMENT);
        for (ucFbIdx = 0; (ucFbIdx < _arFbg[ucFbgId].ucMvBufNs); ucFbIdx++)
        {
            _arFbg[ucFbgId].au4AddrMv[ucFbIdx] = u4YAddr; //YAddr End Storge MV buffer

            FBM_Check_AddrIsOverLap(u4YAddr,u4VP9MVSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
            u4YAddr += u4VP9MVSize;
            _arFbg[ucFbgId].u4WorkBufSize += u4VP9MVSize;

            LOG(1,"VP9:AddrMv[%d] 0x%lx size(%x)\n",ucFbIdx,
                _arFbg[ucFbgId].au4AddrMv[ucFbIdx],u4VP9MVSize);
        }

        u4YAddr = FBM_ALIGN_MASK(u4YAddr,FBM_VP9_MV_ALIGMENT);
        FBM_Check_AddrIsOverLap(u4YAddr,u4MiscSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
        _arFbg[ucFbgId].au4MiscTblStartAddr = u4YAddr;
        LOG(1,"VP9 Misc 0x%lx PoolEnd(%lx)\n",u4YAddr,u4FbEndPoolYAddr);


        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyBQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)(_arFbg[ucFbgId].ucFbNs - FBM_REF_FB_NS_PER_GROUP)) == OSR_OK);

#ifdef CC_VDP_FULL_ISR
        _arFbg[ucFbgId].hEmptyQSemaphore.prState = &_rState;
        _arFbg[ucFbgId].hEmptyBQSemaphore.prState = &_rState;
#endif


        // Nivia and William Co-design
        _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;

        ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
        ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    }
	else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1)
    {
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_FMG_Y_ALIGMENT);
        
        FBM_Check_AddrIsOverLap(u4YAddr,FBM_MISC_BUFFER_SIZE_AV1,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
        _arFbg[ucFbgId].au4MiscTblStartAddr = u4YAddr;
        LOG(1,"AV1 Misc start(0x%lx) size(0x%x) PoolEnd(%lx)",u4YAddr,FBM_MISC_BUFFER_SIZE_AV1,u4FbEndPoolYAddr);


        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyBQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)(_arFbg[ucFbgId].ucFbNs - FBM_REF_FB_NS_PER_GROUP)) == OSR_OK);

#ifdef CC_VDP_FULL_ISR
        _arFbg[ucFbgId].hEmptyQSemaphore.prState = &_rState;
        _arFbg[ucFbgId].hEmptyBQSemaphore.prState = &_rState;
#endif


        // Nivia and William Co-design
        _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;

        ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
        ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    }

    FBM_ChangeResolution(ucFbgId,u4HSize,u4VSize,TRUE);

    return FBM_RETURN_OK;

alloc_fb_fail:
    return FBM_RETURN_ERROR;
}


static UINT32 FBM_AllocNormalFB(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,
                                UINT32 u4YSize,UINT32 u4CSize,UINT32 u4HSize,UINT32 u4VSize)
{
    UINT32 u4MvReservedSize = 0;
    UCHAR ucFbIdx = 0;
    UCHAR ucMaxFb = FBM_MAX_FB_COUNT;
    UCHAR ucFbCount = 0;
    UPTR u4YAddr,u4CAddr;
    UINT32 u4MvSize =0;
    UCHAR ucPoolCount = 2;
    BOOL fgPool2Used = FALSE;
    UINT32 u4OriYSize = u4YSize;
    UPTR u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    UPTR u4FbEndPoolYAddr   = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    UPTR u4FbStartPoolCAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;
    UPTR u4FbEndPoolCAddr   = _arFbg[ucFbgId].u4FbEndPoolCAddr;
    UINT32 u4MiscSize = FBM_MISC_BUFFER_SIZE(u4HSize,u4VSize);
    UINT32 u4VP9MVSize = FBM_VP9_MV_BUFFER_SIZE(u4HSize,u4VSize);

    ucFbCount = FBM_CalcMaxFBNum(ucFbgId,prPar,u4HSize,u4VSize);
    if(ucFbCount != 0)
    {
        ucMaxFb = ucFbCount;
    }

    _arFbg[ucFbgId].ucFbNsBase = 0;
    if(ucMaxFb != FBM_MAX_FB_COUNT)
    {
        _arFbg[ucFbgId].ucFbNs = _arFbg[ucFbgId].ucFbNsBase + ucMaxFb;
    }

    if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)
        && (_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_4K2K_JPEG))
    {
        return FBM_Alloc4KJpegFB(ucFbgId,prPar,u4YSize,u4CSize,u4HSize,u4VSize,ucMaxFb);
    }
    else if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)
        && (_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_8K_JPEG))
    {
        return FBM_Alloc8KJpegFB(ucFbgId,prPar,u4YSize,u4CSize,u4HSize,u4VSize,ucMaxFb);
    }
    else if(prPar && prPar->fgStillImage)
    {
        return FBM_AllocStillImageFB(ucFbgId,prPar,u4YSize,u4CSize,u4HSize,u4VSize,ucMaxFb);
    }
    
    if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264)
    {
        if (_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_1080HD_RR)
        {
            u4MvSize = u4YSize >> 1;
        }
        else
        {
            u4MvSize = u4YSize >> 2;
        }
        u4MvSize = FBM_ALIGN_MASK(u4MvSize, FBM_B2R_H_PITCH);
    }
    else if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265)
    {
        u4MvSize = u4YSize >> 4;
        u4MvSize = FBM_ALIGN_MASK(u4MvSize, FBM_B2R_H_PITCH);
    }
    else if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9)
    {
        u4MvReservedSize += (u4VP9MVSize<<1);
        u4MvReservedSize += u4MiscSize;
        u4MvReservedSize += FBM_VDEC_WORKING_ALIGNMENT;
    }
    else if(_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1)
    {
        u4MvReservedSize += FBM_MISC_BUFFER_SIZE_AV1;
        u4MvReservedSize += FBM_VDEC_WORKING_ALIGNMENT;
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_MPEG4)
    {
        u4MvReservedSize += FBM_WORK_BUF_SIZE;
    }

    LOG(2,"Reserve Size (0x%x)\n",u4MvReservedSize);

    u4YAddr = _arFbg[ucFbgId].u4FbStartPoolYAddr;
    u4CAddr = _arFbg[ucFbgId].u4FbStartPoolCAddr;

    if((_arFbg[ucFbgId].u4FbEndPool2YAddr == _arFbg[ucFbgId].u4FbStartPool2YAddr)
       || (_arFbg[ucFbgId].u4FbEndPool2YAddr == 0))
    {
        ucPoolCount = 1;
    }

    if(_arFbg[ucFbgId].fg10Bit)
    {
        u4YSize = FBM_ALIGN_MASK(((u4YSize*5)>>2), FBM_FMG_Y_ALIGMENT);
        u4CSize = FBM_ALIGN_MASK(((u4CSize*5)>>2), FBM_FMG_Y_ALIGMENT);
    }

    if(_arFbg[ucFbgId].u4FbEndPoolCAddr == _arFbg[ucFbgId].u4FbStartPoolCAddr)
    {
        //no mpegC
        UINT32 u4FBSize = u4YSize + u4CSize;
        LOG(0,"No mepgC case\n");
        if(ucPoolCount == 1)
        {
            u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr - u4MvReservedSize;
        }

        for (ucFbIdx = 0; ucFbIdx < ucMaxFb; ucFbIdx++)
        {
            if (prPar &&(prPar->fgUFO || prPar->fgThumbnailMode))
            {
                if(((u4YAddr + u4FBSize + (u4FBSize>>8)+ FBM_8K_SIZE*2) > u4FbEndPoolYAddr) &&
                   (!fgPool2Used))
                {
                    _FBM_CheckRemainMemSize(TRUE,u4YAddr,u4FBSize,u4FbEndPoolYAddr);
                    if (ucPoolCount == 1 && ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        if(prPar && (prPar->u1RefNum > 0))
                        {
                            if (ucFbIdx > prPar->u1RefNum + 3)
                            {
                                LOG(0,"vdec asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                                break;
                            }
                        }
                        else
                        {
                            LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                            break;
                        }
                    }
                    if(ucPoolCount == 1)
                    {
                        LOG(0,"vdec asign refnum(%d),fbm need use pool2 from (%d)\n",ucMaxFb,ucFbIdx);
                        if (FBM_AllocPool2(ucFbgId) != FBM_RETURN_OK)
                        {
                            goto alloc_fb_fail;
                        }
                        ucPoolCount = 2;
                    }
                    u4YAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPool2YAddr - u4MvReservedSize;
                    fgPool2Used = TRUE;
                }
                else if ((u4YAddr + u4FBSize + (u4FBSize>>8)+ FBM_8K_SIZE*2) > u4FbEndPoolYAddr)
                {
                    if(ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                        break;
                    }
                    else
                    {
                        LOG(0,"buffer is not enough for fb(%d)\n",ucFbIdx);
                        goto alloc_fb_fail;
                    }
                }
            }
            else
            {
                if(((u4YAddr + u4FBSize + FBM_8K_SIZE) > u4FbEndPoolYAddr) &&
                   (!fgPool2Used))
                {
                    _FBM_CheckRemainMemSize(TRUE,u4YAddr,u4FBSize,u4FbEndPoolYAddr);
                    if (ucPoolCount == 1 && ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        if(prPar && (prPar->u1RefNum > 0))
                        {
                            if (ucFbIdx > prPar->u1RefNum + 3)
                            {
                                LOG(0,"vdec asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                                break;
                            }
                        }
                        else
                        {
                            LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                            break;
                        }
                    }
                    if(ucPoolCount == 1)
                    {
                        LOG(0,"vdec asign refnum(%d),fbm need use pool2 from (%d)\n",ucMaxFb,ucFbIdx);
                        if (FBM_AllocPool2(ucFbgId) != FBM_RETURN_OK)
                        {
                            goto alloc_fb_fail;
                        }
                        ucPoolCount = 2;
                    }
                    u4YAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4FbStartPoolYAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPool2YAddr - u4MvReservedSize;
                    fgPool2Used = TRUE;
                }
                else if ((u4YAddr + u4FBSize + FBM_8K_SIZE) > u4FbEndPoolYAddr)
                {
                    if(ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                        break;
                    }
                    else
                    {
                        LOG(0,"buffer is not enough for fb(%d)\n",ucFbIdx);
                        goto alloc_fb_fail;
                    }
                }
            }
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
            u4YAddr += u4YSize;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrY[ucFbIdx],0x00000000,u4YSize);
            }
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY[ucFbIdx],u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4YAddr;
            u4YAddr += u4CSize;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrC[ucFbIdx],0x80808080,u4CSize);
            }
            FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC[ucFbIdx],u4CSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(0,"ucFbgId(%d) au4AddrY[%d] 0x%lx au4AddrC[%d] 0x%lx\n",
                    ucFbgId,ucFbIdx,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdx],
                    ucFbIdx,_arFbg[ucFbgId].au4AddrC[ucFbIdx]);
            }
            if (prPar && (prPar->fgUFO || prPar->fgThumbnailMode))
            {
                u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
                _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx] = u4YAddr;
                u4YAddr += (u4YSize>>8);
                

                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],0xFFFFFFFF,(u4YSize>>8));

                FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],(u4YSize>>8),u4FbStartPoolYAddr,u4FbEndPoolYAddr);
                u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_C_ALIGMENT);
                _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx] = u4YAddr;
                u4YAddr += (u4CSize>>8);
                
   
                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],0xFFFFFFFF,(u4CSize>>8));
                FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],(u4CSize>>8),u4FbStartPoolYAddr,u4FbEndPoolYAddr);

                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                {
                    LOG(1,"ucFbgId(%d) au4AddrY_Ext[%d] 0x%lx au4AddrC_Ext[%d] 0x%lx\n",
                        ucFbgId,  ucFbIdx,
                        _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],
                        ucFbIdx, _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx]);
                }
            }
            u4MvReservedSize += u4MvSize;
            if ((ucPoolCount == 1) || fgPool2Used)
            {
                u4FbEndPoolYAddr = u4FbEndPoolYAddr - u4MvSize;
            }
        }

        _arFbg[ucFbgId].u4MvStartAddr = u4YAddr;
        _arFbg[ucFbgId].ucFbNs = ucFbIdx;
    }
    else
    {
        //YC
        if(ucPoolCount == 1)
        {
            u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr - u4MvReservedSize;
        }

        for (ucFbIdx = 0; ucFbIdx < ucMaxFb; ucFbIdx++)
        {
            if (prPar && (prPar->fgUFO || prPar->fgThumbnailMode))
            {
                if((((u4YAddr + u4YSize + (u4YSize>>8)+ FBM_8K_SIZE) > u4FbEndPoolYAddr) ||
                    ((u4CAddr + u4CSize + (u4CSize>>8)+ FBM_8K_SIZE) > u4FbEndPoolCAddr))&&
                   (!fgPool2Used))
                {
                    _FBM_CheckRemainMemSize(TRUE,u4YAddr,u4YSize,u4FbEndPoolYAddr);
                    _FBM_CheckRemainMemSize(TRUE,u4CAddr,u4CSize,u4FbEndPoolCAddr);
                    if (ucPoolCount == 1 && ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        if(prPar->u1RefNum > 0)
                        {
                            if (ucFbIdx > prPar->u1RefNum + 3)
                            {
                                LOG(0,"vdec asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                                break;
                            }
                        }
                        else
                        {
                            LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                            break;
                        }
                    }
                    if(ucPoolCount == 1)
                    {
                        LOG(0,"vdec asign refnum(%d),fbm need use pool2 from (%d)\n",ucMaxFb,ucFbIdx);
                        if (FBM_AllocPool2(ucFbgId) != FBM_RETURN_OK)
                        {
                            goto alloc_fb_fail;
                        }
                        ucPoolCount = 2;
                    }
                    u4YAddr             = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4CAddr             = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                    u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbEndPool2YAddr - u4MvReservedSize;
                    u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                    u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbEndPool2CAddr;
                    fgPool2Used         = TRUE;
                }
                else if (((u4YAddr + u4YSize + (u4YSize>>8)+ FBM_8K_SIZE) > u4FbEndPoolYAddr) ||
                         ((u4CAddr + u4CSize + (u4CSize>>8)+ FBM_8K_SIZE) > u4FbEndPoolCAddr))
                {
                    if(ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                        break;
                    }
                    else
                    {
                        LOG(0,"buffer is not enough for fb(%d)\n",ucFbIdx);
                        goto alloc_fb_fail;
                    }
                }
            }
            else
            {
                if((((u4YAddr + u4YSize + FBM_8K_SIZE) > u4FbEndPoolYAddr) ||
                    ((u4CAddr + u4CSize + FBM_8K_SIZE) > u4FbEndPoolCAddr))&&
                   (!fgPool2Used))
                {
                    _FBM_CheckRemainMemSize(TRUE,u4YAddr,u4YSize,u4FbEndPoolYAddr);
                    if (ucPoolCount == 1 && ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        if(prPar && (prPar->u1RefNum > 0))
                        {
                            if (ucFbIdx > prPar->u1RefNum + 3)
                            {
                                LOG(0,"vdec asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                                break;
                            }
                        }
                        else
                        {
                            LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                            break;
                        }
                    }
                    if(ucPoolCount == 1)
                    {
                        LOG(0,"vdec asign refnum(%d),fbm need use pool2 from (%d)\n",ucMaxFb,ucFbIdx);
                        if (FBM_AllocPool2(ucFbgId) != FBM_RETURN_OK)
                        {
                            goto alloc_fb_fail;
                        }
                        ucPoolCount = 2;
                    }
                    u4YAddr             = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4CAddr             = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                    u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbStartPool2YAddr;
                    u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbEndPool2YAddr - u4MvReservedSize;
                    u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbStartPool2CAddr;
                    u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbEndPool2CAddr;
                    fgPool2Used         = TRUE;
                }
                else if (((u4YAddr + u4YSize + FBM_8K_SIZE) > u4FbEndPoolYAddr) ||
                         ((u4CAddr + u4CSize + FBM_8K_SIZE) > u4FbEndPoolCAddr))
                {
                    if(ucMaxFb == FBM_MAX_FB_COUNT)
                    {
                        LOG(0,"vdec do not asign refnum, fbm alloc max (%d) fb OK\n",ucFbIdx);
                        break;
                    }
                    else
                    {
                        LOG(0,"buffer is not enough for fb(%d)\n",ucFbIdx);
                        goto alloc_fb_fail;
                    }
                }
            }

            u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);
            _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((void*)(u4YAddr),0x00000000,u4YSize);
            }
            FBM_Check_AddrIsOverLap(u4YAddr,u4YSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr)
            u4YAddr += u4YSize;

            u4CAddr = FBM_ALIGN_MASK(u4CAddr, FBM_GFX_C_ALIGMENT);
            _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4CAddr;
            
            if(prPar && FBM_CheckMemsetOption(prPar->u4FBMMemsetOption, ucFbIdx))
            {
                FBM_GDMA_MEMSET((VOID*)u4CAddr,0x80808080,u4CSize);
            }
            FBM_Check_AddrIsOverLap(u4CAddr,u4CSize,u4FbStartPoolCAddr,u4FbEndPoolCAddr)
            u4CAddr += u4CSize;

            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
            {
                LOG(0,"ucFbgId(%d) au4AddrY[%d] 0x%lx au4AddrC[%d] 0x%lx\n",
                    ucFbgId,ucFbIdx,
                    _arFbg[ucFbgId].au4AddrY[ucFbIdx],
                    ucFbIdx,_arFbg[ucFbgId].au4AddrC[ucFbIdx]);
            }

            if (prPar && (prPar->fgUFO || prPar->fgThumbnailMode))
            {
                u4YAddr = FBM_ALIGN_MASK(u4YAddr, FBM_GFX_Y_ALIGMENT);

                _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx] = u4YAddr;
                u4YAddr += (u4YSize>>8);
                

                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],0xFFFFFFFF,(u4YSize>>8));

                FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],(u4YSize>>8),u4FbStartPoolYAddr,u4FbEndPoolYAddr);

                u4CAddr = FBM_ALIGN_MASK(u4CAddr, FBM_GFX_C_ALIGMENT);

                _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx] = u4CAddr;
                u4CAddr += (u4CSize>>8);
                
  
                FBM_GDMA_MEMSET((VOID*)_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],0xFFFFFFFF,(u4CSize>>8));
                FBM_Check_AddrIsOverLap(_arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],(u4CSize>>8),u4FbStartPoolCAddr,u4FbEndPoolCAddr);

                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                {
                    LOG(1,"ucFbgId(%d) au4AddrY_Ext[%d] 0x%lx au4AddrC_Ext[%d] 0x%lx line(%d)\n",
                        ucFbgId,  ucFbIdx,
                        _arFbg[ucFbgId].au4AddrY_Ext[ucFbIdx],
                        ucFbIdx, _arFbg[ucFbgId].au4AddrC_Ext[ucFbIdx],__LINE__);
                }
            }

            u4MvReservedSize += u4MvSize;
            if ((ucPoolCount == 1) || fgPool2Used)
            {
                u4FbEndPoolYAddr = u4FbEndPoolYAddr - u4MvSize;
            }
        }

        _arFbg[ucFbgId].u4MvStartAddr = u4YAddr;
        _arFbg[ucFbgId].ucFbNs = ucFbIdx;
    }

    if ((u4FbEndPoolYAddr >= _arFbg[ucFbgId].u4FbStartPoolYAddr) &&
        (u4FbEndPoolYAddr <= _arFbg[ucFbgId].u4FbEndPoolYAddr))
    {
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPoolYAddr;
    }
    else if ((u4FbEndPoolYAddr >= _arFbg[ucFbgId].u4FbStartPool2YAddr) &&
             (u4FbEndPoolYAddr <= _arFbg[ucFbgId].u4FbEndPool2YAddr))
    {
        u4FbEndPoolYAddr = _arFbg[ucFbgId].u4FbEndPool2YAddr;
    }
    else
    {
        LOG(0,"u4FbEndPoolYAddr is out of pool\n");
    }

    if ((_arFbg[ucFbgId].u4MvStartAddr >= _arFbg[ucFbgId].u4FbStartPoolYAddr) &&
        (_arFbg[ucFbgId].u4MvStartAddr <= _arFbg[ucFbgId].u4FbEndPoolYAddr))
    {
        if ((_arFbg[ucFbgId].u4MvStartAddr + u4MvReservedSize > _arFbg[ucFbgId].u4FbEndPoolYAddr) &&
            (ucPoolCount == 2))
        {
            LOG(2,"alloc mv in pool2\n");
            _arFbg[ucFbgId].u4MvStartAddr = _arFbg[ucFbgId].u4FbStartPool2YAddr;
        }
    }

    //MV buffer
    if((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
       (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
       (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
    {
        if (ucFbIdx > 2)
        {
            _arFbg[ucFbgId].ucMvBufNs = ucFbIdx - 2;
        }
        else
        {
            goto alloc_fb_fail;
        }
        if(FBM_CfgMvbuffer(ucFbgId,u4OriYSize,_arFbg[ucFbgId].ucMvBufNs) != FBM_RETURN_OK)
        {
            goto alloc_fb_fail;
        }
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_MPEG2)
    {
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_B2R_H_PITCH);

        _arFbg[ucFbgId].au4AddrMv[0] = u4YAddr;

        if ((ucFbIdx >= FBM_DBK_FB_NS) && (_arFbg[ucFbgId].ucFbgType != FBM_FBG_TYPE_1080HD_RR))
        {
            if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                ASSERT(ucFbIdx < FBM_MAX_FB_NS_PER_GROUP);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_RETURN_OK;
            }
            if (_arFbg[ucFbgId].u4FbEndPoolCAddr == _arFbg[ucFbgId].u4FbStartPoolCAddr)
            {
                _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
                _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4YAddr + u4YSize;
            }
            else
            {
                _arFbg[ucFbgId].au4AddrY[ucFbIdx] = u4YAddr;
                _arFbg[ucFbgId].au4AddrC[ucFbIdx] = u4CAddr;
            }
        }
        _arFbg[ucFbgId].u4WorkBufSize = u4FbEndPoolYAddr - _arFbg[ucFbgId].au4AddrMv[0];
        LOG(1,"MPEG2 Mv Addr 0x%lx size(%x)\n",u4YAddr,_arFbg[ucFbgId].u4WorkBufSize);
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RV)
    {
        LOG(1,"RM Before working Buffer 64 Align u4Addr 0x%lx\n",u4YAddr);
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_B2R_H_PITCH);
        LOG(1,"RM After working Buffer 64 Align u4Addr 0x%lx\n",u4YAddr);
        _arFbg[ucFbgId].au4AddrMv[0] = u4YAddr;
        _arFbg[ucFbgId].u4WorkBufSize = u4FbEndPoolYAddr - _arFbg[ucFbgId].au4AddrMv[0];
        LOG(1,"RV Mv Addr 0x%lx size(%x)\n",u4YAddr,_arFbg[ucFbgId].u4WorkBufSize);
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_MPEG4)
    {
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_B2R_H_PITCH);
        _arFbg[ucFbgId].au4AddrMv[0] = u4YAddr;
        _arFbg[ucFbgId].u4WorkBufSize = u4FbEndPoolYAddr - _arFbg[ucFbgId].au4AddrMv[0];
        LOG(1,"MPEG4 Mv Addr 0x%lx size(%x)\n",u4YAddr,_arFbg[ucFbgId].u4WorkBufSize);
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9)
    {
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_VP9_MV_ALIGMENT);
        for (ucFbIdx = 0;
             ((ucFbIdx < _arFbg[ucFbgId].ucMvBufNs)&&(ucFbIdx < (FBM_MAX_FB_NS_PER_GROUP-1))); ucFbIdx++)
        {
            _arFbg[ucFbgId].au4AddrMv[ucFbIdx] = u4YAddr; //YAddr End Storge MV buffer

            FBM_Check_AddrIsOverLap(u4YAddr,u4VP9MVSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);

            u4YAddr += u4VP9MVSize;

            _arFbg[ucFbgId].u4WorkBufSize += u4VP9MVSize;

            LOG(1,"VP9:AddrMv[%d] 0x%lx size(%x)\n",ucFbIdx,
                _arFbg[ucFbgId].au4AddrMv[ucFbIdx],u4VP9MVSize);
        }

        u4YAddr = FBM_ALIGN_MASK(u4YAddr,FBM_VP9_MV_ALIGMENT);
        FBM_Check_AddrIsOverLap(u4YAddr,u4MiscSize,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
        _arFbg[ucFbgId].au4MiscTblStartAddr = u4YAddr;
        LOG(1,"VP9 Misc 0x%lx\n PoolEnd(%lx)",u4YAddr,u4FbEndPoolYAddr);
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1)
    {
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_FMG_Y_ALIGMENT);
        FBM_Check_AddrIsOverLap(u4YAddr,FBM_MISC_BUFFER_SIZE_AV1,u4FbStartPoolYAddr,u4FbEndPoolYAddr);
        _arFbg[ucFbgId].au4MiscTblStartAddr = u4YAddr;
        LOG(1,"AV1 Misc start(0x%lx) size(0x%x) PoolEnd(%lx)",u4YAddr,FBM_MISC_BUFFER_SIZE_AV1,u4FbEndPoolYAddr);
    }
    else if (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)
    {
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_B2R_H_PITCH);
        _arFbg[ucFbgId].au4AddrMv[0] = u4YAddr;
        _arFbg[ucFbgId].u4WorkBufSize = u4FbEndPoolYAddr - _arFbg[ucFbgId].au4AddrMv[0];
        LOG(1,"MJPEG Mv Addr 0x%lx size(%x)\n",u4YAddr,_arFbg[ucFbgId].u4WorkBufSize);
    }
    else    //VC-1 and RM
    {
        ASSERT(_arFbg[ucFbgId].u4VDecFmt != FBM_VDEC_UNKNOWN);
        u4YAddr = FBM_ALIGN_MASK(_arFbg[ucFbgId].u4MvStartAddr, FBM_B2R_H_PITCH);
        _arFbg[ucFbgId].au4AddrMv[0] = u4YAddr;
        _arFbg[ucFbgId].u4WorkBufSize = u4FbEndPoolYAddr - _arFbg[ucFbgId].au4AddrMv[0];
        LOG(1,"Codec %d Mv Addr 0x%lx size(%x)\n",_arFbg[ucFbgId].u4VDecFmt,u4YAddr,_arFbg[ucFbgId].u4WorkBufSize);
    }

    _arFbg[ucFbgId].u4ExtraYBuffer =0;
    _arFbg[ucFbgId].u4ExtraCBuffer =0;

    if ((_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8)||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6)||
        (_arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))

    {
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);
    }
    else
    {
        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)0) == OSR_OK);

        VERIFY(_FBM_csema_reset(&_arFbg[ucFbgId].hEmptyBQSemaphore, _arFbg[ucFbgId].hMutex, (INT32)(_arFbg[ucFbgId].ucFbNs - FBM_REF_FB_NS_PER_GROUP)) == OSR_OK);

#ifdef CC_VDP_FULL_ISR
        _arFbg[ucFbgId].hEmptyQSemaphore.prState = &_rState;
        _arFbg[ucFbgId].hEmptyBQSemaphore.prState = &_rState;
#endif
    }

    // Nivia and William Co-design
    _arFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbFRef = FBM_FB_ID_UNKNOWN;
    _arFbg[ucFbgId].ucFbBRef = FBM_FB_ID_UNKNOWN;

    for (ucFbIdx = _arFbg[ucFbgId].ucFbNsBase; ucFbIdx < _arFbg[ucFbgId].ucFbNs; ucFbIdx++)
    {
        _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbIdx);
    }

    ASSERT(_arFbg[ucFbgId].hEmptyQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);
    ASSERT(_arFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _arFbg[ucFbgId].hMutex);

    return FBM_RETURN_OK;

alloc_fb_fail:
    return FBM_RETURN_ERROR;
}

static UINT32 FBM_AllocFb(UCHAR ucFbgId,FBM_CREATE_FBG_PAR_T *prPar,
                          UINT32 u4YSize,UINT32 u4CSize,UINT32 u4HSize,UINT32 u4VSize)
{
    if(VERIFY_FBG(ucFbgId))
    {
        return FBM_RETURN_ERROR;
    }

    if(u4YSize == 0 || u4CSize == 0)
    {
        return FBM_RETURN_ERROR;
    }

    if (_arFbg[ucFbgId].eResolutionChangeMode != FBM_RESOLUTION_CHANGE_MODE_NONE)
    {
        if(prPar == NULL)
        {
            LOG(0,"Error Seamless playback, prPar is NULL\n");
            return FBM_RETURN_ERROR;
        }
        if (FBM_AllocSeamlessFB(ucFbgId,prPar,u4YSize,u4CSize,u4HSize,u4VSize) != FBM_RETURN_OK)
        {
            LOG(0,"alloc seamless FB fail\n");
            return FBM_RETURN_ERROR;
        }
        return FBM_RETURN_OK;
    }

    if (FBM_AllocNormalFB(ucFbgId,prPar,u4YSize,u4CSize,u4HSize,u4VSize) != FBM_RETURN_OK)
    {
        LOG(0,"alloc normal FB fail\n");
        return FBM_RETURN_ERROR;
    }
    return FBM_RETURN_OK;
}

static UINT32 FBM_AllocStillImagePool(UCHAR ucFbgId,UINT32 u4YSize,UINT32 u4CSize,FBM_CREATE_FBG_PAR_T *prPar)
{
    FBM_POOL_T* prFbmPool = NULL;
    prFbmPool = FBM_GetPoolInfo((UINT8)FBM_POOL_TYPE_MPEG);
    LOG(0,"alloc FBM_AllocStillImagePool\n");
    
    if(_arFbg[ucFbgId].fg10Bit)
    {
        u4YSize = FBM_ALIGN_MASK(((u4YSize*5)>>2), FBM_FMG_Y_ALIGMENT);
        u4CSize = FBM_ALIGN_MASK(((u4CSize*5)>>2), FBM_FMG_Y_ALIGMENT);
    }
    
    if (prFbmPool)
    {
        _arFbg[ucFbgId].u4FbMemoryPool      = prFbmPool->u4Addr;
        //Ysize + Mvsize = u4YSize >> 4
        _arFbg[ucFbgId].u4FbMemoryPoolC     = prFbmPool->u4Addr + u4YSize + (u4YSize >> 4) +  2*FBM_8K_SIZE;
        
        _arFbg[ucFbgId].u4FbStartPoolYAddr  = _arFbg[ucFbgId].u4FbMemoryPool;
        _arFbg[ucFbgId].u4FbEndPoolYAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC;
        _arFbg[ucFbgId].u4FbStartPoolCAddr  = _arFbg[ucFbgId].u4FbMemoryPoolC;
        _arFbg[ucFbgId].u4FbEndPoolCAddr    = _arFbg[ucFbgId].u4FbMemoryPoolC + u4CSize + FBM_8K_SIZE;
        
        _arFbg[ucFbgId].u4FbMemoryPoolSize  = u4YSize + u4CSize + (u4YSize >> 4) + 3*FBM_8K_SIZE;

        LOG(1,"%s Y1[0x%lx-0x%lx] C1[0x%lx-0x%lx] Ysize(0x%x) Csize(0x%x) PoolSize(%d)\n",__FUNCTION__,
                _arFbg[ucFbgId].u4FbStartPoolYAddr,_arFbg[ucFbgId].u4FbEndPoolYAddr,
                _arFbg[ucFbgId].u4FbStartPoolCAddr,_arFbg[ucFbgId].u4FbEndPoolCAddr,
                u4YSize,u4CSize,_arFbg[ucFbgId].u4FbMemoryPoolSize);
    }
    else
    {
        LOG(0,"alloc StillImagePool buffer fail\n");
        return FBM_RETURN_ERROR;
    }
    return FBM_RETURN_OK;
}

static UINT32 FBM_ConfigFrameBuffer(UCHAR ucFbgId, UINT32 u4HSize,UINT32 u4VSize, FBM_CREATE_FBG_PAR_T *prPar)
{
    UINT32 u4YSize = 0,u4CSize=0;

    if(VERIFY_FBG(ucFbgId))
    {
        return FBM_RETURN_ERROR;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_arFbg[ucFbgId].eResolutionChangeMode != FBM_RESOLUTION_CHANGE_MODE_NONE)
    {
        if(prPar == NULL)
        {
            LOG(0,"Error Seamless playback, prPar is NULL\n");
            goto config_fbg_fail;
        }
    }

    if (_arFbg[ucFbgId].fgMvAllocate == FALSE)
    {
        BOOL fgAlloc4K8KBuffer = FALSE;

        if ((FBM_FBG_PAL_H > u4HSize) && (FBM_FBG_PAL_V > u4VSize))
        {
            u4HSize = FBM_FBG_PAL_H;
            u4VSize = FBM_FBG_PAL_V;
        }
        if (_arFbg[ucFbgId].eResolutionChangeMode == FBM_RESOLUTION_CHANGE_MODE_NONE)
        {
            _arFbg[ucFbgId].u4FbWidth = FBM_ALIGN_MASK(u4HSize,FBM_B2R_H_PITCH);
            _arFbg[ucFbgId].u4FbHeight = FBM_ALIGN_MASK(u4VSize,FBM_B2R_H_PITCH);
        }
        else
        {
            if (prPar)
            {
                _arFbg[ucFbgId].u4FbWidth = FBM_ALIGN_MASK(prPar->u4TargetW,FBM_B2R_H_PITCH);
                _arFbg[ucFbgId].u4FbHeight = FBM_ALIGN_MASK(prPar->u4TargetH,FBM_B2R_H_PITCH);
            }
            else
            {
                LOG(0,"Error %s line(%d)\n",__FUNCTION__,__LINE__);
                return FBM_RETURN_ERROR;
            }
        }
        u4YSize = FBM_ALIGN_MASK((_arFbg[ucFbgId].u4FbWidth * _arFbg[ucFbgId].u4FbHeight), FBM_FMG_Y_ALIGMENT);
        u4CSize = FBM_ALIGN_MASK((u4YSize >> 1),FBM_FMG_Y_ALIGMENT);

        if (_arFbg[ucFbgId].ucFbgCm == FBM_CM_422)
        {
            u4CSize *= 2;
        }
        else if(_arFbg[ucFbgId].ucFbgCm == FBM_CM_444)
        {
            u4CSize *= 4;
        }

        LOG(1,"Ysize(0x%x) Csize(0x%x)\n",u4YSize,u4CSize);
        if (u4YSize > FBM_FBG_TYPE_1080HD_Y_SIZE)
        {
            fgAlloc4K8KBuffer = TRUE;
        }

        if(prPar && prPar->fgNonBuf)
        {
            if (FBM_AllocFakePool(ucFbgId,prPar) != FBM_RETURN_OK)
            {
                goto config_fbg_fail;
            }
        }
        else if (_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_4K2K_JPEG
            && _arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)
        {
            if (FBM_Alloc4KJpegPool(ucFbgId,u4YSize,u4CSize,prPar) != FBM_RETURN_OK)
            {
                goto config_fbg_fail;
            }
        }
        else if (prPar && prPar->fgStillImage)
        {
            if (FBM_AllocStillImagePool(ucFbgId,u4YSize,u4CSize,prPar) != FBM_RETURN_OK)
            {
                goto config_fbg_fail;
            }
            _arFbg[ucFbgId].u4VDecFmt = FBM_VDEC_H265;
        }        
        else if(_arFbg[ucFbgId].ucFbgType == FBM_FBG_TYPE_8K_JPEG
            && _arFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)
        {
            if (FBM_Alloc8KJpegPool(ucFbgId,prPar) != FBM_RETURN_OK)
            {
                goto config_fbg_fail;
            }
        }
        else if(fgAlloc4K8KBuffer)
        {
            if (FBM_Alloc4K8KVideoPool(ucFbgId,prPar) != FBM_RETURN_OK)
            {
                goto config_fbg_fail;
            }
        }
        else
        {
            if (FBM_Alloc2KVideoAndJpegPool(ucFbgId,prPar) != FBM_RETURN_OK)
            {
                goto config_fbg_fail;
            }
        }

        if (FBM_AllocFb(ucFbgId,prPar,u4YSize,u4CSize,u4HSize,u4VSize) != FBM_RETURN_OK)
        {
            goto config_fbg_fail;
        }

        _arFbg[ucFbgId].fgMvAllocate = TRUE;
    }
    FBM_MUTEX_UNLOCK(ucFbgId);
    return FBM_RETURN_OK;
config_fbg_fail:
    FBM_MUTEX_UNLOCK(ucFbgId);
    return FBM_RETURN_ERROR;

}

static UCHAR FBM_InitFbgInfo(FBM_CREATE_FBG_PAR_T *prPar)
{
    UCHAR ucFbgId;
    UCHAR ucFbId = 0;
    UINT32 u4MallocSize;
#if defined(CC_SUPPORT_DOLBY_VISION)||defined (CC_SUPPORT_TECHNICOLOR_HDR)
    FBM_PIC_HDR_T* prPicHdr = NULL;
    UPTR u4RpuBuffer = 0;
    UINT32 u4Count;
#endif

    for (ucFbgId = 0; ucFbgId < FBG_MAX_NS; ucFbgId++)
    {
        if (_arFbg[ucFbgId].ucFbgId == FBM_FBG_ID_UNKNOWN)
        {
            break;
        }
    }

    if (ucFbgId >= FBG_MAX_NS)
    {
        LOG(0,"No empty fbg now\n");
        return FBM_FBG_ID_UNKNOWN;
    }

#ifdef FBM_CS_LOG
    _u4EQHandle = (UINT32)_arFbg[ucFbgId].hEmptyQSemaphore.hBinary;
#endif
    _arFbg[ucFbgId].fgUFO   = prPar?prPar->fgUFO:0;
    _arFbg[ucFbgId].u1DecoderSrcId = prPar ? prPar->u1VdecId : 0;
    _arFbg[ucFbgId].fg10Bit = prPar?prPar->fg10Bit:0;
    _arFbg[ucFbgId].fgUFO   = prPar?prPar->fgUFO:0;
    _arFbg[ucFbgId].ucFbgId = ucFbgId;
    _arFbg[ucFbgId].fgIsGameMode = prPar?prPar->fgIsGameMode:0;
    _arFbg[ucFbgId].u1Fps = prPar?prPar->u1Fps:0;
    _arFbg[ucFbgId].u4CrtFbgCnt = 0;

    _arFbg[ucFbgId].rSeqHdr.u4PendingSOC = _arFbg[ucFbgId].u4CrtFbgCnt;
    _arFbg[ucFbgId].rSeqHdr.fgRpuBuffer = prPar?prPar->fgRpuBuffer:FALSE;
    _arFbg[ucFbgId].rSeqHdr.fgHdrBuffer = prPar?prPar->fgHdrBuffer:FALSE;
    _arFbg[ucFbgId].eDolbyType = prPar?prPar->eDolbyType:FBM_FBG_DOLBY_TYPE_NONE;
    _arFbg[ucFbgId].bByPassMJC = FALSE;
    _arFbg[ucFbgId].ucFbgCm = _u1FbgColorMode;
    _arFbg[ucFbgId].u1FbgAppMode= prPar?prPar->u1AppMode:0;
    _arFbg[ucFbgId].ucPictureId = 0;

    _arFbg[ucFbgId].u4FbMemoryPool = 0;
    _arFbg[ucFbgId].u4FbMemoryPoolC = 0;
    _arFbg[ucFbgId].u4FbMemoryPool2 = 0;
    _arFbg[ucFbgId].u4FbMemoryPool2C = 0;

    _arFbg[ucFbgId].u4FbStartPoolYAddr = 0;
    _arFbg[ucFbgId].u4FbEndPoolYAddr = 0;
    _arFbg[ucFbgId].u4FbStartPoolCAddr = 0;
    _arFbg[ucFbgId].u4FbEndPoolCAddr = 0;
    _arFbg[ucFbgId].u4FbStartPool2YAddr = 0;
    _arFbg[ucFbgId].u4FbEndPool2YAddr= 0;
    _arFbg[ucFbgId].u4FbStartPool2CAddr = 0;
    _arFbg[ucFbgId].u4FbEndPool2CAddr = 0;
    _arFbg[ucFbgId].u4TargetSize = 0;
    _arFbg[ucFbgId].fg8KMpeg = FALSE;
    _arFbg[ucFbgId].fgNonBuf = prPar?prPar->fgNonBuf:FALSE;
    _arFbg[ucFbgId].fgTunnelMode = prPar?prPar->fgTunnelMode:FALSE;
    if (_arFbg[ucFbgId].fgNonBuf)
    {
        if (prPar)
        {
            prPar->u4FBMMemsetOption = FBM_FBG_MEMSET_NONE;
        }
    }

    // Clear Flag
    _arFbg[ucFbgId].u4FbgFlag = 0;
    _arFbg[ucFbgId].ucSeqChgFbId = FBM_FB_ID_UNKNOWN;

    FBM_MEMSET((VOID*) &_arFbg[ucFbgId].rSeqChgPendingQ,0x0,sizeof(FBM_SEQ_CHG_QUE_T));
    _arFbg[ucFbgId].fgSeqNoEqual = FALSE;
    _arFbg[ucFbgId].fgRlsDispQue = FALSE;

    // Determine number of frame buffer, later
    _arFbg[ucFbgId].ucFbNs = FBM_MAX_FB_NS_PER_GROUP;

    // Allocalte memory for picture header
    u4MallocSize = _arFbg[ucFbgId].ucFbNs * (sizeof(FBM_PIC_HDR_T));

    if (_arFbg[ucFbgId].pMallocAddr == NULL)
    {
        _arFbg[ucFbgId].pMallocAddr = x_mem_alloc_virtual(u4MallocSize);
        if (_arFbg[ucFbgId].pMallocAddr == NULL)
        {
            LOG(0,"Err:alloc pichdr fail fbg(%d) sz(0x%x)\n",ucFbgId,u4MallocSize);
            return FBM_FBG_ID_UNKNOWN;
        }
    }
    _arFbg[ucFbgId].prPicHdr = (FBM_PIC_HDR_T *)_arFbg[ucFbgId].pMallocAddr;

    FBM_MEMSET(_arFbg[ucFbgId].pMallocAddr, 0, u4MallocSize);

#if defined(CC_SUPPORT_DOLBY_VISION)||defined (CC_SUPPORT_TECHNICOLOR_HDR)

    u4RpuBuffer = _arFbg[ucFbgId].u4RpuPhysicalAddr;
    prPicHdr = _arFbg[ucFbgId].prPicHdr;

    if(u4RpuBuffer == 0)
    {
        u4RpuBuffer = BSP_AllocAlignedDmaMemory(FBM_RPU_BUF_MAX_SIZE*_arFbg[ucFbgId].ucFbNs, 16);
        if(!u4RpuBuffer && (_arFbg[ucFbgId].rSeqHdr.fgRpuBuffer || _arFbg[ucFbgId].rSeqHdr.fgHdrBuffer))
        {
            LOG(0,"Alloc RPU buffer fail @Dolby playback\n");
            return FBM_FBG_ID_UNKNOWN;
        }
        _arFbg[ucFbgId].u4RpuPhysicalAddr = u4RpuBuffer;
        LOG(0,"Alloc RPU buffer %lx fbg(%d) success\n",_arFbg[ucFbgId].u4RpuPhysicalAddr,ucFbgId);
    }
    else
    {
        LOG(1,"Rpu add 0x%lx\n",u4RpuBuffer);
    }
    if (_arFbg[ucFbgId].rSeqHdr.fgRpuBuffer || _arFbg[ucFbgId].rSeqHdr.fgHdrBuffer)
    {
        for(u4Count = 0; (u4Count < _arFbg[ucFbgId].ucFbNs) && prPicHdr; u4Count ++)
        {
            prPicHdr->u4RpuPhysicalAddr = u4RpuBuffer;
            u4RpuBuffer += FBM_RPU_BUF_MAX_SIZE;
            LOG(2,"RPU buffer = 0x%lx\n",prPicHdr->u4RpuPhysicalAddr);
            prPicHdr ++;
        }
    }
#endif


    if (prPar && (FBM_FBG_MEMSET_NONE != prPar->u4FBMMemsetOption))
    {
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_MEMSET, (UPTR)GFX_Memset);
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_TASK_MEMSET, (UPTR)GFX_Task_Memset);
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_TASK_MEMSET_DONE, (UPTR)GFX_Task_Check_Done);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_MEMSET, (UPTR)GDMA_MemSet);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_TASK_MEMSET, (UPTR)GDMA_MemSetAnsync);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE, (UPTR)IsMemOptionDone);
    }
    else
    {
        LOG(1, "No HW init FB\n");
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_MEMSET, (UPTR)NULL);
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_TASK_MEMSET, (UPTR)NULL);
        FBM_RegCbFunc(FBM_CB_FUNC_GFX_TASK_MEMSET_DONE, (UPTR)NULL);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_MEMSET, (UPTR)NULL);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_TASK_MEMSET, (UPTR)NULL);
        FBM_RegCbFunc(FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE, (UPTR)NULL);
    }

    // Init frame buffer status
    for (ucFbId = 0; ucFbId < _arFbg[ucFbgId].ucFbNs; ucFbId++)
    {
        _arFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_UNKNOWN;
        _arFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
        _arFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid = FBM_FB_ID_UNKNOWN;
        _arFbg[ucFbgId].prPicHdr[ucFbId].ucPicId = 0;
        _arFbg[ucFbgId].prPicHdr[ucFbId].fgPicFlush = FALSE;
    }


    if (FBM_PAUSE_TYPE_UNKOWN != _arFbg[ucFbgId].u4PauseType)
    {
        LOG(0,"Force Set Pause to debug ,Cur Pause Type(%d)\n",_arFbg[ucFbgId].u4PauseType);
    }
    else
    {
        _arFbg[ucFbgId].u4PauseType = FBM_PAUSE_TYPE_UNKOWN;
    }
#ifdef FBM_FB_LOG
    FbmInitFbLog();
#endif
    _arFbg[ucFbgId].u4LastB2rAcquireDispTag = INVALID_DISPTAG;
    _arFbg[ucFbgId].ucLastB2rAcquireFbId = FBM_FB_ID_UNKNOWN;

    _arFbg[ucFbgId].eFbIdType = FBM_FBID_TYPE_UNKWOWN;
    _arFbg[ucFbgId].fgMoreCreateFbg = FALSE;
    x_memset(_arImgRzTmpBufInfo,0x0,sizeof(_arImgRzTmpBufInfo));

    if (prPar && (prPar->u4TargetW > 0 && prPar->u4TargetH > 0))
    {
        _arFbg[ucFbgId].eResolutionChangeMode = FBM_RESOLUTION_CHANGE_MODE_SEAMLESS;
        _arFbg[ucFbgId].u4TargetSize =
            FBM_ALIGN_MASK((prPar->u4TargetW),FBM_B2R_H_PITCH)*FBM_ALIGN_MASK((prPar->u4TargetH),FBM_B2R_H_PITCH);
        LOG(0,"Change Mode to seamless Target W/H (%d-%d)\n",prPar->u4TargetW,prPar->u4TargetH);
    }
    else
    {
        _arFbg[ucFbgId].eResolutionChangeMode = FBM_RESOLUTION_CHANGE_MODE_NONE;
        if (prPar)
        {
            LOG(1,"Change Mode to default Target W/H (%d-%d)\n",prPar->u4TargetW,prPar->u4TargetH);
        }
    }

    return ucFbgId;
}

