/* 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_fb.c,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

/** @file fbm_fb.c
 */


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

#include "fbm_fb.h"
#include "fbm_drvif.h"
#include "fbm_pool.h"
#include "fbm_debug.h"
#include "x_assert.h"
#include "x_syslog.h"
#include "vdec_drvif.h"
#include "vdp_prescale_drvif.h"
#ifdef TIME_MEASUREMENT
#include "x_time_msrt.h"
#include "u_time_msrt_name.h"

#endif

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

// FBM Frame Buffer Status Log

//#define CC_GET_AFTER_RESIZE_DONE
//---------------------------------------------------------------------------
// Constant definitions
//---------------------------------------------------------------------------

/* wait FB for 10000 ms (VDP_INVALID_DRIFT) when the first pic is not displayed yet. */
#define FBM_WAIT_FB_TIMEOUT 10000

#define FBM_PTS_FRM_RATE_12 7500
#define FBM_PTS_FRM_RATE_15 6000
#define FBM_PTS_FRM_RATE_20 4500
#define FBM_PTS_FRM_RATE_24 3750
#define FBM_PTS_FRM_RATE_25 3600
#define FBM_PTS_FRM_RATE_30 3000
#define FBM_PTS_FRM_RATE_50 1800
#define FBM_PTS_FRM_RATE_60 1500

#define FBM_PTS_FRM_RATE_TORRENCE 90


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


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

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

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

#define VERIFY_RESIZE_FB(gid, id)                       \
    ((id >= _prFbg[gid].ucSeamlessFbNs) ||              \
    (id >= FBM_MAX_FB_NS_PER_GROUP))

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

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

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

#define VERIFY_FBID(id,ret)                             \
    if(id >= FBM_MAX_FB_NS_PER_GROUP)                   \
    {                                                   \
        LOG(0,"ucFbId %d line(%d)\n",id,__LINE__);      \
        return ret;                                     \
    }

#define VERIFY_FBID_VOID(id)                            \
    if(id >= FBM_MAX_FB_NS_PER_GROUP)                   \
    {                                                   \
        LOG(0,"ucFbId %d line(%d)\n",id,__LINE__);      \
        return;                                         \
    }

#define IS_MINOR_FBS(gid, id)  ((_prFbg[gid].ucFbNsMinorBase <= id) && (id < _prFbg[gid].ucFbNsMinor))
#define IS_MAJOR_FBS(gid, id)  ((_prFbg[gid].ucFbNsMajorBase <= id) && (id < _prFbg[gid].ucFbNsMajor))


#ifdef CC_VDP_FULL_ISR

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

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

#else

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

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

#endif


//---------------------------------------------------------------------------
// Imported variables
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Imported functions
//---------------------------------------------------------------------------
extern void _EnableNewSeamless(UCHAR ucFbgId);

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

static void _FbmPutFrameBufferToDispQ(UCHAR ucFbgId, UCHAR ucFbId);

static UCHAR _FbmGetRefFrameBufferFromEmptyQ(UCHAR ucFbgId);

static UCHAR _FbmGetBFrameBufferFromEmptyQ(UCHAR ucFbgId);

static void _FbmResetPicHdrFields(UCHAR ucFbgId, UCHAR ucFbId);

static BOOL FBM_SetDispTag_UseTagQ(UCHAR ucFbgId, UCHAR ucFbId,UINT64 u4Tag);

static BOOL FBM_GetFbByDispTag_UseTagQ(UINT64 u4Tag, UCHAR *pucFbgId, UCHAR *pucFbId,BOOL b_get);

static BOOL FBM_ReleaseBufferByDispTag_UseTagQ(UINT64 u4Tag,UCHAR *pucReleaseCount);

static VOID FBM_ReleaseBufferByIndex_UseTagQ(UCHAR ucFbgId, UCHAR ucFbId);

static VOID FBM_FlushLockToEmptyQ_UseTagQ(UCHAR ucFbgId);
static UINT32 _FBMChkIsGetFBFromDispQ(UCHAR ucFbgId);
static VOID _FBMUpdateStepCount(UCHAR ucFbgId);


#ifdef FBM_FB_LOG
static void _FbmFbLog(UCHAR u1FbgIdx,UCHAR u1FbIdx, UCHAR ucFbStatus, const CHAR* sFunc, const UINT32 u4Line);
#define ASSERT_FBM_DEBUG(x,a,b)    \
do{                                \
    if(!(x))                       \
    {                              \
        LOG(0,"%s %d\n",a,b);       \
        FBM_FlushFbLog(0xFC, 0xFF);\
        FBM_QueryStatus(0xff);     \
        LOG(0, "FBM is Going to Assert. Sleep 60s.\n");\
        ASSERT(x);                  \
    }                               \
}while(0)
#define  ASSERT_FBM(x) ASSERT_FBM_DEBUG(x,__func__, __LINE__)
#else
#define _FbmFbLog(xx,x, y, z, zz)     ((void)0)
#define  ASSERT_FBM(x)             (ASSERT(x))
#endif

//---------------------------------------------------------------------------
// Static variables
//---------------------------------------------------------------------------
UINT32  u4FbmCtrlLog  = FBM_ENABLE_LOG_UNKNOW;
BOOL fgFbmEnableTagQ = FALSE;


static FBM_FBG_T* _prFbg = NULL;

static FBM_CB_FUNC_T* _prFbmCbFunc = NULL;


/* FBM global flag, not related to FBG index */
static UINT8 _ucFbmGlobalFlag = 0;
static BOOL _fgCheckFBStatus = TRUE;
//---------------------------------------------------------------------------
// Static functions
//---------------------------------------------------------------------------

//-------------------------------------------------------------------------
/** _FbmPutFrameBufferToDispQ
 *  Put FB to display queue
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
static void _FbmPutFrameBufferToDispQ(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR ucNextWriteIdx;
    FBM_PIC_HDR_T* pPicHdr = NULL;
    FBM_SEQ_HDR_T *pSeqHdr = NULL;

    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }
    if (_prFbg[ucFbgId].rDisplayQ.ucCount >= FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"FbgId(%d) DisplayQ.Count(%d)\n",ucFbgId,_prFbg[ucFbgId].rDisplayQ.ucCount);
    }

    ASSERT_FBM(_prFbg[ucFbgId].rDisplayQ.ucCount < FBM_MAX_FB_NS_PER_GROUP);

    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CHK_DISPQ) == FBM_ENABLE_LOG_CHK_DISPQ)
    {
        _FbmQueryFromDisplayQ(ucFbgId,ucFbId);
    }

    pPicHdr = FBM_GetFrameBufferPicHdr(ucFbgId, ucFbId);
    pSeqHdr = FBM_GetFrameBufferSeqHdr(ucFbgId);

    if (pPicHdr && pSeqHdr)
    {
        pPicHdr->ucPicId = _prFbg[ucFbgId].ucPictureId;
        pPicHdr->u4PicSoc = pSeqHdr->u4PendingSOC;
        _prFbg[ucFbgId].ucPictureId++;
        if (_prFbg[ucFbgId].ucPictureId == 0xFF)
        {
            _prFbg[ucFbgId].ucPictureId = 0;
        }
        if (_prFbg[ucFbgId].fgRlsDispQue)
        {
            pPicHdr->fgPicFlush = TRUE;
            _prFbg[ucFbgId].fgRlsDispQue = FALSE;
            LOG(0,"after flush,the first FBG/FB/ID/SOC [%d-%d-%d-%d]\n",ucFbgId,ucFbId,pPicHdr->ucPicId,pPicHdr->u4PicSoc);
        }

        if((_prFbg[ucFbgId].eSeamlessMode & POST_PROCESS_BEFORE_B2R)&&
           (pSeqHdr->rPPOutput.u4Width == 0 || _prFbg[ucFbgId].ucSeqChg))
        {
            _FBM_PostProcess_OutputInfo(ucFbgId, pSeqHdr, &pSeqHdr->rPPOutput);
        }
    }
    else
    {
        LOG(0,"Pic Hdr or Seq Hdr exception!!!\n");
    }

    if (_prFbg[ucFbgId].ucSeqChg == 1)
    {
        _prFbg[ucFbgId].ucNewFbId = ucFbId;
        FbmPutToSeqChgQue(ucFbgId,ucFbId,NULL);
        _prFbg[ucFbgId].ucSeqChg = 0;
        LOG(1,"SegChg fbg(%d),fb(%d),ucSeqChgFbId(%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].ucSeqChgFbId);
    }

    ucNextWriteIdx = (_prFbg[ucFbgId].rDisplayQ.ucReadIdx + _prFbg[ucFbgId].rDisplayQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
    _prFbg[ucFbgId].rDisplayQ.aucQueue[ucNextWriteIdx] = ucFbId;
    _prFbg[ucFbgId].rDisplayQ.ucCount++;

}


//-------------------------------------------------------------------------
/** _FbmGetRefFrameBufferFromEmptyQ
 *  Get reference FB from empty queue
 *  @param  ucFbgId   FBG index.
 *  @return FB index.
 */
//-------------------------------------------------------------------------
static UCHAR _FbmGetRefFrameBufferFromEmptyQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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

    while (_prFbg[ucFbgId].rEmptyQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[_prFbg[ucFbgId].rEmptyQ.ucReadIdx];

        if (++(_prFbg[ucFbgId].rEmptyQ.ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
        {
            _prFbg[ucFbgId].rEmptyQ.ucReadIdx = 0;
        }
        _prFbg[ucFbgId].rEmptyQ.ucCount--;

        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
        }

        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);
        VERIFY_FBID(ucFbId,FBM_FB_ID_UNKNOWN);

        if (_prFbg[ucFbgId].au4GfxMemsetId[ucFbId] &&
            FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE]))
        {
            while(0 == ((FBM_GFX_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GfxMemsetId[ucFbId]))
            {
                x_thread_delay(1);
                //wait
            };
            _prFbg[ucFbgId].au4GfxMemsetId[ucFbId] = 0;
        }
        if (_prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId] &&
            _prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId] &&
            FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE]))
        {
            while(0 == ((FBM_GDMA_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId]))
            {
                x_thread_delay(1);
                //wait
            };
            while(0 == ((FBM_GDMA_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId]))
            {
                x_thread_delay(1);
                //wait
            };

            _prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId] = 0;
            _prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId] = 0;
        }

        return ucFbId;
    }


    return FBM_FB_ID_UNKNOWN;
}


//-------------------------------------------------------------------------
/** _FbmGetBFrameBufferFromEmptyQ
 *  Get B FB from empty queue
 *  @param  ucFbgId   FBG index.
 *  @return FB index.
 */
//-------------------------------------------------------------------------
static UCHAR _FbmGetBFrameBufferFromEmptyQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;
    UINT32 u4Count;
    UINT32 u4ReadIdx;
    UINT32 u4TargetIdx;

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

    ucFbId = FBM_FB_ID_UNKNOWN;

    // search for B frame from Empty Queue
    u4Count = _prFbg[ucFbgId].rEmptyQ.ucCount;
    u4ReadIdx = _prFbg[ucFbgId].rEmptyQ.ucReadIdx;
    u4TargetIdx = FBM_MAX_FB_NS_PER_GROUP;
    while (u4Count > 0)
    {
        if (u4ReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"u4ReadIdx %d\n",u4ReadIdx);

            ASSERT_FBM(u4ReadIdx < FBM_MAX_FB_NS_PER_GROUP);
            return FBM_FB_ID_UNKNOWN;
        }
        ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[u4ReadIdx];

        if (NOT_REFERENCE_FB(ucFbgId, ucFbId))
        {
            // found B frame
            u4TargetIdx = u4ReadIdx;
            u4Count = 0;
        }
        else
        {
            // skip Reference frame
            ucFbId = FBM_FB_ID_UNKNOWN;
            if (++u4ReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                u4ReadIdx = 0;
            }
            u4Count--;
        }
    }

    if (u4TargetIdx != FBM_MAX_FB_NS_PER_GROUP)
    {
        // move back reference frame
        while (u4TargetIdx != _prFbg[ucFbgId].rEmptyQ.ucReadIdx)
        {
            if (u4TargetIdx > 0)
            {
                u4ReadIdx = u4TargetIdx - 1;
            }
            else
            {
                u4ReadIdx = FBM_MAX_FB_NS_PER_GROUP - 1;
            }

            _prFbg[ucFbgId].rEmptyQ.aucQueue[u4TargetIdx] = _prFbg[ucFbgId].rEmptyQ.aucQueue[u4ReadIdx];

            u4TargetIdx = u4ReadIdx;
        }
    }
    else
    {
        if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
        {
            return FBM_FB_ID_UNKNOWN;
        }
        else
        {
            ASSERT_FBM(0);
        }
    }
    VERIFY_FBID(ucFbId,FBM_FB_ID_UNKNOWN);

    _prFbg[ucFbgId].rEmptyQ.ucReadIdx =
        (UCHAR)((_prFbg[ucFbgId].rEmptyQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP);
    _prFbg[ucFbgId].rEmptyQ.ucCount--;

    if (_prFbg[ucFbgId].au4GfxMemsetId[ucFbId] &&
        FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE]))
    {
        while(0 == ((FBM_GFX_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GfxMemsetId[ucFbId]))
        {
            x_thread_delay(1);
            //wait
        };
        _prFbg[ucFbgId].au4GfxMemsetId[ucFbId] = 0;
    }
    if (_prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId] &&
        _prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId] &&
        FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE]))
    {
        while(0 == ((FBM_GDMA_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId]))
        {
            x_thread_delay(1);
            //wait
        };
        while(0 == ((FBM_GDMA_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId]))
        {
            x_thread_delay(1);
            //wait
        };

        _prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId] = 0;
        _prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId] = 0;
    }



    return ucFbId;
}

//-------------------------------------------------------------------------
/** _FbmResetPicHdrFields
 *  Reset Picture header fields
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId    FB index.
 *  @return
 */
//-------------------------------------------------------------------------
static void _FbmResetPicHdrFields(UCHAR ucFbgId, UCHAR ucFbId)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }
    _prFbg[ucFbgId].prPicHdr[ucFbId].u2DecodingOrder = 0;
    _prFbg[ucFbgId].prPicHdr[ucFbId].u4TotlaTimeOffset = 0;
    _prFbg[ucFbgId].prPicHdr[ucFbId].u4MmFlag = 0;
    _prFbg[ucFbgId].prPicHdr[ucFbId].u8Offset = 0;
    _prFbg[ucFbgId].prPicHdr[ucFbId].u8OffsetI = 0;
    _prFbg[ucFbgId].prPicHdr[ucFbId].fgNotDisplay = FALSE;
    _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessResized = FALSE;
    _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid = FBM_FB_ID_UNKNOWN;
    _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid = FBM_FB_ID_UNKNOWN;
    _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
    _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessTaskId = 0xFF;
    x_memset(&_prFbg[ucFbgId].prPicHdr[ucFbId].rExtra, 0, sizeof(FBM_PIC_EXTRA_INFO_T));
}

//-------------------------------------------------------------------------
/** _FbmGetLatestEmptyFrameBufferFromEmptyQ
 *  Get LATEST empty FB from empty queue for MM STEP BACKWARD application
 *  @param  ucFbgId   FBG index.
 *  @return FB index.
 */
//-------------------------------------------------------------------------
static UCHAR _FbmGetLatestEmptyFrameBufferFromEmptyQ(UCHAR ucFbgId)
{
    UCHAR ucIndex;
    UCHAR ucFbId;

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

    while (_prFbg[ucFbgId].rEmptyQ.ucCount > 0)
    {
        ucIndex = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx+_prFbg[ucFbgId].rEmptyQ.ucCount-1)% FBM_MAX_FB_NS_PER_GROUP;
        ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[ucIndex];

        _prFbg[ucFbgId].rEmptyQ.ucCount--;

        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
        }
        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);
        return ucFbId;
    }

    return FBM_FB_ID_UNKNOWN;
}

BOOL _FbmQueryFromEmptyQ(UCHAR ucFbgId,UCHAR ucChkFbId)
{
    UCHAR ucFbId;
    UCHAR ucReadIdx = 0;
    UCHAR ucEmptyCnt = 0;

    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }
    if (ucChkFbId == 0xFF)
    {
        ucReadIdx = _prFbg[ucFbgId].rEmptyQ.ucReadIdx;

        for (ucEmptyCnt = 0; ucEmptyCnt < _prFbg[ucFbgId].rEmptyQ.ucCount; ucEmptyCnt++)
        {
            ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[ucReadIdx];

            if (++(ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
            {
                ucReadIdx = 0;
            }

            LOG(0,"EmpQue(%d) FbId(%d) PTS(0x%llx)\n",ucEmptyCnt,ucFbId,_prFbg[ucFbgId].prPicHdr ? _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS : 0);
        }

    }
    else
    {
        ucReadIdx = _prFbg[ucFbgId].rEmptyQ.ucReadIdx;

        for (ucEmptyCnt = 0; ucEmptyCnt < _prFbg[ucFbgId].rEmptyQ.ucCount; ucEmptyCnt++)
        {
            ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[ucReadIdx];

            if (++(ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
            {
                ucReadIdx = 0;
            }
            if (ucFbId == ucChkFbId)
            {
                LOG(0,"EmpQue(%d) FbId(%d) PTS(0x%llx)\n",ucEmptyCnt,ucFbId,_prFbg[ucFbgId].prPicHdr ? _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS : 0);
                ASSERT_FBM(0);
            }

        }

    }

    return TRUE;

}

BOOL _FbmQueryFromDisplayQ(UCHAR ucFbgId,UCHAR ucChkFbId)
{
    UCHAR ucFbId;
    UCHAR ucReadIdx = 0;
    UCHAR ucDispCnt = 0;

    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }
    if (ucChkFbId == 0xFF)
    {
        ucReadIdx = _prFbg[ucFbgId].rDisplayQ.ucReadIdx;

        for (ucDispCnt = 0; ucDispCnt < _prFbg[ucFbgId].rDisplayQ.ucCount; ucDispCnt++)
        {
            ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[ucReadIdx];

            if (++(ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
            {
                ucReadIdx = 0;
            }

            LOG(0,"DisplayQue(%d) FbId(%d) PTS(0x%llx)\n",ucDispCnt,ucFbId,_prFbg[ucFbgId].prPicHdr ? _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS : 0);
        }


    }
    else
    {
        ucReadIdx = _prFbg[ucFbgId].rDisplayQ.ucReadIdx;

        for (ucDispCnt = 0; ucDispCnt < _prFbg[ucFbgId].rDisplayQ.ucCount; ucDispCnt++)
        {
            ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[ucReadIdx];

            if (++(ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
            {
                ucReadIdx = 0;
            }
            if (ucFbId == ucChkFbId)
            {
                LOG(0,"DisplayQue(%d) FbId(%d) PTS(0x%llx)\n",ucDispCnt,ucFbId,_prFbg[ucFbgId].prPicHdr ? _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS : 0);
                ASSERT_FBM(0);
            }

        }


    }

    return TRUE;
}


//-------------------------------------------------------------------------
/** _FbmGetEmptyFrameBufferFromEmptyQ
 *  Get empty FB from empty queue. H264 ONLY.
 *  @param  ucFbgId   FBG index.
 *  @return FB index.
 */
//-------------------------------------------------------------------------
static UCHAR _FbmGetEmptyFrameBufferFromEmptyQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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


    while (_prFbg[ucFbgId].rEmptyQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[_prFbg[ucFbgId].rEmptyQ.ucReadIdx];

        if (++(_prFbg[ucFbgId].rEmptyQ.ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
        {
            _prFbg[ucFbgId].rEmptyQ.ucReadIdx = 0;
        }
        _prFbg[ucFbgId].rEmptyQ.ucCount--;

        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
        }
        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);
        VERIFY_FBID(ucFbId,FBM_FB_ID_UNKNOWN);

        if (_prFbg[ucFbgId].au4GfxMemsetId[ucFbId] &&
            FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE]))
        {
            while(0 == ((FBM_GFX_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GFX_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GfxMemsetId[ucFbId]))
            {
                x_thread_delay(1);
                //wait
            };
            _prFbg[ucFbgId].au4GfxMemsetId[ucFbId] = 0;
        }
        if (_prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId] &&
            _prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId] &&
            FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE]))
        {
            while(0 == ((FBM_GDMA_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId]))
            {
                x_thread_delay(1);
                //wait
            };
            while(0 == ((FBM_GDMA_TASK_MEMSET_DONE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_GDMA_TASK_MEMSET_DONE])(_prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId]))
            {
                x_thread_delay(1);
                //wait
            };

            _prFbg[ucFbgId].au4GdmaMemsetYId[ucFbId] = 0;
            _prFbg[ucFbgId].au4GdmaMemsetCId[ucFbId] = 0;
        }

        return ucFbId;

    }

    return FBM_FB_ID_UNKNOWN;
}


//-------------------------------------------------------------------------
/** _FbmGetEmptyFrameBufferFromEmptyResizeQ
 *  Get empty FB from empty resize queue.
 *  @param  ucFbgId   FBG index.
 *  @return FB index.
 */
//-------------------------------------------------------------------------
static UCHAR _FbmGetEmptyFrameBufferFromEmptyResizeQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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


    while (_prFbg[ucFbgId].rResizeEmptyQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rResizeEmptyQ.aucQueue[_prFbg[ucFbgId].rResizeEmptyQ.ucReadIdx];

        if (++(_prFbg[ucFbgId].rResizeEmptyQ.ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
        {
            _prFbg[ucFbgId].rResizeEmptyQ.ucReadIdx = 0;
        }
        _prFbg[ucFbgId].rResizeEmptyQ.ucCount--;

        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
        }
        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);
        return ucFbId;
    }

    return FBM_FB_ID_UNKNOWN;
}

//-------------------------------------------------------------------------
/** _FbmGetEmptyFrameBufferFromEmptyResize2Q
 *  Get empty FB from empty resize queue.
 *  @param  ucFbgId   FBG index.
 *  @return FB index.
 */
//-------------------------------------------------------------------------
static UCHAR _FbmGetEmptyFrameBufferFromEmptyResize2Q(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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


    while (_prFbg[ucFbgId].rResize2EmptyQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rResize2EmptyQ.aucQueue[_prFbg[ucFbgId].rResize2EmptyQ.ucReadIdx];

        if (++(_prFbg[ucFbgId].rResize2EmptyQ.ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
        {
            _prFbg[ucFbgId].rResize2EmptyQ.ucReadIdx = 0;
        }
        _prFbg[ucFbgId].rResize2EmptyQ.ucCount--;

        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
        }
        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);
        return ucFbId;
    }

    return FBM_FB_ID_UNKNOWN;
}

#if 0
#ifdef __KERNEL__
//-------------------------------------------------------------------------
/** _FbmGetFrameBufferFromDispQ
 *  Get FB from empty queue
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId    FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
static void _FbmGetFrameBufferFromDispQ(UCHAR ucFbgId, UCHAR ucFbId)
{
    UINT32 u4Count;
    UINT32 u4ReadIdx;
    UINT32 u4TargetIdx;

    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }
    if (_prFbg[ucFbgId].rDisplayQ.ucCount >= FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"ucFbgId %d rDisplayQ.ucCount(%d)\n",ucFbgId,_prFbg[ucFbgId].rDisplayQ.ucCount);
    }

    ASSERT_FBM(_prFbg[ucFbgId].rDisplayQ.ucCount < FBM_MAX_FB_NS_PER_GROUP);

    // search FB from Display Queue
    u4Count = _prFbg[ucFbgId].rDisplayQ.ucCount;
    u4ReadIdx = _prFbg[ucFbgId].rDisplayQ.ucReadIdx;
    u4TargetIdx = FBM_MAX_FB_NS_PER_GROUP;

    if (u4ReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
    {
        ASSERT_FBM(0);
        u4ReadIdx = 0;
    }

    while (u4Count > 0)
    {
        if (ucFbId == _prFbg[ucFbgId].rDisplayQ.aucQueue[u4ReadIdx])
        {
            u4TargetIdx = u4ReadIdx;
            u4Count = 0;
        }
        else
        {
            if (++u4ReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
            {
                u4ReadIdx = 0;
            }
            u4Count--;
        }
    }

    if (u4TargetIdx != FBM_MAX_FB_NS_PER_GROUP)
    {
        // move back other frame buffer
        while (u4TargetIdx != _prFbg[ucFbgId].rDisplayQ.ucReadIdx)
        {
            if (u4TargetIdx > 0)
            {
                u4ReadIdx = u4TargetIdx - 1;
            }
            else
            {
                u4ReadIdx = FBM_MAX_FB_NS_PER_GROUP - 1;
            }
            _prFbg[ucFbgId].rDisplayQ.aucQueue[u4TargetIdx] = _prFbg[ucFbgId].rDisplayQ.aucQueue[u4ReadIdx];

            u4TargetIdx = u4ReadIdx;
        }
    }
    else
    {
        if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
        {
            return;
        }
        else
        {
            ASSERT_FBM(0);
        }
    }

    _prFbg[ucFbgId].rDisplayQ.ucReadIdx = (_prFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;
    _prFbg[ucFbgId].rDisplayQ.ucCount--;

}
#endif
#endif

BOOL    g_bEnableDebugLog = TRUE;

#ifdef FBM_FB_LOG
#define FBM_FB_LOG_NS 64
typedef struct
{
    UCHAR   ucFbgId;
    UCHAR   ucFBId;
    CHAR    ucStatus;
    CHAR    sCallFunc[64];
    UINT32  u4CallLine;
    HAL_TIME_T tCallTime;
} FBM_FB_LOG_T;

static FBM_FB_LOG_T *tDebugLog =  NULL;
static UINT32 u4DebugIdx = 0;
static HANDLE_T hFbLogMutex = NULL_HANDLE;

void FbmInitFbLog(void)
{
    if (tDebugLog == NULL)
    {
        tDebugLog = x_mem_alloc(sizeof(FBM_FB_LOG_T) * FBM_FB_LOG_NS);
    }

    if (tDebugLog == NULL)
    {
        LOG(0,"alloc tDebugLog fail \n");
        ASSERT(0);
        return;
    }

    x_memset(tDebugLog, 0, FBM_FB_LOG_NS*sizeof(FBM_FB_LOG_T));
    LOG(0,"FbmInitFbLog\n");
}
//-----------------------------------------------------------------------------
/** Brief of _FbmFbLog.
 */
//-----------------------------------------------------------------------------
static void _FbmFbLog(UCHAR u1FbgIdx,UCHAR u1FbIdx, UCHAR ucFbStatus, const CHAR* sFunc, const UINT32 u4Line)
{
    UINT32 u4_idx = 0;

    if (!g_bEnableDebugLog)
    {
        return;
    }

    if (hFbLogMutex == NULL_HANDLE)
    {
        // create semaphore
        VERIFY(x_sema_create(&hFbLogMutex, X_SEMA_TYPE_MUTEX, X_SEMA_STATE_UNLOCK) == OSR_OK);
        x_memset(tDebugLog, 0, FBM_FB_LOG_NS*sizeof(FBM_FB_LOG_T));
#if 0
        for (u4DebugIdx = 0; u4DebugIdx < FBM_FB_LOG_NS; u4DebugIdx++)
        {
            szDebug1[u4DebugIdx] = 0;
            szDebug2[u4DebugIdx] = 0;
        }
#endif

        u4DebugIdx = 0;
    }

    VERIFY(x_sema_lock(hFbLogMutex, X_SEMA_OPTION_WAIT) == OSR_OK);

    tDebugLog[u4DebugIdx].ucFbgId = u1FbgIdx;
    tDebugLog[u4DebugIdx].ucFBId = u1FbIdx;
    tDebugLog[u4DebugIdx].ucStatus = ucFbStatus;
    tDebugLog[u4DebugIdx].u4CallLine = u4Line;
    x_memcpy(tDebugLog[u4DebugIdx].sCallFunc, sFunc, x_strlen(sFunc));
    tDebugLog[u4DebugIdx].sCallFunc[x_strlen(sFunc)] = '\0';
    HAL_GetTime(&(tDebugLog[u4DebugIdx].tCallTime));

    if ((++u4DebugIdx >= FBM_FB_LOG_NS) && (u1FbIdx != 0xFC))
    {
        for(u4_idx = 0; u4_idx < FBM_FB_LOG_NS; u4_idx++)
        {
            LOG(6, "%d: [%d.%06d][%-32s-%4d] FBG(%d) FB(%d) Status(%d).\n", u4_idx,
                tDebugLog[u4_idx].tCallTime.u4Seconds, tDebugLog[u4_idx].tCallTime.u4Micros,
                tDebugLog[u4_idx].sCallFunc, tDebugLog[u4_idx].u4CallLine,
                tDebugLog[u4_idx].ucFbgId,
                tDebugLog[u4_idx].ucFBId, tDebugLog[u4_idx].ucStatus);
        }
        LOG(6, "u4DebugIdx = %d\n", u4DebugIdx);
        u4DebugIdx = 0;
    }

    if(u1FbIdx == 0xFC)
    {
        for(u4_idx = u4DebugIdx; u4_idx < FBM_FB_LOG_NS; u4_idx++)
        {
            LOG(0, "%d: [%d.%06d][%-32s-%4d] FBG(%d) FB(%d) Status(%d).\n", u4_idx,
                tDebugLog[u4_idx].tCallTime.u4Seconds, tDebugLog[u4_idx].tCallTime.u4Micros,
                tDebugLog[u4_idx].sCallFunc, tDebugLog[u4_idx].u4CallLine,
                tDebugLog[u4_idx].ucFbgId,
                tDebugLog[u4_idx].ucFBId, tDebugLog[u4_idx].ucStatus);

        }
        LOG(0, "u4DebugIdx = %d\n", u4DebugIdx);
        for(u4_idx = 0; u4_idx < u4DebugIdx; u4_idx++)
        {
            LOG(0, "%d: [%d.%06d][%-32s-%4d] FBG(%d) FB(%d) Status(%d).\n", u4_idx,
                tDebugLog[u4_idx].tCallTime.u4Seconds, tDebugLog[u4_idx].tCallTime.u4Micros,
                tDebugLog[u4_idx].sCallFunc, tDebugLog[u4_idx].u4CallLine,
                tDebugLog[u4_idx].ucFbgId,
                tDebugLog[u4_idx].ucFBId, tDebugLog[u4_idx].ucStatus);

        }
        u4DebugIdx = 0;
    }


    VERIFY(x_sema_unlock(hFbLogMutex) == OSR_OK);
}

#endif

//---------------------------------------------------------------------------
// Inter-file functions
//---------------------------------------------------------------------------

//-------------------------------------------------------------------------
/** _FBM_FbInit
 *  Set FBG structure pointer
 *  @param  prFbg   FBG structure pointer.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void _FBM_FbInit(FBM_FBG_T* prFbg)
{
    _prFbg = prFbg;

    _prFbmCbFunc = FBM_GetCbFuncTbl();
}

UCHAR FBM_CheckFbg(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return TRUE;
    }

    return FALSE;
}


//-------------------------------------------------------------------------
/** FBM_TriggerSeamless
 *  Trigger seamless
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------

VOID FBM_TriggerSmlsByResizer(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR ucRezId = 0;
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    // vomx check.
    if(_prFbg[ucFbgId].eSeamlessMode & POST_PROCESS_DISPLAY_ROTATE)
    {
        if(_prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp == FALSE)
        {
            _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp = TRUE;
        }
    }

    if ((_prFbg[ucFbgId].prPicHdr[ucFbId].u4PicPitch <= FBM_FBG_4K2K_H) &&
        (_prFbg[ucFbgId].prPicHdr[ucFbId].u4PicPitch > FBM_FBG_2560_H) &&
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp)
    {
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp = FALSE;

        LOG(6,"FbgId(%d) ucFbId(%d) resolution achieve to 4K ,don't need imgrz\n",ucFbgId,ucFbId);
    }
    else if(FBM_ChkSeamlessMode(ucFbgId,POST_PROCESS_DISPLAY_ROTATE)
            && !(FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_RESIZER))
            && (_prFbg[ucFbgId].prPicHdr[ucFbId].u4SourceWidth > FBM_FBG_1080HD_H || _prFbg[ucFbgId].prPicHdr[ucFbId].u4SourceHeight > FBM_FBG_1080HD_V))
    {
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp = FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp || _prFbg[ucFbgId].fgAutoSeamless || _prFbg[ucFbgId].prPicHdr[ucFbId].fgResizeDispFrm)
    {
        if(_prFbg[ucFbgId].prPicHdr[ucFbId].fgResizeDispFrm)
        {
            _prFbg[ucFbgId].ucSeamlessRzId = _prFbg[ucFbgId].prPicHdr[ucFbId].ucRzId;
        }
        else if (!_prFbg[ucFbgId].fgEnableNewSeamless)
        {
            UCHAR ucRzId;
            UCHAR ucRzIdMask = 0;

#if defined(ENABLE_MULTIMEDIA) && defined(CC_VDEC_RM_SUPPORT)
            if(_prFbg[ucFbgId].eSeamlessMode& SEAMLESS_BY_RESIZER)
            {
                VDEC_ES_INFO_T *prVdecEsInfo = NULL;
                prVdecEsInfo = _VDEC_GetEsInfo(_prFbg[ucFbgId].u1DecoderSrcId);
                ucRzIdMask = prVdecEsInfo ? prVdecEsInfo->ucImgrzId : 0;
            }
#endif
            _prFbg[ucFbgId].ucSeamlessRzId = VDP_PRESCALE_RZ_ID_UNKNOWN;
            _prFbg[ucFbgId].ucSeamlessRzId2 = VDP_PRESCALE_RZ_ID_UNKNOWN;
            _prFbg[ucFbgId].ucSeamlessRzMask = 0x0;

            _EnableNewSeamless(ucFbgId);
            _prFbg[ucFbgId].fgEnableNewSeamless = TRUE;
            ucRzId = _VDP_Prescale_Init(ucRzIdMask);
            ASSERT_FBM(ucRzId != VDP_PRESCALE_RZ_ID_UNKNOWN);
            _prFbg[ucFbgId].ucSeamlessRzMask |= (1 << ucRzId);
            _prFbg[ucFbgId].ucSeamlessRzId = ucRzId;
            _VDP_SetPfn_RzGetFB(ucRzId,FBM_GetEmptyResizeFrameBuffer);
            _VDP_SetPfn_RzGetFBAddr(ucRzId,FBM_GetResizeFrameBufferAddr);
            _VDP_SetPfn_RzSetFBStatus(ucRzId,FBM_SetResizeFrameBufferStatus);
            _VDP_SetPfn_RzSetFBFlag(ucRzId,FBM_SetResizeFrameBufferFlag);
            FBM_SetResizeFrameBufferFlag(ucFbgId,FBM_FB_ID_ALL,FLAG_SET_TYPE_RESET,0);
            //1 video with 2 imgrz
            if((_prFbg[ucFbgId].rSeqHdr.eSeamlessMode & SEAMLESS_TWO_RESIZER) == SEAMLESS_TWO_RESIZER)
            {
                ucRzId = _VDP_Prescale_Init(ucRzIdMask);
                ASSERT_FBM(ucRzId != VDP_PRESCALE_RZ_ID_UNKNOWN);
                _prFbg[ucFbgId].ucSeamlessRzMask |= (1 << ucRzId);
                _prFbg[ucFbgId].ucSeamlessRzId2 = ucRzId;
                _VDP_SetPfn_RzGetFB(ucRzId,FBM_GetEmptyResize2FrameBuffer);
                _VDP_SetPfn_RzGetFBAddr(ucRzId,FBM_GetResize2FrameBufferAddr);
                _VDP_SetPfn_RzSetFBStatus(ucRzId,FBM_SetResize2FrameBufferStatus);
                _VDP_SetPfn_RzSetFBFlag(ucRzId,FBM_SetResize2FrameBufferFlag);
                FBM_SetResize2FrameBufferFlag(ucFbgId,FBM_FB_ID_ALL,FLAG_SET_TYPE_RESET,0);
            }
            LOG(1, "Enable new seamless, ucRzIdMask %d Rzid0 %d Rzid1 %d\n", ucRzIdMask,_prFbg[ucFbgId].ucSeamlessRzId,_prFbg[ucFbgId].ucSeamlessRzId2);
            //_prFbg[ucFbgId].ucSeamlessRzId = (ucRzId != VDP_PRESCALE_RZ_ID_UNKNOWN) ? ucRzIdMask : VDP_PRESCALE_RZ_ID_DEFAULT;
        }
        LOG(6, "Send resize fbid (%d, %d)\n",ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId]);

        _prFbg[ucFbgId].ucCurSeamlessTaskId++;

        if (_prFbg[ucFbgId].ucCurSeamlessTaskId == 0xFF)
        {
            _prFbg[ucFbgId].ucCurSeamlessTaskId = 0;
        }
        ucRezId = _VDP_GetRzId(_prFbg[ucFbgId].ucSeamlessRzMask,_prFbg[ucFbgId].ucCurSeamlessTaskId);

        _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessTaskId = _prFbg[ucFbgId].ucCurSeamlessTaskId;
        _VDP_Prescale_Send(ucRezId, ucFbgId, ucFbId, _prFbg[ucFbgId].ucCurSeamlessTaskId,_prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS);
    }
    FBM_MUTEX_UNLOCK(ucFbgId);

    return;
}


void _FBM_PutFrameBufferToEmptyQEx(UCHAR ucFbgId, UCHAR ucFbId)
{
    CRIT_STATE_T _rEmptyQState;
    UCHAR ucNextWriteIdx;
    UCHAR ucMinorStartFbId,ucMinorEndFbId;
    UCHAR ucMajorFbId;
    BOOL  bConflict = FALSE;
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    _rEmptyQState = x_crit_start();

    if (FBM_RESOLUTION_CHANGE_MODE_SEAMLESS== _prFbg[ucFbgId].eResolutionChangeMode)
    {
        if (FBM_FBID_TYPE_MINOR== _prFbg[ucFbgId].eFbIdType)
        {
            if (IS_MINOR_FBS(ucFbgId, ucFbId))
            {
                _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY;
                _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                ucNextWriteIdx = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx + _prFbg[ucFbgId].rEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
                _prFbg[ucFbgId].rEmptyQ.aucQueue[ucNextWriteIdx] = ucFbId;
                _prFbg[ucFbgId].rEmptyQ.ucCount++;
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                {
                    LOG(2,"Minor:Directly put EmptyQ(%d-%d-%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                }
            }
            else
            {
                _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY; //Major -> Minor
                _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                ucMinorStartFbId = FBM_MAJOR2MINORSTARTFBID(ucFbId);
                ucMinorEndFbId = ucMinorStartFbId + FBM_SEAMLESS_LVL;

                for (; ucMinorStartFbId < ucMinorEndFbId; ucMinorStartFbId++)
                {
                    if (ucMinorStartFbId >= FBM_MAX_FB_NS_PER_GROUP)
                    {
                        LOG(0,"Fb Id %d overflow\n",ucMinorStartFbId);
                        return;
                    }
                    if ((FBM_FB_STATUS_EMPTY == _prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId]) ||
                        (FBM_FB_STATUS_UNKNOWN == _prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId]))
                    {
                        _prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId] = FBM_FB_STATUS_EMPTY;
                        _prFbg[ucFbgId].u4DispTag[ucMinorStartFbId] = INVALID_DISPTAG;
                        ucNextWriteIdx = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx + _prFbg[ucFbgId].rEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
                        _prFbg[ucFbgId].rEmptyQ.aucQueue[ucNextWriteIdx] = ucMinorStartFbId;
                        _prFbg[ucFbgId].rEmptyQ.ucCount++;
                        VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                        {
                            LOG(0,"Minor:Put EmptyQ(%d-%d-%d)\n",ucFbgId,ucMinorStartFbId,_prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId]);
                        }
                    }
                    else
                    {
                        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                        {
                            LOG(0,"Cur Minor(%d) status(%d) wait release\n",ucMinorStartFbId,_prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId]);
                        }
                    }
                }
            }
        }
        else if (FBM_FBID_TYPE_MAJOR == _prFbg[ucFbgId].eFbIdType)
        {
            if (IS_MAJOR_FBS(ucFbgId, ucFbId))
            {
                _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY;
                _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                ucNextWriteIdx = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx + _prFbg[ucFbgId].rEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
                _prFbg[ucFbgId].rEmptyQ.aucQueue[ucNextWriteIdx] = ucFbId;
                _prFbg[ucFbgId].rEmptyQ.ucCount++;
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                {
                    LOG(2,"Major:Directly put EmptyQ(%d-%d-%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                }
            }
            else
            {
                _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY;       // Minor->Major
                _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                ucMajorFbId = FBM_MINOR2MAJORFBID(ucFbId);

                ucMinorStartFbId = FBM_MAJOR2MINORSTARTFBID(ucMajorFbId);
                ucMinorEndFbId  = ucMinorStartFbId + FBM_SEAMLESS_LVL;
                bConflict = FALSE;

                for (; ucMinorStartFbId < ucMinorEndFbId; ucMinorStartFbId++)
                {
                    if (ucMinorStartFbId >= FBM_MAX_FB_NS_PER_GROUP)
                    {
                        LOG(0,"Fb Id %d overflow\n",ucMinorStartFbId);
                        return;
                    }
                    if (_prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId] != FBM_FB_STATUS_EMPTY)
                    {
                        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                        {
                            LOG(0,"Minor(%d)status(%d) Cur FbId(%d)\n",ucMinorStartFbId,_prFbg[ucFbgId].aucFbStatus[ucMinorStartFbId],ucFbId);
                        }
                        bConflict = TRUE;
                        break;
                    }
                }

                if (!bConflict)
                {
                    if ((FBM_FB_STATUS_EMPTY == _prFbg[ucFbgId].aucFbStatus[ucMajorFbId]) ||
                        (FBM_FB_STATUS_UNKNOWN == _prFbg[ucFbgId].aucFbStatus[ucMajorFbId]))
                    {
                        //avoid more time put the same Fb to emptyQ
                        if (!_prFbg[ucFbgId].afgWaitUse[ucMajorFbId])
                        {
                            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                            {
                                LOG(0,"Done Major(%d) FbId(%d)\n",ucMajorFbId,ucFbId);
                            }
                            _prFbg[ucFbgId].aucFbStatus[ucMajorFbId] = FBM_FB_STATUS_EMPTY;
                            _prFbg[ucFbgId].u4DispTag[ucMajorFbId] = INVALID_DISPTAG;
                            ucNextWriteIdx = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx + _prFbg[ucFbgId].rEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
                            _prFbg[ucFbgId].rEmptyQ.aucQueue[ucNextWriteIdx] = ucMajorFbId;
                            _prFbg[ucFbgId].rEmptyQ.ucCount++;
                            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                            _prFbg[ucFbgId].afgWaitUse[ucMajorFbId] = TRUE;
                        }
                    }
                    else
                    {
                        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CRT_FBG) == FBM_ENABLE_LOG_CRT_FBG)
                        {
                            LOG(0,"Cur Major(%d) status(%d) wait release\n",ucMajorFbId,_prFbg[ucFbgId].aucFbStatus[ucMajorFbId]);
                        }
                    }

                }

            }

        }
        else
        {
            _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY;
            _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
            ucNextWriteIdx = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx + _prFbg[ucFbgId].rEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
            _prFbg[ucFbgId].rEmptyQ.aucQueue[ucNextWriteIdx] = ucFbId;
            _prFbg[ucFbgId].rEmptyQ.ucCount++;

            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
        }

    }
    else
    {
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY;
        _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
        ucNextWriteIdx = (_prFbg[ucFbgId].rEmptyQ.ucReadIdx + _prFbg[ucFbgId].rEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
        _prFbg[ucFbgId].rEmptyQ.aucQueue[ucNextWriteIdx] = ucFbId;
        _prFbg[ucFbgId].rEmptyQ.ucCount++;

        VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);

    }
    x_crit_end(_rEmptyQState);

    return ;
}

//-------------------------------------------------------------------------
/** _FBM_PutFrameBufferToEmptyQ
 *  Put FB to empty queue
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void _FBM_PutFrameBufferToEmptyQ(UCHAR ucFbgId, UCHAR ucFbId)
{

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

    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_CHK_EMPTY) == FBM_ENABLE_LOG_CHK_EMPTY)
    {
        _FbmQueryFromEmptyQ(ucFbgId,ucFbId);
    }

    _FBM_PutFrameBufferToEmptyQEx(ucFbgId,ucFbId);
}


//-------------------------------------------------------------------------
/** _FBM_PutFrameBufferToEmptyResizeQ
 *  Put FB to empty queue
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void _FBM_PutFrameBufferToEmptyResizeQ(UCHAR ucFbgId, UCHAR ucRzFbId)
{
    UCHAR ucNextWriteIdx;

    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_RESIZE_FB(ucFbgId, ucRzFbId)))
    {
        return;
    }
    if (_prFbg[ucFbgId].rResizeEmptyQ.ucCount >= _prFbg[ucFbgId].ucSeamlessFbNs)  //done 0/0/1
    {
        if (_prFbg[ucFbgId].aucResizeFbStatus[ucRzFbId] == FBM_FB_STATUS_EMPTY)
        {
            LOG(1, "[Warning] Put to EmptyResizeQ Again (%d, %d)\n", ucFbgId, ucRzFbId);
            return;
        }
        else
        {
            if (_prFbg[ucFbgId].rResizeEmptyQ.ucCount >= _prFbg[ucFbgId].ucSeamlessFbNs)
            {
                LOG(0,"ucFbgId(%d) RzEmptyQCnt(%d) ucSeamlessFbNs(%d)\n",
                    ucFbgId,
                    _prFbg[ucFbgId].rResizeEmptyQ.ucCount,
                    _prFbg[ucFbgId].ucSeamlessFbNs);
            }
            ASSERT_FBM(_prFbg[ucFbgId].rResizeEmptyQ.ucCount < _prFbg[ucFbgId].ucSeamlessFbNs);
        }
    }

#if 0
    // fix video tear issue and garbage sometime
    if (_prFbg[ucFbgId].aucResizeBlockFb != FBM_FB_ID_UNKNOWN)
    {
        //Direct match the seamless RZ FB and resize block FB, for b2r change frame successful.
        //Or B2R need change frame by fb ready callback again.

        LOG(1,"ResizeBlockFb %d ucRzFbId %d\n",_prFbg[ucFbgId].aucResizeBlockFb,ucRzFbId);

        _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResizeBlockFb].ucSeamlessResizeFbid = ucRzFbId;
        _prFbg[ucFbgId].aucResizeBlockFb = FBM_FB_ID_UNKNOWN;

    }

#endif


    _prFbg[ucFbgId].aucResizeFbStatus[ucRzFbId] = FBM_FB_STATUS_EMPTY;
    _prFbg[ucFbgId].aucResizeSrcFbId[ucRzFbId] = FBM_FB_ID_UNKNOWN;
    _prFbg[ucFbgId].aucResizeTaskId[ucRzFbId] = 0xFF;

    ucNextWriteIdx = (_prFbg[ucFbgId].rResizeEmptyQ.ucReadIdx + _prFbg[ucFbgId].rResizeEmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
    _prFbg[ucFbgId].rResizeEmptyQ.aucQueue[ucNextWriteIdx] = ucRzFbId;
    _prFbg[ucFbgId].rResizeEmptyQ.ucCount++;
}
//-------------------------------------------------------------------------
/** _FBM_PutFrameBufferToEmptyResize2Q
 *  Put FB to empty queue
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------

void _FBM_PutFrameBufferToEmptyResize2Q(UCHAR ucFbgId, UCHAR ucRzFbId)
{
    UCHAR ucNextWriteIdx;

    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_RESIZE_FB(ucFbgId, ucRzFbId)))
    {
        return;
    }

    if (_prFbg[ucFbgId].rResize2EmptyQ.ucCount >= _prFbg[ucFbgId].ucSeamless2FbNs)
    {
        if (_prFbg[ucFbgId].aucResize2FbStatus[ucRzFbId] == FBM_FB_STATUS_EMPTY)
        {
            LOG(1, "[Warning] Put to EmptyResizeQ Again (%d, %d)\n", ucFbgId, ucRzFbId);
            return;
        }
        else
        {
            if (_prFbg[ucFbgId].rResize2EmptyQ.ucCount >= _prFbg[ucFbgId].ucSeamless2FbNs)
            {
                LOG(0,"ucFbgId(%d) Rz2EmptyQCnt(%d) Seamless2FbNs(%d)\n",
                    ucFbgId,
                    _prFbg[ucFbgId].rResize2EmptyQ.ucCount,
                    _prFbg[ucFbgId].ucSeamless2FbNs);

            }
            ASSERT_FBM(_prFbg[ucFbgId].rResize2EmptyQ.ucCount < _prFbg[ucFbgId].ucSeamless2FbNs);
        }
    }

#if 0
    // fix video tear issue and garbage sometime
    if (_prFbg[ucFbgId].aucResize2BlockFb != FBM_FB_ID_UNKNOWN)
    {
        //Direct match the seamless RZ FB and resize block FB, for b2r change frame successful.
        //Or B2R need change frame by fb ready callback again.
        _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResize2BlockFb].ucSeamlessResize2Fbid = ucRzFbId;
        _prFbg[ucFbgId].aucResize2BlockFb = FBM_FB_ID_UNKNOWN;
    }

#endif

    _prFbg[ucFbgId].aucResize2FbStatus[ucRzFbId] = FBM_FB_STATUS_EMPTY;
    _prFbg[ucFbgId].aucResize2SrcFbId[ucRzFbId] = FBM_FB_ID_UNKNOWN;
    _prFbg[ucFbgId].aucResize2TaskId[ucRzFbId] = 0xFF;

    ucNextWriteIdx = (_prFbg[ucFbgId].rResize2EmptyQ.ucReadIdx + _prFbg[ucFbgId].rResize2EmptyQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
    _prFbg[ucFbgId].rResize2EmptyQ.aucQueue[ucNextWriteIdx] = ucRzFbId;
    _prFbg[ucFbgId].rResize2EmptyQ.ucCount++;

}


//-------------------------------------------------------------------------
/** FBM_GetEmptyDelayTime
 *  If FBG without B2R mode, auto get empty from dispQ.
 *  @param  ucFbgId   FBG index.
 *  @param  pu4Delay   time to wait.
 *  @return 1/0 OK/Fail.
 */
//-------------------------------------------------------------------------

static UINT32 FBM_GetEmptyDelayTime(UCHAR ucFbgId, UINT32 *pu4Delay)
{
#ifdef ENABLE_MULTIMEDIA
    VDEC_ES_INFO_T *prVdecEsInfo;
    prVdecEsInfo = _VDEC_GetEsInfo(_prFbg[ucFbgId].u1DecoderSrcId);
#endif

    if (VERIFY_FBG(ucFbgId) || !pu4Delay)
    {
        return 0;
    }

    if ((_prFbg[ucFbgId].ucPlayMode == FBM_FBG_DTV_MODE)
#ifdef ENABLE_MULTIMEDIA
        ||
        ((_prFbg[ucFbgId].ucPlayMode == FBM_FBG_MM_MODE) &&
         (prVdecEsInfo->eContainerType == SWDMX_FMT_MPEG2_TS_TIME_SHIFT)
        )
#endif
       )
    {
        if (!FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_DISPLAYING))
        {
            *pu4Delay = FBM_WAIT_FB_TIMEOUT;
        }
        else if (_prFbg[ucFbgId].u4AvSyncStatus == FBM_FBG_AVSYNC_REPEAT)
        {
            /* During Frame repeat, wait FB for a longer time */
            *pu4Delay = FBM_WAIT_FB_TIMEOUT;
            LOG(3, "Start to play but frame repeat\n");
        }
    }

    if (FBM_ChkFrameBufferGlobalFlagIsr(ucFbgId, FBM_FLAG_FB_NO_TIMEOUT))
    {
        *pu4Delay = 0xfffff;
    }
    if (FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        *pu4Delay = 0;
    }

    if (FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_AUTO_RENDER))
    {
        switch (_prFbg[ucFbgId].rSeqHdr.ucFrmRatCod)
        {
            case MPEG_FRAME_RATE_12_:
            case MPEG_FRAME_RATE_12:
                *pu4Delay = 90000/FBM_FRAME_RATE_12;
                break;
            case MPEG_FRAME_RATE_15:
                *pu4Delay = 90000/FBM_FRAME_RATE_15;
                break;
            case MPEG_FRAME_RATE_20:
                *pu4Delay = 90000/FBM_FRAME_RATE_20;
                break;
            case MPEG_FRAME_RATE_24_:
            case MPEG_FRAME_RATE_24:
                *pu4Delay = 90000/FBM_FRAME_RATE_24;
                break;
            case MPEG_FRAME_RATE_25:
                *pu4Delay = 90000/FBM_FRAME_RATE_25;
                break;
            case MPEG_FRAME_RATE_30_:
            case MPEG_FRAME_RATE_30:
                *pu4Delay = 90000/FBM_FRAME_RATE_30;
                break;
            case MPEG_FRAME_RATE_50:
                *pu4Delay = 90000/FBM_FRAME_RATE_50;
                break;
            case MPEG_FRAME_RATE_60_:
            case MPEG_FRAME_RATE_60:
                *pu4Delay = 90000/FBM_FRAME_RATE_60;
                break;
            case MPEG_FRAME_RATE_UNKNOWN:
            default:
                LOG(1, "Unknown Frame Rate\n");
                *pu4Delay = 90000/FBM_FRAME_RATE_60;
                break;
        }
    }

    return 0; //ms
}


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

VOID FBM_SetFirstSeqChgFlag(UCHAR ucFbgId,BOOL bFlag)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);
    _prFbg[ucFbgId].fgGotFirstSeqChg = bFlag;
    FBM_MUTEX_UNLOCK(ucFbgId);
}


VOID FBM_SetRenderPts(UCHAR ucFbgId,UINT32 u4PTS)
{
    UCHAR ucDispQFb;    
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }
    if(FBM_ChkSeamlessMode(ucFbgId, SEAMLESS_BY_NPTV) ||
       FBM_ChkSeamlessMode(ucFbgId, SEAMLESS_BY_NONTUNNEL_NPTV))
    {
        LOG(0,"it's seamless case, FBM_SetRenderPts not support\n");
        return;
    }
    FBM_MUTEX_LOCK(ucFbgId);
    while (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        ucDispQFb = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
        if (_prFbg[ucFbgId].prPicHdr[ucDispQFb].u4PTS < u4PTS)
        {
            if(FBM_GetFrameBufferFromDispQ(ucFbgId) != ucDispQFb)
            {
                LOG(0,"Erro %s %d\n",__FUNCTION__,__LINE__);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return ;
            }
            FBM_ChkSeqChg(ucFbgId,ucDispQFb,FALSE);
            FBM_SetFrameBufferStatus(ucFbgId,ucDispQFb,FBM_FB_STATUS_LOCK);
            FBM_SetFrameBufferStatus(ucFbgId,ucDispQFb,FBM_FB_STATUS_EMPTY);
        }
        else
        {
            break;
        }
    }
    FBM_MUTEX_UNLOCK(ucFbgId);
}

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

//-------------------------------------------------------------------------
/** FBM_SetFrameBufferFlag
 *  Set FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  u4Flag   flag.
 *  @return NONE.
 */
//-------------------------------------------------------------------------

void FBM_SetFrameBufferFlag(UCHAR ucFbgId, UINT32 u4Flag)
{

    BOOL fgGotFirstSeqChg;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    fgGotFirstSeqChg = _prFbg[ucFbgId].fgGotFirstSeqChg;



    FBM_MUTEX_LOCK(ucFbgId);
    if (u4Flag == FBM_FLAG_SEQ_CHG || u4Flag == FBM_FLAG_SEQ_CHG_SPEEDUP)
    {
        _prFbg[ucFbgId].fgGotFirstSeqChg = TRUE;
#ifdef TIME_MEASUREMENT
        TMS_DIFF_EX(TMS_FLAG_CHG_CHL, TMS_CHL_CHE_TIME, "Vdec_SEQ_CHG");
        TMS_DIFF_EX(TMS_FLAG_BOOT, TMS_COOL_BOOT_TIME, "Vdec_SEQ_CHG");
        TMS_DIFF_EX(TMS_FLAG_INP_CHG, TMS_INP_SRC_CHE_TIME, "Vdec_SEQ_CHG");
#endif
        /*only tunnel mode and non-DV case ,can set FBM_FLAG_SEQ_CHG_SPEEDUP */
        LOG(0,"seqchg fgTunnelMode(%d), eDolbyType(%d)\n",_prFbg[ucFbgId].fgTunnelMode,_prFbg[ucFbgId].eDolbyType);
        if ((_prFbg[ucFbgId].fgTunnelMode == TRUE) && (_prFbg[ucFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_NONE))
        {
            u4Flag = FBM_FLAG_SEQ_CHG_SPEEDUP;
        }
        else
        {
            u4Flag = FBM_FLAG_SEQ_CHG;
        }
      
        if (u4Flag == FBM_FLAG_SEQ_CHG_SPEEDUP && fgGotFirstSeqChg == FALSE)
        {
            _prFbg[ucFbgId].u4FbgFlag |= u4Flag;
        }
        else
        {
            _prFbg[ucFbgId].u4SeqChgFlag = u4Flag;

            _prFbg[ucFbgId].ucSeqChg = 1;
            _prFbg[ucFbgId].ucNewFbId = FBM_FB_ID_UNKNOWN;
            _prFbg[ucFbgId].fgSeqChgPause = TRUE;
            _prFbg[ucFbgId].u4CrtFbgCnt++;
            _prFbg[ucFbgId].rSeqHdr.u4PendingSOC = _prFbg[ucFbgId].u4CrtFbgCnt;
            LOG(2,"Seq chg received! u4PendingSOC(%d)\n",_prFbg[ucFbgId].rSeqHdr.u4PendingSOC);
        }
#ifndef CC_VDEC_RM_SUPPORT
#ifdef CC_B2R_RM_SUPPORT

        if(!fgGotFirstSeqChg)
        {
            UCHAR ucB2rId = B2R_NULL;
            B2R_RM_T input_Src;
            VDEC_ES_INFO_T *prVdecEsInfo;
            VDEC_ES_INFO_KEEP_T *prVdecEsInfoKeep;
            prVdecEsInfo= _VDEC_GetEsInfo(_prFbg[ucFbgId].u1DecoderSrcId);
            prVdecEsInfoKeep = _VDEC_GetEsInfoKeep(_prFbg[ucFbgId].u1DecoderSrcId);
            input_Src.eVdecType = prVdecEsInfoKeep->eCurFMT;// prVdecEsInfoKeep->eCurFMT;
            input_Src.u2HActive = _prFbg[ucFbgId].rSeqHdr.u2HSize;//prVdecEsInfo->u2OrgHSize;
            input_Src.u2VActive =_prFbg[ucFbgId].rSeqHdr.u2VSize; //prVdecEsInfo->u2OrgVSize;
            input_Src.u2Fps = 30;//prVdecEsInfo->u4FrameRate/100;
            input_Src.fgUFOEnable =_prFbg[ucFbgId].rSeqHdr.fgUfoEn;//prVdecEsInfo->fgEnableUFO;
            input_Src.fg8Bit =!(_prFbg[ucFbgId].rSeqHdr.u1Depth==10); //(prVdecEsInfo->u4BitDepth == 8);
            input_Src.u2BlockMode = !(_prFbg[ucFbgId].rSeqHdr.fgRasterOrder);
            input_Src.ucEsId = _prFbg[ucFbgId].u1DecoderSrcId;

            FBM_MUTEX_UNLOCK(ucFbgId);
            if(!FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
            {
                if (prVdecEsInfo->u4RenderVDPId != 0xFF)
                {
                    VDP_SetB2RId(B2R_NULL, prVdecEsInfo->u4RenderVDPId, _prFbg[ucFbgId].u1DecoderSrcId);
                }

                ucB2rId = B2R_Source_Connect(input_Src);
                LOG(1,"cB2rId =%d,prVdecEsInfoKeep=%d,u1DecoderSrcId=%d,rSeqHdr.u1Depth=%d\n",ucB2rId,prVdecEsInfoKeep,_prFbg[ucFbgId].u1DecoderSrcId,_prFbg[ucFbgId].rSeqHdr.u1Depth);
                if (prVdecEsInfoKeep->pfnVdecSetParam && (ucB2rId >= B2R_3) && (ucB2rId < B2R_NULL))
                {
                    prVdecEsInfoKeep->pfnVdecSetParam(_prFbg[ucFbgId].u1DecoderSrcId, (UINT32)VDEC_BLK_MODE, 0, 0, 0);
                }
            }
            FBM_MUTEX_LOCK(ucFbgId);
        }
#endif
#endif
        if ((FBM_ChkSeamlessMode(ucFbgId, SEAMLESS_BY_NPTV)
             ||FBM_ChkSeamlessMode(ucFbgId, SEAMLESS_BY_NONTUNNEL_NPTV))
            && fgGotFirstSeqChg)
        {
            if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_SEQ_CHG_PRE_CB],
                                         _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_SEQ_CHG_PRE_CB]))
            {
                B2R_NPTV_PENDING_ITEM t_pending_item;

                if(FALSE == (((FBM_FB_SEQ_CHG_PRE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_SEQ_CHG_PRE_CB])(ucFbgId)))
                {
                    x_memset(&t_pending_item, 0, sizeof(B2R_NPTV_PENDING_ITEM));
                    t_pending_item.fgPending = TRUE;
                    t_pending_item.u4ItemSOC = _prFbg[ucFbgId].rSeqHdr.u4PendingSOC;
                    t_pending_item.u4PendingWdith = _prFbg[ucFbgId].rSeqHdr.u4SourceWidth;
                    t_pending_item.u4PendingHeight = _prFbg[ucFbgId].rSeqHdr.u4SourceHeight;

                    LOG(1, "Fbg(%d) H(%d) V(%d)\n", ucFbgId, t_pending_item.u4PendingWdith, t_pending_item.u4PendingHeight);
                    FBM_B2RNTPVSavePendingItem(ucFbgId, t_pending_item);
                }
            }
        }

        FBM_MUTEX_UNLOCK(ucFbgId);

        return;
    }
    _prFbg[ucFbgId].u4FbgFlag |= u4Flag;

    FBM_MUTEX_UNLOCK(ucFbgId);
}

//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferFlag
 *  Check FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  u4Flag   flag.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UCHAR FBM_ChkSeamlessMode(UCHAR ucFbgId, UINT32 u4Mode)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0;
    }

    return (_prFbg[ucFbgId].eSeamlessMode & u4Mode) ? 1 : 0;
}

//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferFlag
 *  Check FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  u4Flag   flag.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UINT32 FBM_SetSeamlessMode(UCHAR ucFbgId, UINT32 u4Mode)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return 0;
    }
    _prFbg[ucFbgId].eSeamlessMode |= u4Mode;
    return _prFbg[ucFbgId].eSeamlessMode;
}


//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferFlag
 *  Check FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  u4Flag   flag.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UCHAR FBM_ChkFrameBufferFlag(UCHAR ucFbgId, UINT32 u4Flag)
{
    UCHAR ucChk;

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

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].u4FbgFlag & u4Flag)
    {
        ucChk = 1;
    }
    else
    {
        ucChk = 0;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucChk;
}


//-------------------------------------------------------------------------
/** FBM_SetFrameBufferPicFlag
 *  Set FB Picture flag
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  u4Flag   flag.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFrameBufferPicFlag(UCHAR ucFbgId, UCHAR ucFbId, UINT32 u4Flag)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _prFbg[ucFbgId].prPicHdr[ucFbId].u4MmFlag |= u4Flag;
    if ((FBM_MM_EOS_FLAG == u4Flag) || (FBM_MM_PSEUDO_EOS_FLAG == u4Flag))
    {
        _prFbg[ucFbgId].fgSendEOS = TRUE;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
}


//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferPicFlag
 *  Check FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  u4Flag   flag.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UCHAR FBM_ChkFrameBufferPicFlag(UCHAR ucFbgId, UCHAR ucFbId, UINT32 u4Flag)
{
    UCHAR ucChk;

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

    FBM_MUTEX_LOCK(ucFbgId);


    if (_prFbg[ucFbgId].prPicHdr &&
        _prFbg[ucFbgId].prPicHdr[ucFbId].u4MmFlag & u4Flag)
    {
        ucChk = 1;
    }
    else
    {
        ucChk = 0;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucChk;
}


//-------------------------------------------------------------------------
/** FBM_ClrFrameBufferPicFlag
 *  Clear FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  u4Flag   flag.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_ClrFrameBufferPicFlag(UCHAR ucFbgId, UCHAR ucFbId, UINT32 u4Flag)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _prFbg[ucFbgId].prPicHdr[ucFbId].u4MmFlag &= ~u4Flag;

    FBM_MUTEX_UNLOCK(ucFbgId);
}


//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferFlagIsr
 *  Check FBG flag at ISR
 *  @param  ucFbgId   FBG index.
 *  @param  u4Flag   flag.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UCHAR FBM_ChkFrameBufferFlagIsr(UCHAR ucFbgId, UINT32 u4Flag)
{
    UCHAR ucChk;

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

    if (_prFbg[ucFbgId].u4FbgFlag & u4Flag)
    {
        ucChk = 1;
    }
    else
    {
        ucChk = 0;
    }

    return ucChk;
}


//-------------------------------------------------------------------------
/** FBM_ClrFrameBufferFlag
 *  Clear FBG flag
 *  @param  ucFbgId   FBG index.
 *  @param  u4Flag   flag.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_ClrFrameBufferFlag(UCHAR ucFbgId, UINT32 u4Flag)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _prFbg[ucFbgId].u4FbgFlag &= ~u4Flag;

    if ((u4Flag == FBM_FLAG_DEINTERLACE) &&
        (_prFbg[ucFbgId].u4ResidualFb == 1))
    {
        _prFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_RESET;
        _prFbg[ucFbgId].u4ResidualFree = 1;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferNs
 *  Get FBG frame buffer number
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer number.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFrameBufferNs(UCHAR ucFbgId)
{
    UCHAR ucFbNs;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbNs = (_prFbg[ucFbgId].ucFbNs - _prFbg[ucFbgId].ucFbNsBase);

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbNs;
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferSize
 *  Get FBG frame buffer size
 *  @param  ucFbgId   FBG index.
 *  @param  pu4Width   width pointer.
 *  @param  pu4Height   height pointer.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetFrameBufferSize(UCHAR ucFbgId, UINT32 *pu4Width, UINT32 *pu4Height)
{
    if ((pu4Width == NULL) || (pu4Height == NULL))
    {
        return;
    }

    *pu4Width = (UPTR)NULL;
    *pu4Height = (UPTR)NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pu4Width = _prFbg[ucFbgId].u4FbWidth;
    *pu4Height = _prFbg[ucFbgId].u4FbHeight;
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferStatus
 *  Get FBG frame buffer status
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return frame buffer status.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR ucFbStatus;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbStatus = _prFbg[ucFbgId].aucFbStatus[ucFbId];

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbStatus;
}


//-------------------------------------------------------------------------
/** FBM_CheckFrameBufferStatus
 *  Check FBG frame buffer status
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  ucFbStatus   FB status.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UCHAR FBM_CheckFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus)
{
    UCHAR ucValid;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucValid = (ucFbStatus == _prFbg[ucFbgId].aucFbStatus[ucFbId]);

    // VDP protection
    if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_NOT_READY)
    {
        ucValid = 1;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucValid;
}

UCHAR FBM_ChkFbDispTagInB2R(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR ucValid = 0;

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

    FBM_MUTEX_LOCK(ucFbgId);
    if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK) &&
        (_prFbg[ucFbgId].u4DispTag[ucFbId] == INVALID_DISPTAG))
    {
        ucValid = 1;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucValid;
}

//-------------------------------------------------------------------------
/** FBM_SetFrameBufferStatus
 *  Set FBG frame buffer status
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  ucFbStatus   frame buffer status.
 *  @return NONE.
 */
//-------------------------------------------------------------------------

#ifdef FBM_FB_LOG

#if 0
#ifdef FBM_SetFrameBufferStatus
//#undef FBM_SetFrameBufferStatus
#endif
void FBM_SetFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus)
{
    FBM_SetFrameBufferStatus_dbg(ucFbgId, ucFbId, ucFbStatus, __func__, __LINE__);
}
#endif

void FBM_SetFrameBufferStatus_dbg(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus, const CHAR* sFunc, const UINT32 u4Line)
#else
void FBM_SetFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus)
#endif
{

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

    FBM_MUTEX_LOCK(ucFbgId);

    // [LOG] FBM change FB status
    SYSLOG(FBM_PREFIX + ucFbgId, ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId], ucFbStatus);
    _FbmFbLog(ucFbgId,ucFbId, ucFbStatus, sFunc, u4Line);
    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_FB_STATUS) == FBM_ENABLE_LOG_FB_STATUS)
    {
        LOG(2,"Fbg-Fb(%d-%d):S(%d->%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId],ucFbStatus);
    }

//    LOG(7, "Fbg(%d) Fb(%d) %d >> %d\n", ucFbgId, ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId], ucFbStatus);
//    LOG(7, "Fb(%d, %x) %d >> %d\n", ucFbId, _prFbg[ucFbgId].au4AddrY[ucFbId], _prFbg[ucFbgId].aucFbStatus[ucFbId], ucFbStatus);

    // All FB go to EMPTY status at NOT READY mode
    if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_NOT_READY)
    {
        ucFbStatus = FBM_FB_STATUS_EMPTY;
    }

    // If Display NOT ready, don't put FB in DisplayQ (Display Q >> Empty)
    if ((ucFbStatus == FBM_FB_STATUS_DISPLAYQ) &&
        ((_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_DISP_READY) == 0))
    {
        ucFbStatus = FBM_FB_STATUS_EMPTY;
    }

    if (ucFbId == _prFbg[ucFbgId].ucFbDecode)
    {
        // check current decode frame buffer status change
        if ((ucFbStatus != FBM_FB_STATUS_DECODE) &&
            (ucFbStatus != FBM_FB_STATUS_FIELD_READY))
        {
            _prFbg[ucFbgId].ucFbDecode = FBM_FB_ID_UNKNOWN;
        }

        // check back reference frame buffer status change
        if (ucFbId == _prFbg[ucFbgId].ucFbBRef)
        {
            if ((ucFbStatus == FBM_FB_STATUS_READY) ||
                (ucFbStatus == FBM_FB_STATUS_FIELD_READY))
            {
                _prFbg[ucFbgId].ucFbBRefValid = 1;
            }
            else if (ucFbStatus == FBM_FB_STATUS_EMPTY) //if FBM_FB_STATUS_FIELD_READY->FBM_FB_STATUS_EMPTY, set BRef invalid.
            {
                _prFbg[ucFbgId].ucFbBRefValid = 0;
            }
            else
            {
            }
        }
    }

#if 1
    //need more test.
    // for new OMX, dropped frame should go back to OMX by display.
    if (_prFbg[ucFbgId].fgCreateFromInst && ucFbStatus == FBM_FB_STATUS_EMPTY && _prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
    {
        ucFbStatus = FBM_FB_STATUS_DISPLAYQ;
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgNotDisplay = TRUE;
        _FbmFbLog(ucFbgId,ucFbId, ucFbStatus, __func__, __LINE__);
    }
#endif
    switch (ucFbStatus)
    {
        case FBM_FB_STATUS_EMPTY:
            if (!FBM_ChkFrameBufferFlag(ucFbgId , FBM_FLAG_FREEZE|FBM_FLAG_RELEASE_FBG|FBM_FLAG_SEEK_MODE))
            {
#ifndef __MODEL_slt__
                if (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ)
                {
                    LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                }
                ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ);
#endif
            }

            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
            {
                _prFbg[ucFbgId].u4DispTag[ucFbId]=INVALID_DISPTAG;
                _prFbg[ucFbgId].u4DropTag[ucFbId] = INVALID_DISPTAG;
                _prFbg[ucFbgId].prPicHdr[ucFbId].fgPicFlush = FALSE;

                if (_prFbg[ucFbgId].fgCreateFromInst)
                {
                    if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1))
                    {
                        if(_prFbg[ucFbgId].afgRefList[ucFbId])
                        {
                            break;
                        }
                    }
                    ucFbStatus = FBM_FB_STATUS_RECYCLE;
                    break;
                }
                if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2) ||
                    (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1))
                {
                    if (_prFbg[ucFbgId].afgRefList[ucFbId])
                    {
                        // the resized frame should be useless now.
                        if (_prFbg[ucFbgId].fgEnableNewSeamless)
                        {

                            if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid != FBM_FB_ID_UNKNOWN &&
                                _prFbg[ucFbgId].aucResizeFbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid] != FBM_FB_STATUS_EMPTY)
                            {
                                HAL_GetTime(&_prFbg[ucFbgId].arRlResizeFb[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid]);
                                _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid);
                                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
                            }

                            if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid != FBM_FB_ID_UNKNOWN &&
                                _prFbg[ucFbgId].aucResize2FbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid] != FBM_FB_STATUS_EMPTY)
                            {
                                //HAL_GetTime(&_prFbg[ucFbgId].arRlResizeFb[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid]);
                                _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid);
                                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
                            }
                            _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessTaskId = 0xFF;
                        }

                        //don't release FB when it is still in the reference list.
                        break;
                    }
                    else
                    {
                        // release semaphore (Empty)
                        //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                    }
                }
                else
                {
                    if (IS_REFERENCE_FB(ucFbgId, ucFbId))
                    {
                        // release reference frame buffer
                    }
                    else
                    {
                        // release B frame buffer

                        // release semaphore (B & Empty)
                        VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyBQSemaphore) == OSR_OK);
                    }

                    // release semaphore (Empty)
                    //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                }
                _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbId);

                if (_prFbg[ucFbgId].fgEnableNewSeamless)
                {
                    if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid != FBM_FB_ID_UNKNOWN &&
                        _prFbg[ucFbgId].aucResizeFbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid] != FBM_FB_STATUS_EMPTY)
                    {
                        HAL_GetTime(&_prFbg[ucFbgId].arRlResizeFb[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid]);

                        if (_prFbg[ucFbgId].aucResizeFbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid] == FBM_FB_STATUS_EMPTY)
                        {
                            LOG(0, "Warning! rz fb already cleaned! \n");
                        }



                        if (ucFbId != _prFbg[ucFbgId].aucResizeSrcFbId[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid])
                        {
                            LOG(0,"srcId not match (%d %d)\n",ucFbId,
                                _prFbg[ucFbgId].aucResizeSrcFbId[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid]);

                        }

                        else
                        {
                            _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessResized = FALSE;
                            _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid);

                            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
                        }

                    }
                    else if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid != FBM_FB_ID_UNKNOWN &&
                             _prFbg[ucFbgId].aucResize2FbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid] != FBM_FB_STATUS_EMPTY)
                    {
                        //HAL_GetTime(&_prFbg[ucFbgId].arRlResizeFb[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid]);

                        if (_prFbg[ucFbgId].aucResize2FbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid] == FBM_FB_STATUS_EMPTY)
                        {
                            LOG(0, "Warning! rz fb already cleaned! \n");
                        }

                        _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessResized = FALSE;

                        _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid);
                        VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
                    }
                    _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessTaskId = 0xFF;
                }
            }
            break;

        case FBM_FB_STATUS_DECODE:
            _prFbg[ucFbgId].ucFbDecode = ucFbId;
            break;

        case FBM_FB_STATUS_DISPLAYQ:

            if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DECODE) ||
                (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_FIELD_READY)||
                (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_READY))
            {
#ifdef CC_53XX_SWDMX_V2
                //VDEC_GenPTS(_prFbg[ucFbgId].u1DecoderSrcId, ucFbgId, ucFbId);
#else
               // VDEC_GenPTS(ucFbgId, ucFbId);
#endif
                _FbmPutFrameBufferToDispQ(ucFbgId, ucFbId);

                if (_prFbg[ucFbgId].u1FbgAppMode == FBM_FBG_APP_OMX_DISP)
                {
#ifdef CC_USE_DDI
                    FBM_TriggerSmlsByResizer(ucFbgId, ucFbId);
#else
                    //stage fright case, do seamless in B2R send render msg.
                    //Otherwise, the stage fright drop frame will not update seamless FB to empty in time.
#endif
                }
                else
                {
                    FBM_TriggerSmlsByResizer(ucFbgId, ucFbId);
                }

            }
            else
            {
                if (_prFbg[ucFbgId].fgCreateFromInst)
                {
                    ASSERT_FBM(0);
                }
                if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DECODE) &&
                    (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_FIELD_READY)&&
                    (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_READY))
                {
                    LOG(0,"ucFbgId(%d)ucFbId(%d)FbStatus(%d) \n",
                        ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                }
                ASSERT_FBM((_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DECODE) ||
                           (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_FIELD_READY)||
                           (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_READY));

                if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
                {
                    if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP9) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2) ||
                        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AV1))
                    {
                        if (_prFbg[ucFbgId].afgRefList[ucFbId])
                        {
                            //don't release FB when it is still in the reference list.
                            break;
                        }
                        else
                        {
                            // release semaphore (Empty)
                            //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                        }
                    }
                    else
                    {
                        if (IS_REFERENCE_FB(ucFbgId, ucFbId))
                        {
                            // release reference frame buffer
                        }
                        else
                        {
                            // release B frame buffer

                            // release semaphore (B & Empty)
                            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyBQSemaphore) == OSR_OK);
                        }

                        // release semaphore (Empty)
                        //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                    }

                    _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbId);
                }
            }
            break;

        case FBM_FB_STATUS_READY:
            break;
        case FBM_FB_STATUS_LOCK:
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY)
            {
                ucFbStatus = FBM_FB_STATUS_EMPTY;
            }
            break;
        default:
            break;
    }

    _prFbg[ucFbgId].aucFbStatus[ucFbId] = ucFbStatus;

    FBM_MUTEX_UNLOCK(ucFbgId);

    if (ucFbStatus == FBM_FB_STATUS_DISPLAYQ
        && !(_prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp || _prFbg[ucFbgId].fgAutoSeamless)
        && !FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE) /*Thumbnail mode not call fb ready to b2r.*/)
    {
        FB_CHG_INFO_T t_fb_info;

        t_fb_info.fgOmxSrc = FALSE;
        t_fb_info.ucFbgId = ucFbgId;
        t_fb_info.ucFbid  = ucFbId;
        if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_FB_READY_IND]))
        {
            ((FBM_FB_READY_IND_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND])(&t_fb_info);
        }
        else
        {
            ASSERT_FBM(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND] == 0);
        }
    }

    if (ucFbStatus == FBM_FB_STATUS_DISPLAYQ)
    {
        if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->aau4CbFunc[ucFbgId][FBM_CB_FUNC_FB_READY_EX_IND],
                                     _prFbmCbFunc->aau4CbFuncCRC[ucFbgId][FBM_CB_FUNC_FB_READY_EX_IND]))
        {
            FBM_PIC_NTF_INFO_T rPicNfyInfo;
            x_memset(&rPicNfyInfo, 0, sizeof(FBM_PIC_NTF_INFO_T));
            rPicNfyInfo.ucFbgId = ucFbgId;
            rPicNfyInfo.ucFbId = ucFbId;
            rPicNfyInfo.eDolbyType = _prFbg[ucFbgId].eDolbyType;
            if (FBM_ChkFrameBufferPicFlag(ucFbgId, ucFbId, (FBM_MM_EOS_FLAG | FBM_MM_PSEUDO_EOS_FLAG)))
            {
                rPicNfyInfo.fgEos = TRUE;
            }
            ((FBM_FB_READY_IND_FUNC_EX)_prFbmCbFunc->aau4CbFunc[ucFbgId][FBM_CB_FUNC_FB_READY_EX_IND])(
                _prFbmCbFunc->aau4CbFuncTag[ucFbgId][FBM_CB_FUNC_FB_READY_EX_IND],
                &rPicNfyInfo);
        }
    }
}


//-------------------------------------------------------------------------
/** FBM_CheckFrameBufferDispQ
 *  Get FBG display queue size
 *  @param  ucFbgId   FBG index.
 *  @return display queue size.
 */
//-------------------------------------------------------------------------
UCHAR FBM_CheckFrameBufferDispQ(UCHAR ucFbgId)
{
    UCHAR ucCount, ucFbId;

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

    FBM_MUTEX_LOCK(ucFbgId);

    if(_prFbg[ucFbgId].rDisplayQ.ucReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return 0;
    }
    if (_prFbg[ucFbgId].prPicHdr == NULL)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return 0;
    }

    ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];

    if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return 0;
    }
    if (_prFbg[ucFbgId].prPicHdr[ucFbId].fgResizeDispFrm)
    {
        if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid == FBM_FB_ID_UNKNOWN)
        {
            FBM_MUTEX_UNLOCK(ucFbgId);
            return 0;
        }
        else
        {
            FBM_MUTEX_UNLOCK(ucFbgId);
            return 1;
        }
    }
    else
    {
        ucCount = _prFbg[ucFbgId].rDisplayQ.ucCount;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucCount;
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferFromDispQ
 *  Get frame buffer from display queue
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFrameBufferFromDispQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;
    UINT32 u4ChkIsGetFb = FBM_GETFBFROMDISPQ_DEFALUT;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbId = FBM_FB_ID_UNKNOWN;

    u4ChkIsGetFb =  _FBMChkIsGetFBFromDispQ(ucFbgId);

    if ((u4ChkIsGetFb == FBM_GETFBFROMDISPQ_STEP_DONE) || u4ChkIsGetFb == FBM_GETFBFROMDISPQ_FORCE_PAUSE)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }


    if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];

        _prFbg[ucFbgId].rDisplayQ.ucReadIdx =
            (UCHAR)(_prFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;
        _prFbg[ucFbgId].rDisplayQ.ucCount--;

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

        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
    }

    if (u4ChkIsGetFb == FBM_GETFBFROMDISPQ_STEP)
    {
        _FBMUpdateStepCount(ucFbgId);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}

//-------------------------------------------------------------------------
/** FBM_PreLook2ndFrameBufferFromDispQ
 *  Pre-look frame buffer from display queue
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------

UCHAR FBM_PreLook2ndFrameBufferFromDispQ(UCHAR ucFbgId)
{
    UCHAR ucFbId = FBM_FB_ID_UNKNOWN;

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

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].rDisplayQ.ucCount > 1)
    {
        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[(_prFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP];
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId(%d)\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
        }
        else
        {
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
            {
                LOG(0,"FbgId(%d) ucFbId(%d) FbStatus(%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                _FbmQueryFromDisplayQ(ucFbgId,0xFF);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
        }
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}
//-------------------------------------------------------------------------
/** FBM_PreLookNthFBFromDispQ
 *  Pre-look frame buffer from display queue
 *  @param  ucFbgId   FBG index.  @ucTheNth start from index 0. n means the N+1 th
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------

UCHAR FBM_PreLookNthFBFromDispQ(UCHAR ucFbgId, UCHAR ucTheNth)
{
    UCHAR ucFbId = FBM_FB_ID_UNKNOWN;
    UCHAR ucKeepFbNs = 0;

    if(ucTheNth > 1)
    {
        ucKeepFbNs = ucTheNth - 1;
    }

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

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].rDisplayQ.ucCount > ucKeepFbNs)
    {
        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[(_prFbg[ucFbgId].rDisplayQ.ucReadIdx + ucKeepFbNs) % FBM_MAX_FB_NS_PER_GROUP];
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId(%d)\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
        }
        else
        {
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",
                    ucFbgId,ucFbId,
                    _prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
        }
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}

//-------------------------------------------------------------------------
/** FBM_PreLookFrameBufferFromDispQ
 *  Pre-look frame buffer from display queue
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_PreLookFrameBufferFromDispQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbId = FBM_FB_ID_UNKNOWN;

    if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId(%d)\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",
                ucFbgId,ucFbId,
                _prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}

//-------------------------------------------------------------------------
/** FBM_GetNextDispQPts
 *  Get next frame buffer's PTS from display queue
 *  @param  ucFbgId   FBG index.
 *  @return PTS value.
 */
//-------------------------------------------------------------------------
UINT32 FBM_GetNextDispQPts(UCHAR ucFbgId)
{
    UINT32 u4Pts;
    UCHAR ucKeepFbNs = 0;

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

    FBM_MUTEX_LOCK(ucFbgId);

    u4Pts = 0;
    if (FBM_ChkSeamlessMode(ucFbgId, SEAMLESS_BY_NPTV))
    {
        ucKeepFbNs = _prFbg[ucFbgId].fgSendEOS ? 0 : 2;
    }
    if (_prFbg[ucFbgId].rDisplayQ.ucCount > ucKeepFbNs)
    {
        UCHAR ucFbId;

        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId(%d)\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return 0;
        }
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",ucFbgId,ucFbId,
                _prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);

        u4Pts = _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS;
    }
    else
    {
        // return last display q item
        UCHAR ucFbId;
        UCHAR ucLastQ;

        if (_prFbg[ucFbgId].rDisplayQ.ucReadIdx == 0)
        {
            ucLastQ = FBM_MAX_FB_NS_PER_GROUP - 1;
        }
        else
        {
            ucLastQ = (UCHAR)(_prFbg[ucFbgId].rDisplayQ.ucReadIdx - 1);
        }

        if (ucLastQ >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"LastQ(%d)\n",ucLastQ);
            ASSERT_FBM(ucLastQ < FBM_MAX_FB_NS_PER_GROUP);
            return 0;
        }

        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[ucLastQ];

        if (ucFbId < FBG_MAX_NS)
        {
            u4Pts = _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS;
        }
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return u4Pts;
}

//-------------------------------------------------------------------------
/** FBM_CalFrmRate
 *  Use next frame buffer's PTS from display queue to calculate frame rate
 *  @param  ucFbgId   FBG index.
 *  @return Frame rate type.
 */
//-------------------------------------------------------------------------
UCHAR FBM_CalFrmRate(UCHAR ucFbgId)
{
    UINT32 u4NextPts;
    UINT32 u4CurPts;
    UINT32 u4PtsDiff;
    UINT32 u4PtsInterval;
    INT32 i4NextTmpRef;
    INT32 i4CurTmpRef;
    UINT16 u2Interval;
    UCHAR ucFrmRate;
    UCHAR ucLastQ;

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

    FBM_MUTEX_LOCK(ucFbgId);

    u4NextPts = 0;
    ucFrmRate = MPEG_FRAME_RATE_UNKNOWN;

    if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        UCHAR ucFbId;

        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"FbId(%d)\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return 0;
        }
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",ucFbgId,ucFbId,
                _prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);

        u4NextPts = _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS;
        i4NextTmpRef = _prFbg[ucFbgId].prPicHdr[ucFbId].i4TemporalRef;

        if (_prFbg[ucFbgId].rDisplayQ.ucReadIdx == 0)
        {
            ucLastQ = FBM_MAX_FB_NS_PER_GROUP - 1;
        }
        else
        {
            ucLastQ = (UCHAR)(_prFbg[ucFbgId].rDisplayQ.ucReadIdx - 1);
        }

        if (ucLastQ >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"LastQ %d\n",ucLastQ);
            ASSERT_FBM(ucLastQ < FBM_MAX_FB_NS_PER_GROUP);
            return 0;
        }

        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[ucLastQ];

        u4CurPts = _prFbg[ucFbgId].prPicHdr[ucFbId].u4PTS;
        i4CurTmpRef = _prFbg[ucFbgId].prPicHdr[ucFbId].i4TemporalRef;

        if (u4NextPts >= u4CurPts)
        {
            u4PtsDiff = u4NextPts - u4CurPts;
        }
        else
        {
            u4PtsDiff = (0xFFFFFFFF - u4CurPts) + u4NextPts;
        }

        if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
            (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265))
        {
            /* H.264 temporal reference can not be used as units */
            u2Interval = 1;
        }
        else
        {
            if (i4NextTmpRef > i4CurTmpRef)
            {
                u2Interval = (UINT16)(i4NextTmpRef - i4CurTmpRef);
            }
            else
            {
                u2Interval = 1;
            }
        }

        u4PtsInterval = (u4PtsDiff /u2Interval);
        if(u4PtsInterval > FBM_PTS_FRM_RATE_15-FBM_PTS_FRM_RATE_TORRENCE)
        {
            ucFrmRate = MPEG_FRAME_RATE_30;
        }
        else if (u4PtsInterval == FBM_PTS_FRM_RATE_24)
        {
            ucFrmRate = MPEG_FRAME_RATE_24;
        }
        else if (u4PtsInterval > FBM_PTS_FRM_RATE_24-FBM_PTS_FRM_RATE_TORRENCE)
        {
            ucFrmRate = MPEG_FRAME_RATE_24_;
        }
        else if (u4PtsInterval >= FBM_PTS_FRM_RATE_25-FBM_PTS_FRM_RATE_TORRENCE)
        {
            ucFrmRate = MPEG_FRAME_RATE_25;
        }
        else if (u4PtsInterval >= FBM_PTS_FRM_RATE_30-1 && u4PtsInterval <= FBM_PTS_FRM_RATE_30+1)
        {
            ucFrmRate = MPEG_FRAME_RATE_30;
        }
        else if (u4PtsInterval > FBM_PTS_FRM_RATE_30-FBM_PTS_FRM_RATE_TORRENCE)
        {
            ucFrmRate = MPEG_FRAME_RATE_30_;
        }
        else if (u4PtsInterval >= FBM_PTS_FRM_RATE_50-FBM_PTS_FRM_RATE_TORRENCE)
        {
            ucFrmRate = MPEG_FRAME_RATE_50;
        }
        else if (u4PtsInterval == FBM_PTS_FRM_RATE_60)
        {
            ucFrmRate = MPEG_FRAME_RATE_60;
        }
        else if (u4PtsInterval > FBM_PTS_FRM_RATE_60-FBM_PTS_FRM_RATE_TORRENCE)
        {
            ucFrmRate = MPEG_FRAME_RATE_60_;
        }
        else
        {
            ucFrmRate = MPEG_FRAME_RATE_60;
        }
        LOG(1,"#### FBM calculate frame rate : %d %d\n",u4PtsInterval,ucFrmRate);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFrmRate;
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferAtIsr
 *  Get frame buffer from display queue at ISR
 *  @param  ucFbgId   FBG index.
 *  @param  pu4AddrY   Y Address.
 *  @param  pu4AddrC   C Address.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetFrameBufferAtIsr(UCHAR ucFbgId, UPTR* pu4AddrY, UPTR* pu4AddrC)
{
    if ((pu4AddrY == NULL) || (pu4AddrC == NULL))
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        *pu4AddrY = (UPTR)NULL;
        *pu4AddrC = (UPTR)NULL;
        return;
    }

    if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        UCHAR ucFbId;
        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];

        if (VERIFY_FB(ucFbgId, ucFbId))
        {
            *pu4AddrY = (UPTR)NULL;
            *pu4AddrC = (UPTR)NULL;
            return;
        }

        *pu4AddrY = _prFbg[ucFbgId].au4AddrY[ucFbId];
        *pu4AddrC = _prFbg[ucFbgId].au4AddrC[ucFbId];

        // [LOG] FBM get fb at ISR
        SYSLOG(FBM_PREFIX + 30 + ucFbgId, ucFbId, _prFbg[ucFbgId].au4AddrY[ucFbId], _prFbg[ucFbgId].au4AddrC[ucFbId]);
    }
    else
    {
        *pu4AddrY = (UPTR)NULL;
        *pu4AddrC = (UPTR)NULL;

        // [LOG] FBM get fb at ISR
        SYSLOG(FBM_PREFIX + 30 + ucFbgId, FBM_FB_ID_UNKNOWN, 0, 0);

        LOG(7, "FBAI-F\n");
    }
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferPicHdr
 *  Get frame buffer picture header
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return picture header.
 */
//-------------------------------------------------------------------------
#ifndef USERDRV_KERNEL_MOD

FBM_PIC_HDR_T *FBM_GetFrameBufferPicHdr(UCHAR ucFbgId, UCHAR ucFbId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        LOG(7,"FBG = %d , is invalid to get picture header.\n", ucFbgId);
        return NULL;
    }

    if (ucFbId != _prFbg[ucFbgId].ucFbNs)
    {
        if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
        {
            return NULL;
        }
    }
#if 0
    else if (FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_DEBLOCKING))
    {
        if (VERIFY_FBG(ucFbgId))
        {
            return NULL;
        }
    }
#endif

    if(_prFbg[ucFbgId].prPicHdr==NULL)
    {
        LOG(0,"FBM_GetFrameBufferPicHdr FBG[%d] PicHdr is Null\n",ucFbgId);
        return NULL;
    }
    else
    {
        return &(_prFbg[ucFbgId].prPicHdr[ucFbId]);
    }
}


//-------------------------------------------------------------------------
/** FBM_GetFrameBufferSeqHdr
 *  Get frame buffer sequence header
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return sequence header.
 */
//-------------------------------------------------------------------------
FBM_SEQ_HDR_T *FBM_GetFrameBufferSeqHdr(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return NULL;
    }

    return &(_prFbg[ucFbgId].rSeqHdr);
}
#endif

//-------------------------------------------------------------------------
/** FBM_GetFrameBufferSeqHdrByB2R
 *  Get frame buffer sequence header
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return sequence header.
 */
//-------------------------------------------------------------------------
FBM_SEQ_HDR_T *FBM_GetFrameBufferSeqHdrByB2R(UCHAR ucFbgId)
{
    FBM_SEQ_HDR_T* pSeqHdr = NULL;
    UCHAR ucReadIdx = 0;

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

    if ((FBM_ChkSeamlessMode(ucFbgId,(~SEAMLESS_NONE))) &&
        (!FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_RESIZER))&&
        (!FBM_ChkSeamlessMode(ucFbgId,POST_PROCESS_DISPLAY_ROTATE)))

    {
        ucReadIdx = _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx;
        if (ucReadIdx == 0)
        {
            ucReadIdx = FBM_MAX_FB_NS_PER_GROUP-1;
        }
        else
        {
            ucReadIdx--;
        }
        if (ucReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
        {
            return NULL;
        }
        pSeqHdr = &_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucReadIdx].rPendingSeqHdr;
        if (pSeqHdr)
        {
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_SEQCHG) == FBM_ENABLE_LOG_SEQCHG)
            {
                LOG(3,"New SeqHdr[%d] W/H (%d-%d)\n",ucReadIdx,pSeqHdr->u4SourceWidth,pSeqHdr->u4SourceHeight);
            }
            // error handle enhance
            if ((pSeqHdr->u4SourceHeight != 0) && (pSeqHdr->u4SourceWidth != 0))
            {
                return pSeqHdr;
            }
            else
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_SEQCHG) == FBM_ENABLE_LOG_SEQCHG)
                {
                    LOG(2,"Org SeqHdr[%d] W/H (%d-%d)\n",ucReadIdx,
                        _prFbg[ucFbgId].rSeqHdr.u4SourceWidth,
                        _prFbg[ucFbgId].rSeqHdr.u4SourceHeight);
                }

                return &(_prFbg[ucFbgId].rSeqHdr);
            }
        }
        else
        {
            LOG(0,"Seq Hdr info NULL\n");
            return NULL;
        }

    }
    else
    {
        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_SEQCHG) == FBM_ENABLE_LOG_SEQCHG)
        {
            LOG(3,"SeqHdr W/H (%d-%d)\n",_prFbg[ucFbgId].rSeqHdr.u4SourceWidth,_prFbg[ucFbgId].rSeqHdr.u4SourceHeight);
        }
        return &(_prFbg[ucFbgId].rSeqHdr);
    }

}

//-------------------------------------------------------------------------
/** FBM_GetLastSeqChgItem
 *  Get frame buffer sequence header
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return sequence header.
 */
//-------------------------------------------------------------------------
FBM_SeqChg_T *FBM_GetLastSeqChgItem(UCHAR ucFbgId)
{
    UCHAR ucReadIdx = 0;
    FBM_SEQ_HDR_T* pSeqHdr = NULL;
    FBM_SeqChg_T*  pSeqChgQueItem = NULL;

    if (_prFbg == NULL)
    {
        return NULL;
    }

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

    if ((FBM_ChkSeamlessMode(ucFbgId,(~SEAMLESS_NONE))) &&
        (!FBM_ChkSeamlessMode(ucFbgId,SEAMLESS_BY_RESIZER)))

    {
        ucReadIdx = (_prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx + _prFbg[ucFbgId].rSeqChgPendingQ.ucCount)%FBM_MAX_FB_NS_PER_GROUP;

        if (ucReadIdx == 0)
        {
            ucReadIdx = FBM_MAX_FB_NS_PER_GROUP - 1;
        }
        else
        {
            ucReadIdx--;
        }
        if (ucReadIdx >= FBM_MAX_FB_NS_PER_GROUP)
        {
            return NULL;
        }

        pSeqHdr = &_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucReadIdx].rPendingSeqHdr;
        pSeqChgQueItem = &_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucReadIdx];
        if (pSeqHdr && pSeqChgQueItem)
        {
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_SEQCHG) == FBM_ENABLE_LOG_SEQCHG)
            {
                LOG(3,"New SeqHdr[%d] W/H (%d-%d)\n",ucReadIdx,pSeqHdr->u4SourceWidth,pSeqHdr->u4SourceHeight);
            }

            return pSeqChgQueItem;

        }
        else
        {
            LOG(0,"Seq Hdr info NULL\n");
            return NULL;
        }

    }

    return NULL;
}

//-------------------------------------------------------------------------
/** FBM_GetFrameBufferAddr
 *  Get frame buffer address
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  pu4AddrY   Y Address.
 *  @param  pu4AddrC   C Address.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
#ifndef USERDRV_KERNEL_MOD
void FBM_GetFrameBufferAddr(UCHAR ucFbgId, UCHAR ucFbId, UPTR *pu4AddrY, UPTR *pu4AddrC)
{
    if ((pu4AddrY == NULL) || (pu4AddrC == NULL))
    {
        return;
    }

    *pu4AddrY = (UPTR)NULL;
    *pu4AddrC = (UPTR)NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if (VERIFY_FB(ucFbgId, ucFbId))
    {
        if (ucFbId != _prFbg[ucFbgId].ucFbNs)
        {
            return;
        }
    }
    if (ucFbId>=FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"FbId(%d)\n",ucFbId);
        ASSERT_FBM(ucFbId<FBM_MAX_FB_NS_PER_GROUP);
        return;
    }

    *pu4AddrY = _prFbg[ucFbgId].au4AddrY[ucFbId];
    *pu4AddrC = _prFbg[ucFbgId].au4AddrC[ucFbId];

}
#endif
//-------------------------------------------------------------------------
/** FBM_GetFrameBufferExtAddr
 *  Get frame buffer address
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @param  pu4AddrExtY   Y_LEN Address.
 *  @param  pu4AddrExtC   C_EN Address.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
#ifndef USERDRV_KERNEL_MOD
VOID FBM_GetFrameBufferAddrExt(UCHAR ucFbgId, UCHAR ucFbId, UPTR *pu4AddrYExt, UPTR *pu4AddrCExt)
{

    if ((pu4AddrYExt == NULL) || (pu4AddrCExt == NULL))
    {
        return;
    }

    *pu4AddrYExt = (UPTR)NULL;
    *pu4AddrCExt = (UPTR)NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if (VERIFY_FB(ucFbgId, ucFbId))
    {
        if (ucFbId != _prFbg[ucFbgId].ucFbNs)
        {
            return;
        }
    }
    if (ucFbId>=FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"FbId(%d)\n",ucFbId);
        ASSERT_FBM(ucFbId<FBM_MAX_FB_NS_PER_GROUP);
        return;
    }

    *pu4AddrYExt = _prFbg[ucFbgId].au4AddrY_Ext[ucFbId];
    *pu4AddrCExt = _prFbg[ucFbgId].au4AddrC_Ext[ucFbId];


}
#endif
//-------------------------------------------------------------------------
/** FBM_GetFrameBufferAddrMv
 *  Get MV buffer address. H264 ONLY.
 *  @param  ucFbgId   FBG index.
 *  @param  ucMvBufId   MV buffer index.
 *  @param  pu4AddrMv   MV buffer address.
 *  @return NONE.
 */
//-------------------------------------------------------------------------

void FBM_GetFrameBufferAddrMv(UCHAR ucFbgId, UCHAR ucMvBufId, UPTR *pu4AddrMv)
{
    if (pu4AddrMv == NULL)
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if ((ucMvBufId>=_prFbg[ucFbgId].ucMvBufNs) || (ucMvBufId>=FBM_MAX_FB_NS_PER_GROUP-1))
    {
        return;
    }

    *pu4AddrMv = _prFbg[ucFbgId].au4AddrMv[ucMvBufId];

}

//-------------------------------------------------------------------------
/** FBM_GetFrameBufferMvNs
 *  Get MV buffer Ns. H264 ONLY.
 *  @param  ucFbgId   FBG index.
 *  @param  ucMvBufId   MV buffer index.
 *  @param  pu4AddrMv   MV buffer address.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetFrameBufferMvNs(UCHAR ucFbgId)
{
    UCHAR ucFbNs;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbNs = _prFbg[ucFbgId].ucMvBufNs;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbNs;
}

//-------------------------------------------------------------------------
/** FBM_GetWorkingBuffer
 *  Get MV buffer address.
 *  @param  ucFbgId   FBG index.
 *  @param  pu4Addr   Working buffer address.
 *  @param  pu4Size    Working buffer size.
 *  @return NONE.
 */
//-------------------------------------------------------------------------


void FBM_GetWorkingBuffer(UCHAR ucFbgId, UPTR *pu4Addr, UINT32 *pu4Size)
{
    if ((pu4Addr == NULL) || (pu4Size == NULL))
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pu4Addr = _prFbg[ucFbgId].au4AddrMv[0];
    *pu4Size = _prFbg[ucFbgId].u4WorkBufSize;

}

void FBM_GetExtraFrameBuffer(UCHAR ucFbgId, UPTR* pu4YAddr, UPTR* pu4CAddr)
{
    if ( (pu4YAddr == NULL) || (pu4CAddr == NULL) )
    {
        return;
    }
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pu4YAddr = _prFbg[ucFbgId].u4ExtraYBuffer;
    *pu4CAddr = _prFbg[ucFbgId].u4ExtraCBuffer;
}


//-------------------------------------------------------------------------
/** FBM_GetDecFrameBuffer
 *  Get decoding frame buffer
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetDecFrameBuffer(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbId = _prFbg[ucFbgId].ucFbDecode;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}


//-------------------------------------------------------------------------
/** FBM_GetReadyFrameBuffer
 *  Get ready frame buffer
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetReadyFrameBuffer(UCHAR ucFbgId)
{
    // Notes about usage
    // Error Concealment background for I picture

    UCHAR ucFbId;
    UINT32 u4FbIdx;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbId = FBM_FB_ID_UNKNOWN;

    if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
    {
        // get the last FB at display Q

        u4FbIdx = (UINT32)(((_prFbg[ucFbgId].rDisplayQ.ucReadIdx + _prFbg[ucFbgId].rDisplayQ.ucCount) - 1) % FBM_MAX_FB_NS_PER_GROUP);
        ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[u4FbIdx];

        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) FbStatus(%d)\n",ucFbgId,ucFbId,
                _prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
    }
    else
    {
        // get locked frame buffer
        for (u4FbIdx = _prFbg[ucFbgId].ucFbNsBase;
             ((u4FbIdx < _prFbg[ucFbgId].ucFbNs)&& (u4FbIdx < FBM_MAX_FB_NS_PER_GROUP)); u4FbIdx++)
        {
            if (_prFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
            {
                ucFbId = (UCHAR)u4FbIdx;
                u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;
            }
        }

        // get any frame buffer which is NOT decoding
        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            for (u4FbIdx = _prFbg[ucFbgId].ucFbNsBase; u4FbIdx < _prFbg[ucFbgId].ucFbNs; u4FbIdx++)
            {
                if (_prFbg[ucFbgId].ucFbDecode != (UCHAR)(u4FbIdx))
                {
                    ucFbId = (UCHAR)u4FbIdx;
                    u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;
                }
            }
        }
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}


//-------------------------------------------------------------------------
/** FBM_GetRefFrameBuffer
 *  Get reference frame buffer
 *  @param  ucFbgId   FBG index.
 *  @param  ucFRefFbId   forward reference FB index pointer.
 *  @param  ucBRefFbId   backward reference FB index pointer.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_GetRefFrameBuffer(UCHAR ucFbgId, UCHAR* ucFRefFbId, UCHAR* ucBRefFbId)
{
    if ((ucFRefFbId == NULL) ||
        (ucBRefFbId == NULL))
    {
        return;
    }

    if (VERIFY_FBG(ucFbgId))
    {
        *ucFRefFbId = FBM_FB_ID_UNKNOWN;
        *ucBRefFbId = FBM_FB_ID_UNKNOWN;

        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].ucFbFRefValid)
    {
        *ucFRefFbId = _prFbg[ucFbgId].ucFbFRef;
    }
    else
    {
        *ucFRefFbId = FBM_FB_ID_UNKNOWN;
    }

    if (_prFbg[ucFbgId].ucFbBRefValid)
    {
        *ucBRefFbId = _prFbg[ucFbgId].ucFbBRef;
    }
    else
    {
        *ucBRefFbId = FBM_FB_ID_UNKNOWN;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
}

void FBM_PrintFBStatus(UCHAR ucFbgId)
{
    UINT32 u4FbIdx;
    CHAR szDebug1[FBM_MAX_FB_NS_PER_GROUP+1];

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

    for (u4FbIdx = _prFbg[ucFbgId].ucFbNsBase;
         ((u4FbIdx < _prFbg[ucFbgId].ucFbNs)&& (u4FbIdx < FBM_MAX_FB_NS_PER_GROUP)); u4FbIdx++)
    {
        szDebug1[u4FbIdx] = '0' +  _prFbg[ucFbgId].aucFbStatus[u4FbIdx];
    }
    szDebug1[u4FbIdx] = 0;

    LOG(1, "%s\n", szDebug1);
}


//-------------------------------------------------------------------------
/** FBM_GetEmptyRefFrameBuffer
 *  Get empty reference frame buffer
 *  @param  ucFbgId   FBG index.
 *  @param  u4Delay   time to wait.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetEmptyRefFrameBuffer(UCHAR ucFbgId, UINT32 u4Delay)
{
#ifdef CC_MT5351_SLT
    HAL_TIME_T rStart;
    HAL_TIME_T rStop;
    HAL_TIME_T rDelta;
#endif

    UCHAR ucFbId;

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

#ifdef CC_MT5351_SLT
    HAL_GetTime(&rStart);
#endif
    FBM_MUTEX_LOCK(ucFbgId);

    FBM_GetEmptyDelayTime(ucFbgId, &u4Delay);

    // We should not change status at NOT READY mode
    if (_prFbg[ucFbgId].u4FbgFlag & (FBM_FLAG_NOT_READY | FBM_FLAG_RESET | FBM_FLAG_CLEAR_FRC_PRM))
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        LOG(0,"%s %d\n",__FUNCTION__,__LINE__);

        return FBM_FB_ID_UNKNOWN;
    }
    //LOG(1, "REF: ");
    //FBM_PrintFBStatus(ucFbgId);

    ucFbId = FBM_FB_ID_UNKNOWN;

    // wait semaphore (Empty)
    if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
    {
        // wait semaphore success
        ucFbId = _FbmGetRefFrameBufferFromEmptyQ(ucFbgId);

        // Work around counting semaphore issue
        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"%s %d\n",__FUNCTION__,__LINE__);

            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        if (IS_REFERENCE_FB(ucFbgId, ucFbId) ||
            (FBM_FB_ID_UNKNOWN == _prFbg[ucFbgId].ucFbFRef) ||
            (FBM_FB_ID_UNKNOWN == _prFbg[ucFbgId].ucFbBRef))
        {
            // we get an empty reference frame buffer
        }
        else
        {
            // we get an empty B fram buffer

            // In this case, old forward reference become B, Bug Fixed (20041110)
            if (_prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].ucFbFRef] != FBM_FB_STATUS_EMPTY)
            {
                // wait semaphore (B & Empty)
                //                VERIFY(_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyBQSemaphore, X_SEMA_OPTION_NOWAIT, 0) == OSR_OK);
                if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyBQSemaphore, X_SEMA_OPTION_NOWAIT, 0) != OSR_OK)
                {
                    if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
                    {
                        // reset, handle abnormal case

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

                        return FBM_FB_ID_UNKNOWN;
                    }
                    else
                    {
                        //ASSERT_FBM(0);
                    }
                }

#if 0
                // London Bug
                // Put old forward reference to Empty if it is still in ready status
                if (_prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].ucFbFRef] == FBM_FB_STATUS_READY)
                {
                    if (_prFbg[ucFbgId].fgCreateFromInst)
                    {
                        ASSERT_FBM(0);
                    }

                    LOG(1, "[ERR] Reference FB leak!\n");
                    LOG(0,"FRef %d Status %d\n",_prFbg[ucFbgId].ucFbFRef,_prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].ucFbFRef]);

                    FBM_SetFrameBufferStatus(ucFbgId, _prFbg[ucFbgId].ucFbFRef, FBM_FB_STATUS_EMPTY);
                }
#endif

            }
        }

        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"FbId %d\n",ucFbId);

            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
#if 0 //def __KERNEL__
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
        {
            if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
            {
                return FBM_FB_ID_UNKNOWN;
            }
            else
            {
                if (_prFbg[ucFbgId].fgCreateFromInst)
                {
                    ASSERT_FBM(0);
                }
#if 1
                switch (_prFbg[ucFbgId].aucFbStatus[ucFbId])
                {
                    case FBM_FB_STATUS_DISPLAYQ:
                        _FbmGetFrameBufferFromDispQ(ucFbgId, ucFbId);
                        //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                        FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
                        break;
                    case FBM_FB_STATUS_DECODE:
                    case FBM_FB_STATUS_READY:
                    case FBM_FB_STATUS_LOCK:
                    default:
                        // VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                        FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
                        break;
                }
#endif
            }
        }
#else
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
                ucFbgId,ucFbId,
                _prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
#endif
    }
    #if 0
    else
    {
        // wait semaphore fail
        if (_prFbg[ucFbgId].hEmptyQSemaphore.i4Count > 0)
        {
            LOG(0,"ucFbgId %d i4Count %d\n",
                ucFbgId,
                _prFbg[ucFbgId].hEmptyQSemaphore.i4Count);
        }
        ASSERT_FBM(_prFbg[ucFbgId].hEmptyQSemaphore.i4Count == 0);

        if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
        {
            if (_prFbg[ucFbgId].fgCreateFromInst)
            {
                ASSERT_FBM(0);
            }
            // get frame buffer from display Q

            ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
            _prFbg[ucFbgId].rDisplayQ.ucReadIdx =
                (UCHAR)((_prFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP);
            _prFbg[ucFbgId].rDisplayQ.ucCount--;

            LOG(6, "[LINE%d]Get FB(%d-%d) From DispQ Cnt%d.\n", __LINE__, ucFbgId, ucFbId, _prFbg[ucFbgId].rDisplayQ.ucCount);
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"ucFbId %d\n",ucFbId);
                ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
                    ucFbgId,ucFbId,
                    _prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
        }
        else
        {
            UINT32 u4FbIdx;
            if (_prFbg[ucFbgId].fgCreateFromInst)
            {
                ASSERT_FBM(0);
            }

            // it is possible. Both Ref is lock by vdp
            // 2005/02/18 William, I found this case when change channel, fbm reset is pending

            if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
            {
                // get locked frame buffer
                for (u4FbIdx = 0; u4FbIdx < FBM_MAX_FB_NS_PER_GROUP; u4FbIdx++)
                {
                    if (_prFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
                    {
                        LOG(3, "{DL}\n");

                        ucFbId = (UCHAR)u4FbIdx;
                        u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;

                        // ask vdp to reset parameter, otherwise, assert at vdp set status to empty
                        _prFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_CLEAR_FRC_PRM;
                    }
                }
            }

            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                LOG(0,"%s %d\n",__FUNCTION__,__LINE__);

                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
        }
    }
    #endif

    if (ucFbId == FBM_FB_ID_UNKNOWN)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    if (ucFbId != FBM_FB_ID_UNKNOWN)
    {
        _prFbg[ucFbgId].ucLastDecodeReference = 1;
    }

    if ((ucFbId != FBM_FB_ID_UNKNOWN) &&
        (ucFbId != _prFbg[ucFbgId].ucFbBRef))
    {
        _prFbg[ucFbgId].ucFbFRef = _prFbg[ucFbgId].ucFbBRef;
        _prFbg[ucFbgId].ucFbBRef = ucFbId;
        _prFbg[ucFbgId].ucFbFRefValid = _prFbg[ucFbgId].ucFbBRefValid;
        _prFbg[ucFbgId].ucFbBRefValid = 0;
    }

    // Auto-Change Empty Status to Decode Status
    // Bug Fixed (20041206)
    _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_DECODE, __func__, __LINE__);
    if (_prFbg[ucFbgId].ucFbDecode != FBM_FB_ID_UNKNOWN)
    {
        LOG(0,"ucFbgId(%d) ucFbDecode(%d)\n", ucFbgId, _prFbg[ucFbgId].ucFbDecode);
    }
    ASSERT_FBM(_prFbg[ucFbgId].ucFbDecode == FBM_FB_ID_UNKNOWN);

    _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DECODE;
    _prFbg[ucFbgId].ucFbDecode = ucFbId;
    _FbmResetPicHdrFields(ucFbgId, ucFbId);

    FBM_MUTEX_UNLOCK(ucFbgId);

#ifdef CC_MT5351_SLT
    HAL_GetTime(&rStop);

    HAL_GetDeltaTime(&rDelta, &rStart, &rStop);

    if (rDelta.u4Micros > 100000)
    {
        LOG(1, "GetRefTime %u.%6u\n", rDelta.u4Seconds, rDelta.u4Micros);
    }
#endif
    return ucFbId;
}

//-------------------------------------------------------------------------
/** FBM_GetEmptyBFrameBuffer
 *  Get empty B frame buffer
 *  @param  ucFbgId   FBG index.
 *  @param  u4Delay   time to wait.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetEmptyBFrameBuffer(UCHAR ucFbgId, UINT32 u4Delay)
{
#ifdef CC_MT5351_SLT
    HAL_TIME_T rStart;
    HAL_TIME_T rStop;
    HAL_TIME_T rDelta;
#endif

    UCHAR ucFbId;

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

#ifdef CC_MT5351_SLT
    HAL_GetTime(&rStart);
#endif

    FBM_MUTEX_LOCK(ucFbgId);

    FBM_GetEmptyDelayTime(ucFbgId, &u4Delay);

    // We should not change status at NOT READY mode
    if (_prFbg[ucFbgId].u4FbgFlag & (FBM_FLAG_NOT_READY | FBM_FLAG_RESET | FBM_FLAG_CLEAR_FRC_PRM))
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }
    //LOG(1, "B: ");
    //FBM_PrintFBStatus(ucFbgId);

    ucFbId = FBM_FB_ID_UNKNOWN;
    // wait semaphore (B & Empty)
    if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyBQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
    {
        // wait semaphore success

        // wait semaphore (Empty)
        if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_NOWAIT, 0) != OSR_OK)
        {
            if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
            {
                // reset, handle abnormal case

                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            else
            {
                ASSERT_FBM(0);
            }
        }

        ucFbId = _FbmGetBFrameBufferFromEmptyQ(ucFbgId);

        if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
        {
            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                LOG(1, "[Warning] Get Empty B Fail (%d, %d)\n", ucFbgId, ucFbId);

                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
        }
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d) \n",
                ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
    }
    #if 0
    else
    {
        // wait semaphore fail
        if (_prFbg[ucFbgId].hEmptyBQSemaphore.i4Count > 0)
        {
            LOG(0,"ucFbgId(%d) i4Count(%d)\n",ucFbgId,_prFbg[ucFbgId].hEmptyBQSemaphore.i4Count);
        }
        ASSERT_FBM(_prFbg[ucFbgId].hEmptyBQSemaphore.i4Count == 0);

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

            LOG(3,"{DQ}");
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"ucFbId %d\n",ucFbId);
                ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
                    ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
        }
        else
        {
            UINT32 u4FbIdx;
            if (_prFbg[ucFbgId].fgCreateFromInst)
            {
                ASSERT_FBM(0);
            }

            // it is possible. Both Ref is lock by vdp
            // 2005/02/18 William, I found this case when change channel, fbm reset is pending

            if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
            {
                // get locked frame buffer
                for (u4FbIdx = 0; u4FbIdx < FBM_MAX_FB_NS_PER_GROUP; u4FbIdx++)
                {
                    if (_prFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
                    {
                        LOG(3, "{DL}\n");

                        ucFbId = (UCHAR)u4FbIdx;
                        u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;

                        // ask vdp to reset parameter, otherwise, assert at vdp set status to empty
                        _prFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_CLEAR_FRC_PRM;
                    }
                }
            }

            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
        }
    }
    #endif

    if (ucFbId == FBM_FB_ID_UNKNOWN)
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    if (ucFbId != FBM_FB_ID_UNKNOWN)
    {
        _prFbg[ucFbgId].ucLastDecodeReference = 0;
    }

    // Auto-Change Empty Status to Decode Status
    // Bug Fixed (20041206)
    _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_DECODE, __func__, __LINE__);
    if (_prFbg[ucFbgId].ucFbDecode != FBM_FB_ID_UNKNOWN)
    {
        LOG(0,"ucFbgId(%d) ucFbDecode(%d)\n",ucFbgId,_prFbg[ucFbgId].ucFbDecode);
    }
    ASSERT_FBM(_prFbg[ucFbgId].ucFbDecode == FBM_FB_ID_UNKNOWN);
    if (ucFbId < FBM_MAX_FB_NS_PER_GROUP)
    {
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DECODE;
        _prFbg[ucFbgId].ucFbDecode = ucFbId;
        _FbmResetPicHdrFields(ucFbgId, ucFbId);
    }

    // [LOG] FBM get empty B FB
    SYSLOG(FBM_PREFIX + 20 + ucFbgId, ucFbId, _prFbg[ucFbgId].rEmptyQ.ucCount, 0);

    FBM_MUTEX_UNLOCK(ucFbgId);

#ifdef CC_MT5351_SLT
    HAL_GetTime(&rStop);

    HAL_GetDeltaTime(&rDelta, &rStart, &rStop);

    if (rDelta.u4Micros > 100000)
    {
        LOG(1, "GetBTime %u.%6u\n", rDelta.u4Seconds, rDelta.u4Micros);
    }
#endif

    return ucFbId;
}


//-------------------------------------------------------------------------
/** FBM_GetEmptyFrameBuffer
 *  Get empty frame buffer. H264 ONLY.
 *  @param  ucFbgId   FBG index.
 *  @param  u4Delay   time to wait.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetEmptyFrameBuffer(UCHAR ucFbgId, UINT32 u4Delay)
{
    UCHAR ucFbId;
    if (VERIFY_FBG(ucFbgId))
    {
        return FBM_FB_ID_UNKNOWN;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    FBM_GetEmptyDelayTime(ucFbgId, &u4Delay);

    // We should not change status at NOT READY mode
    if (_prFbg[ucFbgId].u4FbgFlag & (FBM_FLAG_NOT_READY | FBM_FLAG_RESET | FBM_FLAG_CLEAR_FRC_PRM))
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    ucFbId = FBM_FB_ID_UNKNOWN;


    // wait semaphore (Empty)
    if ((_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK))
    {
        // wait semaphore success
        ucFbId = _FbmGetEmptyFrameBufferFromEmptyQ(ucFbgId);

        // Work around counting semaphore issue
        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId(%d)\n",ucFbId);

            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",ucFbgId,ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
    }
    else
    {
        // wait semaphore fail

        if (_prFbg[ucFbgId].fgCreateFromInst)
        {
            ASSERT_FBM(0);
        }
        if (_prFbg[ucFbgId].hEmptyQSemaphore.i4Count > 0)
        {
            LOG(0,"ucFbgId(%d) i4Count(%d) fgIsSeamlessCft(%d)\n",ucFbgId,_prFbg[ucFbgId].hEmptyQSemaphore.i4Count,
                _prFbg[ucFbgId].fgIsSeamlessCft);
        }
        ASSERT_FBM(_prFbg[ucFbgId].hEmptyQSemaphore.i4Count == 0);

        if ((_prFbg[ucFbgId].rDisplayQ.ucCount > 0 && FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE)))
        {
            UCHAR ucTmpId = 0;
            UCHAR ucTmpFbId = FBM_FB_ID_UNKNOWN;

            ucFbId = FBM_FB_ID_UNKNOWN;

            // get frame buffer from display Q. Ref FB only set Empty
            for (ucTmpId = 0; ucTmpId < _prFbg[ucFbgId].rDisplayQ.ucCount; ucTmpId++)
            {
                ucTmpFbId = FBM_GetFrameBufferFromDispQ(ucFbgId);

                if ((ucTmpFbId < FBM_MAX_FB_NS_PER_GROUP) && _prFbg[ucFbgId].afgRefList[ucTmpFbId])
                {
                    FBM_SetFrameBufferStatus(ucFbgId, ucTmpFbId, FBM_FB_STATUS_LOCK);
                    FBM_SetFrameBufferStatus(ucFbgId, ucTmpFbId, FBM_FB_STATUS_EMPTY);

                    LOG(0,"Set Status ucTmpFbId %d\n",ucTmpFbId);

                }
                else if (ucTmpFbId < FBM_MAX_FB_NS_PER_GROUP)
                {
                    ucFbId = ucTmpFbId;
                    LOG(0,"ucTmpFbId %d\n",ucTmpFbId);
                    break;
                }
                else
                {
                    LOG(0, "[LINE%d]Get FB(%d-%d) From DispQ Error!.\n", __LINE__, ucFbgId, ucFbId);
                    if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
                    {
                        LOG(0,"ucFbId(%d)\n",ucFbId);
                    }
                    ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
                }
            }


            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                LOG(0,"All displayQ are reference frame!!\n");
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }

            LOG(6, "[LINE%d]Get FB(%d-%d) From DispQ Cnt%d.\n", __LINE__, ucFbgId, ucFbId, _prFbg[ucFbgId].rDisplayQ.ucCount);

            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"ucFbId(%d)\n",ucFbId);
                ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
#if 1 //FixMe
            if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid != FBM_FB_ID_UNKNOWN &&
                _prFbg[ucFbgId].aucResizeFbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid] != FBM_FB_STATUS_EMPTY)
            {
                _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResizeFbid);
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
            }

            if (_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid != FBM_FB_ID_UNKNOWN &&
                _prFbg[ucFbgId].aucResize2FbStatus[_prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid] != FBM_FB_STATUS_EMPTY)
            {
                _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, _prFbg[ucFbgId].prPicHdr[ucFbId].ucSeamlessResize2Fbid);
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
            }
#endif
        }
        else
        {
            UINT32 u4FbIdx;

            // it is possible. Both Ref is lock by vdp
            // 2005/02/18 William, I found this case when change channel, fbm reset is pending

            if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
            {
                // get locked frame buffer
                for (u4FbIdx = 0; u4FbIdx < FBM_MAX_FB_NS_PER_GROUP; u4FbIdx++)
                {
                    if (_prFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
                    {
                        LOG(3, "{DL}\n");

                        ucFbId = (UCHAR)u4FbIdx;
                        u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;

                        // ask vdp to reset parameter, otherwise, assert at vdp set status to empty
                        _prFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_CLEAR_FRC_PRM;
                    }
                }
            }

            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
        }
    }

    // Auto-Change Empty Status to Decode Status
    // Bug Fixed (20041206)
    _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_DECODE, __func__, __LINE__);
    if (_prFbg[ucFbgId].ucFbDecode != FBM_FB_ID_UNKNOWN)
    {
        LOG(0,"ucFbgId(%d) ucFbDecode(%d)\n",ucFbgId,_prFbg[ucFbgId].ucFbDecode);
    }
    ASSERT_FBM(_prFbg[ucFbgId].ucFbDecode == FBM_FB_ID_UNKNOWN);
    if (ucFbId < FBM_MAX_FB_NS_PER_GROUP)
    {
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DECODE;
        _prFbg[ucFbgId].ucFbDecode = ucFbId;
        _FbmResetPicHdrFields(ucFbgId, ucFbId);
    }
    else
    {
        ucFbId = FBM_FB_ID_UNKNOWN;
        LOG(1, "[Warning] Get Empty Ref Fail (%d, %d)\n", ucFbgId, ucFbId);
//        ASSERT_FBM(0);
    }

    // [LOG] FBM get empty Ref FB
    SYSLOG(FBM_PREFIX + 10 + ucFbgId, ucFbId, _prFbg[ucFbgId].rEmptyQ.ucCount, 0);

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}


//-------------------------------------------------------------------------
/** FBM_CanGetEmptyRefFrameBuffer
 *  Check empty reference frame buffer
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer number.
 */
//-------------------------------------------------------------------------
UCHAR FBM_CanGetEmptyRefFrameBuffer(UCHAR ucFbgId)
{
    UCHAR rValue;

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

    FBM_MUTEX_LOCK(ucFbgId);

    rValue = (UCHAR) _prFbg[ucFbgId].hEmptyQSemaphore.i4Count;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return rValue;
}


//-------------------------------------------------------------------------
/** FBM_CanGetEmptyBFrameBuffer
 *  Check empty B frame buffer
 *  @param  ucFbgId   FBG index.
 *  @return frame buffer number.
 */
//-------------------------------------------------------------------------
UCHAR FBM_CanGetEmptyBFrameBuffer(UCHAR ucFbgId)
{
    UCHAR rValue;

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

    FBM_MUTEX_LOCK(ucFbgId);

    rValue = (UCHAR) _prFbg[ucFbgId].hEmptyBQSemaphore.i4Count;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return rValue;
}


//-------------------------------------------------------------------------
/** FBM_GetDbkEmptyRefFrameBuffer
 *  Get empty Ref frame buffer for DBK
 *  @param  ucFbgId   FBG index.
 *  @param  u4Delay   time to wait.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------

UCHAR FBM_GetDbkEmptyRefFrameBuffer(UCHAR ucFbgId, UINT32 u4Delay)
{

#ifdef CC_MT5351_SLT
    HAL_TIME_T rStart;
    HAL_TIME_T rStop;
    HAL_TIME_T rDelta;
#endif

    UCHAR ucFbId;

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

#ifdef CC_MT5351_SLT
    HAL_GetTime(&rStart);
#endif

    FBM_MUTEX_LOCK(ucFbgId);

    FBM_GetEmptyDelayTime(ucFbgId, &u4Delay);

    // We should not change status at NOT READY mode
    if (_prFbg[ucFbgId].u4FbgFlag & (FBM_FLAG_NOT_READY | FBM_FLAG_RESET | FBM_FLAG_CLEAR_FRC_PRM))
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    ucFbId = FBM_FB_ID_UNKNOWN;
    // wait semaphore (B & Empty)
    if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyBQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
    {
        // wait semaphore success

        // wait semaphore (Empty)
        if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_NOWAIT, 0) != OSR_OK)
        {
            if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
            {
                // reset, handle abnormal case

                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            else
            {
                ASSERT_FBM(0);
            }
        }

        ucFbId = _FbmGetBFrameBufferFromEmptyQ(ucFbgId);

        if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
        {
            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                LOG(1, "[Warning] Get Empty B Fail (%d, %d)\n", ucFbgId, ucFbId);

                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
        }
        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
        {
            LOG(0,"ucFbgId %d ucFbId %d aucFbStatus(%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
    }
    else
    {
        // wait semaphore fail

        ASSERT_FBM(_prFbg[ucFbgId].hEmptyBQSemaphore.i4Count == 0);

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

            LOG(3,"{DQ}");

            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"ucFbId %d\n",ucFbId);
                ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_DISPLAYQ)
            {
                LOG(0,"ucFbgId %d ucFbId %d aucFbStatus %d\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
        }
        else
        {
            UINT32 u4FbIdx;

            // it is possible. Both Ref is lock by vdp
            // 2005/02/18 William, I found this case when change channel, fbm reset is pending

            if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
            {
                // get locked frame buffer
                for (u4FbIdx = 0; u4FbIdx < FBM_MAX_FB_NS_PER_GROUP; u4FbIdx++)
                {
                    if (_prFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
                    {
                        LOG(3, "{DL}\n");

                        ucFbId = (UCHAR)u4FbIdx;
                        u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;

                        // ask vdp to reset parameter, otherwise, assert at vdp set status to empty
                        _prFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_CLEAR_FRC_PRM;
                    }
                }
            }

            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
        }
    }

    if (VERIFY_FB(ucFbgId, ucFbId))
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    // Auto-Change Empty Status to Decode Status
    // Bug Fixed (20041206)
    _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_DECODE, __func__, __LINE__);
    _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DECODE;
    _FbmResetPicHdrFields(ucFbgId, ucFbId);

    // [LOG] FBM get empty B FB
    SYSLOG(FBM_PREFIX + 20 + ucFbgId, ucFbId, _prFbg[ucFbgId].rEmptyQ.ucCount, 0);

    FBM_MUTEX_UNLOCK(ucFbgId);

#ifdef CC_MT5351_SLT
    HAL_GetTime(&rStop);

    HAL_GetDeltaTime(&rDelta, &rStart, &rStop);

    if (rDelta.u4Micros > 100000)
    {
        LOG(1, "GetBTime %u.%6u\n", rDelta.u4Seconds, rDelta.u4Micros);
    }
#endif

    return ucFbId;
}


//-------------------------------------------------------------------------
/** FBM_UpdateReferenceList
 *  Update Reference FB List. H264 ONLY.
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId   FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------

void FBM_UpdateReferenceList(UCHAR ucFbgId, UCHAR ucFbId, BOOL fgReference)
{
    if (VERIFY_FBG(ucFbgId) || VERIFY_FB(ucFbgId, ucFbId))
    {
        return;
    }

    if ((_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_H264) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_H265) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_AVS) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_RAW) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_JPEG)&&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_VP6) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_VP8) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_VP9) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_AVS2) &&
        (_prFbg[ucFbgId].u4VDecFmt != FBM_VDEC_AV1))
    {
        return;
    }
    if (fgReference && (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY))
    {
        //Empty status only can be set reference(0), or
        //FBM_UpdateReferenceList(1) -> FBM_UpdateReferenceList(0)
        //will make this FB put into empty Q twice.
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].afgRefList[ucFbId] && (!fgReference))
    {
        if (_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY)
        {
            if (0)//_prFbg[ucFbgId].fgCreateFromInst)
            {
                ASSERT_FBM(0);
            }
            else
            {
                //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
                _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbId);

                _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_EMPTY, __func__, __LINE__);

            }
        }
    }
    _prFbg[ucFbgId].afgRefList[ucFbId] = fgReference;

    FBM_MUTEX_UNLOCK(ucFbgId);

}


#if 1
UCHAR FBM_GetDbkSmallBFrameBuffer(UCHAR ucFbgId)
{
    UCHAR ucFbId;

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

    ucFbId = _prFbg[ucFbgId].ucFbNs;

    return ucFbId;
}
#endif


#if 1
void FBM_SetFrameBufferFtrCnt(UCHAR ucFbgId, UCHAR ucFbId, UINT32 u4DbkOfStCnt, UINT32 u4Dbk4pCnt)
{
    if ((VERIFY_FBG(ucFbgId)) || (VERIFY_FB(ucFbgId, ucFbId)))
    {
        return;
    }

    _prFbg[ucFbgId].au4DbkOfstCnt[ucFbId] = u4DbkOfStCnt;
    _prFbg[ucFbgId].au4Dbk4pCnt[ucFbId] = u4Dbk4pCnt;

}


void FBM_GetFrameBufferFtrCnt(UCHAR ucFbgId, UCHAR ucFbId, UINT32 *pu4DbkOfStCnt, UINT32 *pu4Dbk4pCnt)
{
    if ((pu4DbkOfStCnt == NULL) || (pu4Dbk4pCnt == NULL))
    {
        return;
    }

    *pu4DbkOfStCnt = 0;
    *pu4Dbk4pCnt = 0;

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

    *pu4DbkOfStCnt = _prFbg[ucFbgId].au4DbkOfstCnt[ucFbId];
    *pu4Dbk4pCnt = _prFbg[ucFbgId].au4Dbk4pCnt[ucFbId];
}
#endif

//-------------------------------------------------------------------------
/** FBM_SetFrameBufferGlobalFlag
 *  Set FBG global flag
 *  @param  ucFbgId   FBG index.
 *  @param  ucFlag   flag.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_SetFrameBufferGlobalFlag(UCHAR ucFbgId, UINT8 ucFlag)
{
    UNUSED(ucFbgId);
    _ucFbmGlobalFlag |= ucFlag;
}


//-------------------------------------------------------------------------
/** FBM_ChkFrameBufferGlobalFlagIsr
 *  Check FBG global flag
 *  @param  ucFbgId   FBG index.
 *  @param  ucFlag   flag.
 *  @return 1/0 for valid/invalid.
 */
//-------------------------------------------------------------------------
UCHAR FBM_ChkFrameBufferGlobalFlagIsr(UCHAR ucFbgId, UINT8 ucFlag)
{
    UCHAR ucChk;

    UNUSED(ucFbgId);
    if (_ucFbmGlobalFlag & ucFlag)
    {
        ucChk = 1;
    }
    else
    {
        ucChk = 0;
    }

    return ucChk;
}

//-------------------------------------------------------------------------
/** FBM_ClrFrameBufferGlobalFlag
 *  Clear FBG global flag
 *  @param  ucFbgId   FBG index.
 *  @param  ucFlag   flag.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_ClrFrameBufferGlobalFlag(UCHAR ucFbgId, UINT8 ucFlag)
{
    UNUSED(ucFbgId);
    _ucFbmGlobalFlag &= ~ucFlag;
}

#ifdef FBM_FB_LOG
void FBM_FlushFbLog(UINT8 ucFbId, UINT8 u4FbStatus)
{
    _FbmFbLog(0xFF,0xFC, u4FbStatus, __func__, __LINE__);
}

#endif


//-------------------------------------------------------------------------
/** FBM_GetLatestEmptyFrameBuffer
 *  Get LATEST empty frame for MM STEP BACKWARD application
 *  @param  ucFbgId   FBG index.
 *  @param  u4Delay   time to wait.
 *  @return frame buffer index.
 */
//-------------------------------------------------------------------------
UCHAR FBM_GetLatestEmptyFrameBuffer(UCHAR ucFbgId, UINT32 u4Delay)
{
    UCHAR ucFbId;

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

    FBM_MUTEX_LOCK(ucFbgId);
    if (_prFbg[ucFbgId].ucPlayMode != FBM_FBG_MM_MODE)
    {
        LOG(0,"ucFbgId %d ucPlayMode %d\n",ucFbgId,_prFbg[ucFbgId].ucPlayMode);
    }

    ASSERT_FBM(_prFbg[ucFbgId].ucPlayMode == FBM_FBG_MM_MODE);

    if (FBM_ChkFrameBufferFlagIsr(ucFbgId, FBM_FLAG_FB_NO_TIMEOUT))
    {
        u4Delay = 0xfffff;
    }
    if (FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        u4Delay = 0;
    }

    // We should not change status at NOT READY mode
    if (_prFbg[ucFbgId].u4FbgFlag & (FBM_FLAG_NOT_READY | FBM_FLAG_RESET | FBM_FLAG_CLEAR_FRC_PRM))
    {
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    ucFbId = FBM_FB_ID_UNKNOWN;
    if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
    {
        // wait semaphore (Empty)
        if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
        {
            // wait semaphore success
            ucFbId = _FbmGetLatestEmptyFrameBufferFromEmptyQ(ucFbgId);

            // Work around counting semaphore issue
            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }

            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
                    ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }

            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
        }
        else
        {
            // wait semaphore fail

            ASSERT_FBM(_prFbg[ucFbgId].hEmptyQSemaphore.i4Count == 0);

            if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
            {
                // get frame buffer from display Q

                ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
                _prFbg[ucFbgId].rDisplayQ.ucReadIdx = (_prFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;
                _prFbg[ucFbgId].rDisplayQ.ucCount--;

                LOG(6, "[LINE%d]Get FB(%d-%d) From DispQ Cnt%d.\n", __LINE__, ucFbgId, ucFbId, _prFbg[ucFbgId].rDisplayQ.ucCount);

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

                }
                ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);
            }
            else
            {
                UCHAR u4FbIdx;

                // it is possible. Both Ref is lock by vdp
                // 2005/02/18 William, I found this case when change channel, fbm reset is pending

                if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_RESET)
                {
                    // get locked frame buffer
                    for (u4FbIdx = 0; u4FbIdx < FBM_MAX_FB_NS_PER_GROUP; u4FbIdx++)
                    {
                        if (_prFbg[ucFbgId].aucFbStatus[u4FbIdx] == FBM_FB_STATUS_LOCK)
                        {
                            LOG(3, "{DL}\n");

                            ucFbId = u4FbIdx;
                            u4FbIdx = FBM_MAX_FB_NS_PER_GROUP;

                            // ask vdp to reset parameter, otherwise, assert at vdp set status to empty
                            _prFbg[ucFbgId].u4FbgFlag |= FBM_FLAG_CLEAR_FRC_PRM;
                        }
                    }
                }

                if (ucFbId == FBM_FB_ID_UNKNOWN)
                {
                    FBM_MUTEX_UNLOCK(ucFbgId);
                    return FBM_FB_ID_UNKNOWN;
                }
            }
        }
    }
    else
    {
        // wait semaphore (Empty)
        if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
        {
            // wait semaphore success

            ucFbId = _FbmGetLatestEmptyFrameBufferFromEmptyQ(ucFbgId);

            // Work around counting semaphore issue
            if (ucFbId == FBM_FB_ID_UNKNOWN)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }

            if ( ((ucFbId == _prFbg[ucFbgId].ucFbFRef) && (_prFbg[ucFbgId].ucFbFRefValid))
                 || ((ucFbId == _prFbg[ucFbgId].ucFbBRef) && (_prFbg[ucFbgId].ucFbBRefValid))
               )
            {
                // we get an empty reference frame buffer
            }
            else
            {
                //Get empty B
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyBQSemaphore) == OSR_OK);
            }

            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                FBM_MUTEX_UNLOCK(ucFbgId);
                return FBM_FB_ID_UNKNOWN;
            }
            if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
                    ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }

            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
        }
        else
        {
            // wait semaphore fail

            ASSERT_FBM(_prFbg[ucFbgId].hEmptyQSemaphore.i4Count == 0);

            if (_prFbg[ucFbgId].rDisplayQ.ucCount > 0)
            {
                // get frame buffer from display Q

                ucFbId = _prFbg[ucFbgId].rDisplayQ.aucQueue[_prFbg[ucFbgId].rDisplayQ.ucReadIdx];
                _prFbg[ucFbgId].rDisplayQ.ucReadIdx = (_prFbg[ucFbgId].rDisplayQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;
                _prFbg[ucFbgId].rDisplayQ.ucCount--;

                LOG(6, "[LINE%d]Get FB(%d-%d) From DispQ Cnt%d.\n", __LINE__, ucFbgId, ucFbId, _prFbg[ucFbgId].rDisplayQ.ucCount);

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

    if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
    {
        if (IS_REFERENCE_FB(ucFbgId, ucFbId) ||
            (FBM_FB_ID_UNKNOWN == _prFbg[ucFbgId].ucFbFRef) ||
            (FBM_FB_ID_UNKNOWN == _prFbg[ucFbgId].ucFbBRef))
        {
            // we get an empty reference frame buffer
            if (ucFbId != FBM_FB_ID_UNKNOWN)
            {
                _prFbg[ucFbgId].ucLastDecodeReference = 1;
            }

            if ((ucFbId != FBM_FB_ID_UNKNOWN) &&
                (ucFbId != _prFbg[ucFbgId].ucFbBRef))
            {
                _prFbg[ucFbgId].ucFbFRef = _prFbg[ucFbgId].ucFbBRef;
                _prFbg[ucFbgId].ucFbBRef = ucFbId;

                _prFbg[ucFbgId].ucFbFRefValid = _prFbg[ucFbgId].ucFbBRefValid;
                _prFbg[ucFbgId].ucFbBRefValid = 0;
            }
        }
        else
        {
            // we get an empty B fram buffer
            if (ucFbId != FBM_FB_ID_UNKNOWN)
            {
                _prFbg[ucFbgId].ucLastDecodeReference = 0;
            }
        }

    }



    // Auto-Change Empty Status to Decode Status
    // Bug Fixed (20041206)
    // There might be FB in decode state in STEP BACKWARD case
    //ASSERT_FBM(_prFbg[ucFbgId].ucFbDecode == FBM_FB_ID_UNKNOWN);
    if (ucFbId < FBM_MAX_FB_NS_PER_GROUP)
    {
        _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_DECODE, __func__, __LINE__);
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DECODE;
        // ilii
        //_prFbg[ucFbgId].ucFbDecode = ucFbId;
        //_FbmResetPicHdrFields(ucFbgId, ucFbId);
    }
    else
    {
        ucFbId = FBM_FB_ID_UNKNOWN;
        LOG(1, "[Warning] Get Latest Empty Fail (%d, %d)\n", ucFbgId, ucFbId);
//        ASSERT_FBM(0);
    }

    // [LOG] FBM get empty Ref FB
    SYSLOG(FBM_PREFIX + 10 + ucFbgId, ucFbId, _prFbg[ucFbgId].rEmptyQ.ucCount, 0);

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}

//-------------------------------------------------------------------------
/** FBM_SetSeqChgFbId
 *  Setup the FB id to which the sequence change will be applied
 *  @param  ucFbgId   FBG index.
 *  @param  ucFbId    FB index.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
VOID FBM_SetSeqChgFbId(UCHAR ucFbgId, UCHAR ucFbId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        LOG(0,"Invalid fbgid @ %s\n",__FUNCTION__);
        return;
    }
    _prFbg[ucFbgId].ucSeqChgFbId = ucFbId;

    LOG(2,"FBM_SetSeqChgFbId ucFbgId  %d ucFbId %d \n",ucFbgId,ucFbId);
}

UINT32 FBM_ConfigWorkingBuffer(UCHAR ucFbgId, UPTR u4BufAddr)
{
    UCHAR ucSrcFbgId = FBM_FBG_ID_UNKNOWN;
    UCHAR u4FbgIdx, u4FbId;

    // init Q
    _prFbg[ucFbgId].rEmptyQ.ucCount = 0;
    _prFbg[ucFbgId].rEmptyQ.ucReadIdx = 0;

    for (u4FbgIdx = 0; u4FbgIdx < FBG_MAX_NS; u4FbgIdx++)
    {
        if (_prFbg[u4FbgIdx].ucFbgId != FBM_FBG_ID_UNKNOWN)
        {
            for (u4FbId = _prFbg[ucFbgId].ucFbNsBase; u4FbId < _prFbg[u4FbgIdx].ucFbNs; u4FbId++)
            {
                if (_prFbg[u4FbgIdx].au4AddrY[u4FbId] == u4BufAddr)
                {
                    ucSrcFbgId = u4FbgIdx;
                    break;
                }
            }
        }

        if (ucSrcFbgId != FBM_FBG_ID_UNKNOWN)
        {
            break;
        }
    }

    if (ucSrcFbgId == FBM_FBG_ID_UNKNOWN)
    {
        LOG(0, "Error: could not find proper FBG from FBM instance!\n");
        return (UINT32)-1;
    }
    if (_prFbg[ucFbgId].ucFbNs != _prFbg[ucSrcFbgId].ucFbNs)
    {
        LOG(0,"ucFbgId(%d) ucSrcFbgId(%d) FbNs(%d) SrcFbNs(%d)\n",ucFbgId,ucSrcFbgId,_prFbg[ucFbgId].ucFbNs,_prFbg[ucSrcFbgId].ucFbNs);
    }
    ASSERT_FBM(_prFbg[ucFbgId].ucFbNs == _prFbg[ucSrcFbgId].ucFbNs);
    _prFbg[ucFbgId].ucFbNs = _prFbg[ucSrcFbgId].ucFbNs;
    _prFbg[ucFbgId].ucFbNsBase = _prFbg[ucSrcFbgId].ucFbNsBase;
    for (u4FbId = 0; u4FbId < _prFbg[ucSrcFbgId].ucFbNs; u4FbId++)
    {
        _prFbg[ucFbgId].au4AddrY[u4FbId] = _prFbg[ucSrcFbgId].au4AddrY[u4FbId];
        _prFbg[ucFbgId].au4AddrC[u4FbId] = _prFbg[ucSrcFbgId].au4AddrC[u4FbId];
    }

    _prFbg[ucFbgId].u4FbWidth = _prFbg[ucSrcFbgId].u4FbWidth;
    _prFbg[ucFbgId].u4FbHeight = _prFbg[ucSrcFbgId].u4FbHeight;
    _prFbg[ucFbgId].ucFbgCm = _prFbg[ucSrcFbgId].ucFbgCm;
    _prFbg[ucFbgId].ucMvBufNs = _prFbg[ucSrcFbgId].ucMvBufNs;

    _prFbg[ucFbgId].u4FbMemoryPoolSize = _prFbg[ucSrcFbgId].u4FbMemoryPoolSize;
    _prFbg[ucFbgId].u4FbMemoryPool = _prFbg[ucSrcFbgId].u4FbMemoryPool;

    // init working buf
    if (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_MPEG2)
    {
        _prFbg[ucFbgId].au4AddrMv[0] = _prFbg[ucSrcFbgId].au4AddrMv[0];

        if ((_prFbg[ucFbgId].ucFbNs - _prFbg[ucFbgId].ucFbNsBase >= FBM_DBK_FB_NS) && (_prFbg[ucFbgId].ucFbgType != FBM_FBG_TYPE_1080HD_RR))
        {
            _prFbg[ucFbgId].au4AddrY[_prFbg[ucFbgId].ucFbNs] = _prFbg[ucSrcFbgId].au4AddrY[_prFbg[ucFbgId].ucFbNs];
            _prFbg[ucFbgId].au4AddrC[_prFbg[ucFbgId].ucFbNs] = _prFbg[ucSrcFbgId].au4AddrC[_prFbg[ucFbgId].ucFbNs];
        }
    }
    else if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
             (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
             (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
    {
        for (u4FbId = 0; u4FbId < _prFbg[ucFbgId].ucMvBufNs && u4FbId < (FBM_MAX_FB_NS_PER_GROUP-1) ; u4FbId++)
        {
            _prFbg[ucFbgId].au4AddrMv[u4FbId] = _prFbg[ucSrcFbgId].au4AddrMv[u4FbId];
        }
    }
    else if (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RV)
    {
        _prFbg[ucFbgId].u4ExtraYBuffer = _prFbg[ucSrcFbgId].u4ExtraYBuffer;
        _prFbg[ucFbgId].u4ExtraCBuffer = _prFbg[ucSrcFbgId].u4ExtraCBuffer;
        _prFbg[ucFbgId].au4AddrMv[0] = _prFbg[ucSrcFbgId].au4AddrMv[0];
    }
    else
    {
        _prFbg[ucFbgId].au4AddrMv[0] = _prFbg[ucSrcFbgId].au4AddrMv[0];
    }

    _prFbg[ucFbgId].u4WorkBufSize = _prFbg[ucSrcFbgId].u4WorkBufSize;

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

    {
        // create semaphore, Empty Q
        VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);
    }
    else
    {
        // create semaphore, Empty Q
        VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);

        // create semaphore, Empty BQ
        VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyBQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);

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

    }

    x_memset(_prFbg[ucFbgId].afgIsOwner, 0, sizeof(_prFbg[ucFbgId].afgIsOwner));

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

    // put all frame buffer into empty queue
#if 0
    for (u4FbId = 0; u4FbId < _prFbg[ucFbgId].ucFbNs; u4FbId++)
    {
        _FBM_PutFrameBufferToEmptyQ(ucFbgId, (UCHAR)(u4FbId));
    }
#endif

    ASSERT_FBM(_prFbg[ucFbgId].hEmptyQSemaphore.hMutex == _prFbg[ucFbgId].hMutex);
//    ASSERT_FBM(_prFbg[ucFbgId].hEmptyRQSemaphore.hMutex == _prFbg[ucFbgId].hMutex);
    ASSERT_FBM(_prFbg[ucFbgId].hEmptyBQSemaphore.hMutex == _prFbg[ucFbgId].hMutex);

    return 0;
}

VOID FBM_GetFbByAddr(UPTR u4Addr, UCHAR *pucFbgId, UCHAR *pucFbId)
{
    UCHAR ucFbgId;
    UCHAR ucFbId;

    if (pucFbgId == NULL || pucFbId == NULL)
    {
        return;
    }

    *pucFbgId = FBM_FBG_ID_UNKNOWN;
    *pucFbId = FBM_FB_ID_UNKNOWN;

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

        for (ucFbId=_prFbg[ucFbgId].ucFbNsBase; ucFbId<_prFbg[ucFbgId].ucFbNs; ucFbId++)
        {
            if (_prFbg[ucFbgId].au4AddrY[ucFbId] == u4Addr)
            {
                *pucFbgId = ucFbgId;
                *pucFbId = ucFbId;
                return;
            }
        }
    }
}

UCHAR _FBM_GetFbIdByAddr(UCHAR ucFbgId, UPTR u4Addr)
{
    UCHAR i;
    if (VERIFY_FBG(ucFbgId))
    {
        return FBM_FB_ID_UNKNOWN;
    }

    for (i=_prFbg[ucFbgId].ucFbNsBase; i<_prFbg[ucFbgId].ucFbNs; i++)
    {
        if (_prFbg[ucFbgId].au4AddrY[i] == u4Addr)
        {
            return i;
        }
    }
    return FBM_FB_ID_UNKNOWN;
}

BOOL FBM_FlushEmptyBufToDispQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

    if ((ucFbgId == FBM_FBG_ID_UNKNOWN) || (_prFbg[ucFbgId].hMutex == (HANDLE_T)(UPTR)NULL))
    {
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);
    while (_prFbg[ucFbgId].rEmptyQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[_prFbg[ucFbgId].rEmptyQ.ucReadIdx];

        if (++(_prFbg[ucFbgId].rEmptyQ.ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
        {
            _prFbg[ucFbgId].rEmptyQ.ucReadIdx = 0;
        }
        _prFbg[ucFbgId].rEmptyQ.ucCount--;

        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
        }
        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);

        VERIFY_FBID(ucFbId,FALSE);

        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DISPLAYQ;
        _FbmFbLog(ucFbgId,ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId], __func__, __LINE__);
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgNotDisplay = TRUE;
        _FbmPutFrameBufferToDispQ(ucFbgId, ucFbId);

        LOG(3, "FBM_FlushEmptyBufToDispQ Empty -> DispQ : (%d)\n", ucFbId);
    }
    VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);
    VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyBQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);

    FBM_MUTEX_UNLOCK(ucFbgId);

    LOG(0, "FBM_FlushEmptyBufToDispQ EmptyQ Cnt : (%d)\n", _prFbg[ucFbgId].rEmptyQ.ucCount);

    return TRUE;
}

BOOL FBM_ReleaseFBFlush(UCHAR ucFbgId)
{
    UCHAR i;
    UCHAR ucFbId;
    FBM_MUTEX_LOCK(ucFbgId);
    LOG(3, "FBM_ReleaseFBFlush() Enter.\n");
    while (_prFbg[ucFbgId].rEmptyQ.ucCount > 0)
    {
        ucFbId = _prFbg[ucFbgId].rEmptyQ.aucQueue[_prFbg[ucFbgId].rEmptyQ.ucReadIdx];

        if (++(_prFbg[ucFbgId].rEmptyQ.ucReadIdx) >= FBM_MAX_FB_NS_PER_GROUP)
        {
            _prFbg[ucFbgId].rEmptyQ.ucReadIdx = 0;
        }
        _prFbg[ucFbgId].rEmptyQ.ucCount--;

        ASSERT_FBM(ucFbId != FBM_FB_ID_UNKNOWN);

#if 1
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_RECYCLE;
#else
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DISPLAYQ;
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgNotDisplay = TRUE;
        _FbmPutFrameBufferToDispQ(ucFbgId, ucFbId);
#endif
        _FbmFbLog(ucFbgId,ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId], __func__, __LINE__);
    }
    VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);
    VERIFY(_FBM_csema_reset(&_prFbg[ucFbgId].hEmptyBQSemaphore, _prFbg[ucFbgId].hMutex, 0) == OSR_OK);

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

    for (i=_prFbg[ucFbgId].ucFbNsBase; i < _prFbg[ucFbgId].ucFbNs; i++)
    {
        _prFbg[ucFbgId].afgRefList[i] = FALSE;
    }

    LOG(3, "FBM_ReleaseFBFlush() Leave.\n");
    FBM_MUTEX_UNLOCK(ucFbgId);
    return TRUE;
}

BOOL FBM_InsertFB(UCHAR ucFbgId, UPTR u4Addr)
{
    UCHAR ucFbId;
    UCHAR ucCount;
    if (VERIFY_FBG(ucFbgId) || u4Addr == 0)
    {
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].au4AddrY[0] == 0)
    {
        FBM_ConfigWorkingBuffer(ucFbgId, u4Addr);
    }

    ucFbId = _FBM_GetFbIdByAddr(ucFbgId, u4Addr);

    if ((ucFbId == FBM_FB_ID_UNKNOWN) || (ucFbId >= FBM_MAX_FB_NS_PER_GROUP))
    {
        LOG(0, "Can't find target FB by the given addr!\n");
        ASSERT_FBM(0);
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FALSE;
    }

    ASSERT_FBM(_prFbg[ucFbgId].fgCreateFromInst == TRUE);

    if (_fgCheckFBStatus)
    {
        if (!(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_UNKNOWN ||
              _prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK ||
              _prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_RECYCLE))
        {
            LOG(0, "Insert fbid %d status NG %d !\n", ucFbId, _prFbg[ucFbgId].aucFbStatus[ucFbId]);
            if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_UNKNOWN) &&
                (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK) &&
                (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_RECYCLE))
            {
                LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
            }
            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_UNKNOWN ||
                       _prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK ||
                       _prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_RECYCLE);
        }
        ASSERT_FBM(_prFbg[ucFbgId].afgIsOwner[ucFbId] == FALSE);
    }

    ucCount = 1;
    if(FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_DEBLOCKING))
    {
        ucCount = 2;
    }
    if (_prFbg[ucFbgId].rEmptyQ.ucCount >= ucCount)
    {
        _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_DISPLAYQ;
        _prFbg[ucFbgId].prPicHdr[ucFbId].fgNotDisplay= TRUE;
        _prFbg[ucFbgId].afgIsOwner[ucFbId] = TRUE;
        _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_DISPLAYQ, __func__, __LINE__);
        _FbmPutFrameBufferToDispQ(ucFbgId, ucFbId);
        FBM_MUTEX_UNLOCK(ucFbgId);
        return TRUE;
    }

    _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_EMPTY, __func__, __LINE__);
    _prFbg[ucFbgId].aucFbStatus[ucFbId] = FBM_FB_STATUS_EMPTY;
    _prFbg[ucFbgId].afgIsOwner[ucFbId] = TRUE;

    _FBM_PutFrameBufferToEmptyQ(ucFbgId, ucFbId);

    if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8) ||
        (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
    {
        //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
    }
    else
    {
        UCHAR ucRefCount = 0;

        if (_prFbg[ucFbgId].ucFbFRef != FBM_FB_ID_UNKNOWN)
        {
            ucRefCount++;
        }
        if (_prFbg[ucFbgId].ucFbBRef != FBM_FB_ID_UNKNOWN)
        {
            ucRefCount++;
        }

        //if (_prFbg[ucFbgId].hEmptyQSemaphore.i4Count + ucRefCount >= 2)
        {
            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyBQSemaphore) == OSR_OK);
        }
        //VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyQSemaphore) == OSR_OK);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
    return TRUE;
}

UCHAR FBM_GetFreeFB(UCHAR ucFbgId)
{
    UCHAR i, ucTargetId = FBM_FB_ID_UNKNOWN;
    if (VERIFY_FBG(ucFbgId))
    {
        return FBM_FB_ID_UNKNOWN;
    }

    ASSERT_FBM(_prFbg[ucFbgId].fgCreateFromInst == TRUE);
    FBM_MUTEX_LOCK(ucFbgId);

    for (i=_prFbg[ucFbgId].ucFbNsBase; (i < _prFbg[ucFbgId].ucFbNs) && (i < FBM_MAX_FB_NS_PER_GROUP); i++)
    {
        if (_prFbg[ucFbgId].afgIsOwner[i] == FALSE)
        {
            continue;
        }

        if (_prFbg[ucFbgId].aucFbStatus[i] == FBM_FB_STATUS_RECYCLE)
        {
            ucTargetId = i;
            break;
        }

        if (_prFbg[ucFbgId].aucFbStatus[i] == FBM_FB_STATUS_LOCK)
        {
            if ((_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H264) ||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_H265) ||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS) ||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_RAW) ||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_JPEG)||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP6) ||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_VP8) ||
                (_prFbg[ucFbgId].u4VDecFmt == FBM_VDEC_AVS2))
            {
                if (!_prFbg[ucFbgId].afgRefList[i])
                {
                    ucTargetId = i;
                    break;
                }
            }
            else
            {
                if (!IS_REFERENCE_FB(ucFbgId, i))
                {
                    ucTargetId = i;
                    break;
                }
            }
        }
    }

    if (ucTargetId < FBM_MAX_FB_NS_PER_GROUP)
    {
        _prFbg[ucFbgId].afgIsOwner[ucTargetId] = FALSE;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucTargetId;
}


BOOL FBM_GetInsertFBCount(UCHAR ucFbgId, UINT32 *pu4Count)
{
    if (VERIFY_FBG(ucFbgId) || pu4Count == 0)
    {
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);
    *pu4Count = _prFbg[ucFbgId].rEmptyQ.ucCount;
    FBM_MUTEX_UNLOCK(ucFbgId);
    return TRUE;
}
UCHAR FBM_GetResizeFrameBufferNs(UCHAR ucFbgId)
{
    UCHAR ucFbNs;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbNs = _prFbg[ucFbgId].ucSeamlessFbNs;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbNs;
}

VOID FBM_GetResizeFrameBufferSize(UCHAR ucFbgId, UINT32 *pu4Width, UINT32 *pu4Height)
{
    if ((pu4Width == NULL) || (pu4Height == NULL))
    {
        return;
    }

    *pu4Width = (UINT32)0;
    *pu4Height = (UINT32)0;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    *pu4Width = FBM_FBG_1080HD_H;
    *pu4Height = FBM_FBG_1080HD_V;
}

UCHAR FBM_GetResizeFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR ucFbStatus;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucFbStatus = _prFbg[ucFbgId].aucResizeFbStatus[ucFbId];

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbStatus;
}

UCHAR FBM_CheckResizeFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus)
{
    UCHAR ucValid;

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

    FBM_MUTEX_LOCK(ucFbgId);

    ucValid = (ucFbStatus == _prFbg[ucFbgId].aucResizeFbStatus[ucFbId]);

    /*
    // VDP protection
    if (_prFbg[ucFbgId].u4FbgFlag & FBM_FLAG_NOT_READY)
    {
        ucValid = 1;
    }
    */

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucValid;
}


BOOL FBM_SetResizeFrameBufferFlag(UCHAR ucFbgId, UCHAR ucFbId,
                                  UCHAR ucSetType,UINT32 u4Flag)
{
    UCHAR ucSetFbId = 0;
    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }

    if ( ucFbId != FBM_FB_ID_ALL && VERIFY_RESIZE_FB(ucFbgId, ucFbId))
    {
        if (ucFbId != _prFbg[ucFbgId].ucSeamlessFbNs)
        {
            return FALSE;
        }
    }

    if(ucFbId == FBM_FB_ID_ALL && ucSetType == FLAG_SET_TYPE_CHECK)
    {
        return FALSE;
    }
    else if(_prFbg[ucFbgId].ucSeamlessFbNs == 0)
    {
        return FALSE;
    }

    do
    {
        ucSetFbId = ucFbId == FBM_FB_ID_ALL ? ucSetFbId : ucFbId;
        if(ucSetFbId < FBM_MAX_FB_NS_PER_GROUP)
        {
            if(ucSetType == FLAG_SET_TYPE_RESET)
            {
                _prFbg[ucFbgId].u4ResizeBufferFlag[ucSetFbId] = u4Flag;
            }
            else if(ucSetType == FLAG_SET_TYPE_ENABLE)
            {
                _prFbg[ucFbgId].u4ResizeBufferFlag[ucSetFbId] |= u4Flag;
            }
            else if(ucSetType == FLAG_SET_TYPE_DISABLE)
            {
                _prFbg[ucFbgId].u4ResizeBufferFlag[ucSetFbId] &= ~u4Flag;
            }
            else if(ucSetType == FLAG_SET_TYPE_CHECK)
            {
                return (_prFbg[ucFbgId].u4ResizeBufferFlag[ucSetFbId] & u4Flag) ? TRUE : FALSE;
            }

            ucSetFbId ++;
            if(ucFbId != FBM_FB_ID_ALL)
                break;
            else if(ucSetFbId == _prFbg[ucFbgId].ucSeamlessFbNs)
                break;
        }
    }
    while(1);

    return TRUE;
}


BOOL FBM_SetResize2FrameBufferFlag(UCHAR ucFbgId, UCHAR ucFbId,
                                   UCHAR ucSetType,UINT32 u4Flag)
{
    UCHAR ucSetFbId = 0;
    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }
    if ( ucFbId != FBM_FB_ID_ALL && VERIFY_RESIZE_FB(ucFbgId, ucFbId))
    {
        if (ucFbId != _prFbg[ucFbgId].ucSeamless2FbNs)
        {
            return FALSE;
        }
    }

    if(ucFbId == FBM_FB_ID_ALL && ucSetType == FLAG_SET_TYPE_CHECK)
    {
        return FALSE;
    }
    else if(_prFbg[ucFbgId].ucSeamless2FbNs == 0)
    {
        return FALSE;
    }

    do
    {
        ucSetFbId = ucFbId == FBM_FB_ID_ALL ? ucSetFbId : ucFbId;
        if(ucSetFbId < FBM_MAX_FB_NS_PER_GROUP)
        {
            if(ucSetType == FLAG_SET_TYPE_RESET)
            {
                _prFbg[ucFbgId].u4Resize2BufferFlag[ucSetFbId] = u4Flag;
            }
            else if(ucSetType == FLAG_SET_TYPE_ENABLE)
            {
                _prFbg[ucFbgId].u4Resize2BufferFlag[ucSetFbId] |= u4Flag;
            }
            else if(ucSetType == FLAG_SET_TYPE_DISABLE)
            {
                _prFbg[ucFbgId].u4Resize2BufferFlag[ucSetFbId] &= ~u4Flag;
            }
            else if(ucSetType == FLAG_SET_TYPE_CHECK)
            {
                return (_prFbg[ucFbgId].u4ResizeBufferFlag[ucSetFbId] & u4Flag) ? TRUE : FALSE;
            }

            ucSetFbId ++;
            if(ucFbId != FBM_FB_ID_ALL)
                break;
            else if(ucSetFbId == _prFbg[ucFbgId].ucSeamless2FbNs)
                break;
        }
    }
    while(1);

    return TRUE;
}

VOID FBM_GetResizeFrameBufferAddr(UCHAR ucFbgId, UCHAR ucFbId, UPTR *pu4AddrY, UPTR *pu4AddrC)
{
    if ((pu4AddrY == NULL) || (pu4AddrC == NULL))
    {
        return;
    }

    *pu4AddrY = (UPTR)NULL;
    *pu4AddrC = (UPTR)NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if (VERIFY_RESIZE_FB(ucFbgId, ucFbId))
    {
        if (ucFbId != _prFbg[ucFbgId].ucSeamlessFbNs)
        {
            return;
        }
    }

    if (ucFbId>=FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"ucFbId %d\n",ucFbId);
        ASSERT_FBM(ucFbId<FBM_MAX_FB_NS_PER_GROUP);
        return;
    }

    *pu4AddrY = _prFbg[ucFbgId].au4ResizeAddrY[ucFbId];
    *pu4AddrC = _prFbg[ucFbgId].au4ResizeAddrC[ucFbId];
}

VOID FBM_GetResize2FrameBufferAddr(UCHAR ucFbgId, UCHAR ucFbId, UPTR *pu4AddrY, UPTR *pu4AddrC)
{
    if ((pu4AddrY == NULL) || (pu4AddrC == NULL))
    {
        return;
    }

    *pu4AddrY = (UPTR)NULL;
    *pu4AddrC = (UPTR)NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if (VERIFY_RESIZE_FB(ucFbgId, ucFbId))
    {
        if (ucFbId != _prFbg[ucFbgId].ucSeamless2FbNs)
        {
            return;
        }
    }

    if (ucFbId>=FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"ucFbId %d\n",ucFbId);
        ASSERT_FBM(ucFbId<FBM_MAX_FB_NS_PER_GROUP);
        return;
    }

    *pu4AddrY = _prFbg[ucFbgId].au4Resize2AddrY[ucFbId];
    *pu4AddrC = _prFbg[ucFbgId].au4Resize2AddrC[ucFbId];
}

VOID FBM_SetResizeFrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus)
{
    UCHAR ucSrcId = FBM_FB_ID_UNKNOWN;

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

    FBM_MUTEX_LOCK(ucFbgId);

    // [LOG] FBM change FB status
    SYSLOG(FBM_PREFIX + ucFbgId, ucFbId, _prFbg[ucFbgId].aucResizeFbStatus[ucFbId], ucFbStatus);
    _FbmFbLog(ucFbgId,ucFbId, ucFbStatus, __func__, __LINE__);

    // check current resize frame buffer status change
    if (ucFbId == _prFbg[ucFbgId].ucFbResize && ucFbStatus != FBM_FB_STATUS_RESIZE)
    {
        _prFbg[ucFbgId].ucFbResize = FBM_FB_ID_UNKNOWN;
    }

    switch (ucFbStatus)
    {
        case FBM_FB_STATUS_EMPTY:

            if (_prFbg[ucFbgId].aucResizeFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
            {
                _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, ucFbId);
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
            }
            break;

        case FBM_FB_STATUS_RESIZE:

            _prFbg[ucFbgId].ucFbResize = ucFbId;
            break;
        case FBM_FB_STATUS_RESIZE_DONE:

            if (_prFbg[ucFbgId].aucResizeFbStatus[ucFbId] != FBM_FB_STATUS_RESIZE)
            {
                LOG(6, "[Warning] Set ResizeDone to non-Resizing frame (%d, %d)!\n", ucFbId, _prFbg[ucFbgId].aucResizeFbStatus[ucFbId]);
                ucFbStatus = FBM_FB_STATUS_EMPTY;
            }

#ifdef CC_GET_AFTER_RESIZE_DONE
            if (_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId] != FBM_FB_ID_UNKNOWN &&
                _prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]] == FBM_FB_STATUS_DISPLAYQ &&
                _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]].ucSeamlessResizeFbid == ucFbId &&
                _prFbg[ucFbgId].aucResizeTaskId[ucFbId] == _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]].ucSeamlessTaskId)
#else
            if (_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId] != FBM_FB_ID_UNKNOWN &&
                (_prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]] == FBM_FB_STATUS_DISPLAYQ ||
                 _prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]] == FBM_FB_STATUS_LOCK) &&
                _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]].ucSeamlessResizeFbid == ucFbId &&
                _prFbg[ucFbgId].aucResizeTaskId[ucFbId] == _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]].ucSeamlessTaskId)
#endif
            {
                if (ucFbStatus != FBM_FB_STATUS_RESIZE_DONE)
                {
                    LOG(0,"ucFbStatus %d\n",ucFbStatus);
                }
                ASSERT_FBM(ucFbStatus == FBM_FB_STATUS_RESIZE_DONE);
                _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResizeSrcFbId[ucFbId]].fgSeamlessResized = TRUE;
            }
            else
            {
                ucFbStatus = FBM_FB_STATUS_EMPTY;
#if 1
                if (_prFbg[ucFbgId].aucResizeFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
                {
                    _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, ucFbId);
                    VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
                }
#endif
            }

            break;

        default:
            ASSERT_FBM(0);
            break;
    }

    _prFbg[ucFbgId].aucResizeFbStatus[ucFbId] = ucFbStatus;

    ucSrcId = _prFbg[ucFbgId].aucResizeSrcFbId[ucFbId];

    FBM_MUTEX_UNLOCK(ucFbgId);

#if 1
    if ((ucFbStatus == FBM_FB_STATUS_RESIZE_DONE) && !FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        FB_CHG_INFO_T t_fb_info;

        t_fb_info.fgOmxSrc = FALSE;
        t_fb_info.ucFbgId = ucFbgId;
        t_fb_info.ucFbid  = ucSrcId;

        if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_FB_READY_IND]))
        {
            ((FBM_FB_READY_IND_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND])(&t_fb_info);
        }
        else
        {
            ASSERT_FBM(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND] == 0);
        }
    }
#endif
}

VOID FBM_SetResize2FrameBufferStatus(UCHAR ucFbgId, UCHAR ucFbId, UCHAR ucFbStatus)
{
    UCHAR ucSrcId = FBM_FB_ID_UNKNOWN;

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

    FBM_MUTEX_LOCK(ucFbgId);

    // [LOG] FBM change FB status
    SYSLOG(FBM_PREFIX + ucFbgId, ucFbId, _prFbg[ucFbgId].aucResize2FbStatus[ucFbId], ucFbStatus);
    _FbmFbLog(ucFbgId,ucFbId, ucFbStatus, __func__, __LINE__);

    // check current resize frame buffer status change
    if (ucFbId == _prFbg[ucFbgId].ucFbResize2 && ucFbStatus != FBM_FB_STATUS_RESIZE)
    {
        _prFbg[ucFbgId].ucFbResize2 = FBM_FB_ID_UNKNOWN;
    }

    switch (ucFbStatus)
    {
        case FBM_FB_STATUS_EMPTY:
            if (_prFbg[ucFbgId].aucResize2FbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
            {
                _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, ucFbId);
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
            }
            break;

        case FBM_FB_STATUS_RESIZE:

            _prFbg[ucFbgId].ucFbResize2 = ucFbId;

            LOG(1,"FBM_FB_STATUS_RESIZE2 ucFbgId %d ucFbResize %d\n",ucFbgId,ucFbId);

            break;
        case FBM_FB_STATUS_RESIZE_DONE:

            if (_prFbg[ucFbgId].aucResize2FbStatus[ucFbId] != FBM_FB_STATUS_RESIZE)
            {
                LOG(6, "[Warning] Set ResizeDone to non-Resizing frame (%d, %d)!\n", ucFbId, _prFbg[ucFbgId].aucResize2FbStatus[ucFbId]);
                ucFbStatus = FBM_FB_STATUS_EMPTY;
            }

#ifdef CC_GET_AFTER_RESIZE_DONE
            if (_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId] != FBM_FB_ID_UNKNOWN &&
                _prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]] == FBM_FB_STATUS_DISPLAYQ &&
                _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]].ucSeamlessResize2Fbid == ucFbId &&
                _prFbg[ucFbgId].aucResize2TaskId[ucFbId] == _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]].ucSeamlessTaskId)
#else
            if (_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId] != FBM_FB_ID_UNKNOWN &&
                (_prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]] == FBM_FB_STATUS_DISPLAYQ ||
                 _prFbg[ucFbgId].aucFbStatus[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]] == FBM_FB_STATUS_LOCK) &&
                _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]].ucSeamlessResize2Fbid == ucFbId &&
                _prFbg[ucFbgId].aucResize2TaskId[ucFbId] == _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]].ucSeamlessTaskId)
#endif
            {
                if (ucFbStatus != FBM_FB_STATUS_RESIZE_DONE)
                {
                    LOG(0,"ucFbStatus %d\n",ucFbStatus);
                }
                ASSERT_FBM(ucFbStatus == FBM_FB_STATUS_RESIZE_DONE);
                _prFbg[ucFbgId].prPicHdr[_prFbg[ucFbgId].aucResize2SrcFbId[ucFbId]].fgSeamlessResized = TRUE;
            }
            else
            {
                ucFbStatus = FBM_FB_STATUS_EMPTY;
#if 1
                if (_prFbg[ucFbgId].aucResize2FbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
                {
                    _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, ucFbId);
                    VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
                }
#endif
            }

            break;

        default:
            ASSERT_FBM(0);
            break;
    }

    _prFbg[ucFbgId].aucResize2FbStatus[ucFbId] = ucFbStatus;

    ucSrcId = _prFbg[ucFbgId].aucResize2SrcFbId[ucFbId];

    FBM_MUTEX_UNLOCK(ucFbgId);

#if 1
    if ((ucFbStatus == FBM_FB_STATUS_RESIZE_DONE) && !FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        FB_CHG_INFO_T t_fb_info;

        t_fb_info.fgOmxSrc = FALSE;
        t_fb_info.ucFbgId = ucFbgId;
        t_fb_info.ucFbid  = ucSrcId;

        if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_FB_READY_IND]))
        {
            ((FBM_FB_READY_IND_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND])(&t_fb_info);
        }
        else
        {
            ASSERT_FBM(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND] == 0);
        }
    }
#endif
}

UCHAR FBM_GetEmptyResizeFrameBuffer(UCHAR ucFbgId, UCHAR ucSrcFbId, UCHAR ucTaskId, UINT32 u4Delay, UCHAR* pucRetValue)
{
    UCHAR ucFbId;

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

    ASSERT_FBM(ucTaskId != 0xFF);

    FBM_MUTEX_LOCK(ucFbgId);
    *pucRetValue = 0;

    if (_prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessTaskId != ucTaskId)
    {

        *pucRetValue = 1;
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }
    ucFbId = FBM_FB_ID_UNKNOWN;
    // wait semaphore (Empty)
    _prFbg[ucFbgId].aucResizeBlockFb = ucSrcFbId;
    if(FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE) && _prFbg[ucFbgId].rResizeEmptyQ.ucCount == 0)
    {
        UCHAR ucFbIdx = 0;
        for(ucFbIdx = 0; ucFbIdx <_prFbg[ucFbgId].ucSeamlessFbNs; ucFbIdx++)
        {
            if(_prFbg[ucFbgId].aucResizeFbStatus[ucFbIdx] == FBM_FB_STATUS_RESIZE_DONE)
            {
                _FBM_PutFrameBufferToEmptyResizeQ(ucFbgId, ucFbIdx);
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
            }
        }
    }
    if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
    {
        // wait semaphore success
        _prFbg[ucFbgId].aucResizeBlockFb = FBM_FB_ID_UNKNOWN;

        if(_prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessTaskId != ucTaskId)
        {

            *pucRetValue = 1;
            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResizeQSemaphore) == OSR_OK);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        ucFbId = _FbmGetEmptyFrameBufferFromEmptyResizeQ(ucFbgId);

        // Work around counting semaphore issue
        if (ucFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"Unexpected error when get empty resize buffer!!!\n");
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucFbId %d\n",ucFbId);
            ASSERT_FBM(ucFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_prFbg[ucFbgId].aucResizeFbStatus[ucFbId] != FBM_FB_STATUS_EMPTY)
        {
            LOG(0,"ucFbgId(%d) ucFbId(%d) ResizeFbStatus(%d)\n",
                ucFbgId,ucFbId,_prFbg[ucFbgId].aucResizeFbStatus[ucFbId]);
        }
        ASSERT_FBM(_prFbg[ucFbgId].aucResizeFbStatus[ucFbId] == FBM_FB_STATUS_EMPTY);
    }
    else
    {
        // wait semaphore fail
        _prFbg[ucFbgId].aucResizeBlockFb = FBM_FB_ID_UNKNOWN;

        ASSERT_FBM(_prFbg[ucFbgId].hEmptyResizeQSemaphore.i4Count == 0);
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    if (ucFbId < FBM_MAX_FB_NS_PER_GROUP)
    {
        _FbmFbLog(ucFbgId,ucFbId, FBM_FB_STATUS_RESIZE, __func__, __LINE__);
        _prFbg[ucFbgId].aucResizeFbStatus[ucFbId] = FBM_FB_STATUS_RESIZE;
        _prFbg[ucFbgId].ucFbResize = ucFbId;
        _prFbg[ucFbgId].aucResizeSrcFbId[ucFbId] = ucSrcFbId;
        _prFbg[ucFbgId].aucResizeTaskId[ucFbId] = ucTaskId;
        _prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessResizeFbid = ucFbId;
        _prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessResize2Fbid = FBM_FB_ID_UNKNOWN;
        _prFbg[ucFbgId].prPicHdr[ucSrcFbId].fgSeamlessResized = FALSE;
        if(_prFbg[ucFbgId].u4ResizeBufferFlag[ucFbId] & SEAMLESS_FB_FLAG_MEMREST)
        {
            UINT32 u4FbSize = _prFbg[ucFbgId].rSeqHdr.u4ResizeWidth * _prFbg[ucFbgId].rSeqHdr.u4ResizeHeight;
            FBM_MemReset((VOID*)_prFbg[ucFbgId].au4ResizeAddrY[ucFbId],0x0,u4FbSize);
            FBM_MemReset((VOID*)_prFbg[ucFbgId].au4ResizeAddrC[ucFbId],0x80808080,u4FbSize>>1);
            _prFbg[ucFbgId].u4ResizeBufferFlag[ucFbId] &= ~(SEAMLESS_FB_FLAG_MEMREST);
        }
    }
    else
    {
        LOG(1, "[Warning] Get Empty Ref Fail (%d, %d)\n", ucFbgId, ucFbId);
    }

    // [LOG] FBM get empty Ref FB
    SYSLOG(FBM_PREFIX + 10 + ucFbgId, ucFbId, _prFbg[ucFbgId].rResizeEmptyQ.ucCount, 0);

    FBM_MUTEX_UNLOCK(ucFbgId);

    //callback to b2r to update buffer within ready threshold
    if (!FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        FB_CHG_INFO_T t_fb_info;

        t_fb_info.fgOmxSrc = FALSE;
        t_fb_info.ucFbgId = ucFbgId;
        t_fb_info.ucFbid  = ucSrcFbId;

        if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_FB_READY_IND]))
        {
            ((FBM_FB_READY_IND_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND])(&t_fb_info);
        }
        else
        {
            ASSERT_FBM(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND] == 0);
        }
    }

    x_memcpy((void*)&_prFbg[ucFbgId].prPicHdr[ucSrcFbId].rTimeB2rReleaseRzFB, (void*)(&_prFbg[ucFbgId].arRlResizeFb[ucFbId]), sizeof(HAL_TIME_T));
    return ucFbId;

}

UCHAR FBM_GetEmptyResize2FrameBuffer(UCHAR ucFbgId, UCHAR ucSrcFbId, UCHAR ucTaskId, UINT32 u4Delay, UCHAR* pucRetValue)
{
    UCHAR ucRzFbId;

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

    ASSERT_FBM(ucTaskId != 0xFF);

    FBM_MUTEX_LOCK(ucFbgId);
    *pucRetValue = 0;

    if (_prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessTaskId != ucTaskId)
    {

        *pucRetValue = 1;
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }
    ucRzFbId = FBM_FB_ID_UNKNOWN;
    // wait semaphore (Empty)
    _prFbg[ucFbgId].aucResize2BlockFb = ucSrcFbId;
    if(FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE) && _prFbg[ucFbgId].rResize2EmptyQ.ucCount == 0)
    {
        UCHAR ucFbIdx = 0;
        for(ucFbIdx = 0; ucFbIdx <_prFbg[ucFbgId].ucSeamless2FbNs; ucFbIdx++)
        {
            if(_prFbg[ucFbgId].aucResize2FbStatus[ucFbIdx] == FBM_FB_STATUS_RESIZE_DONE)
            {
                _FBM_PutFrameBufferToEmptyResize2Q(ucFbgId, ucFbIdx);
                VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
            }
        }
    }

    if (_FBM_csema_lock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore, X_SEMA_OPTION_WAIT, u4Delay) == OSR_OK)
    {
        // wait semaphore success
        _prFbg[ucFbgId].aucResize2BlockFb = FBM_FB_ID_UNKNOWN;

        if(_prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessTaskId != ucTaskId)
        {

            *pucRetValue = 1;
            VERIFY(_FBM_csema_unlock(&_prFbg[ucFbgId].hEmptyResize2QSemaphore) == OSR_OK);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        ucRzFbId = _FbmGetEmptyFrameBufferFromEmptyResize2Q(ucFbgId);

        // Work around counting semaphore issue
        if (ucRzFbId == FBM_FB_ID_UNKNOWN)
        {
            LOG(0,"Unexpected error when get empty resize2 buffer!!!\n");
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }

        if (ucRzFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"ucRzFbId %d\n",ucRzFbId);
            ASSERT_FBM(ucRzFbId < FBM_MAX_FB_NS_PER_GROUP);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return FBM_FB_ID_UNKNOWN;
        }
        if (_prFbg[ucFbgId].aucResize2FbStatus[ucRzFbId] != FBM_FB_STATUS_EMPTY)
        {
            LOG(0,"ucFbgId(%d) ucRzFbId(%d) Resize2FbStatus(%d)\n",
                ucFbgId,ucRzFbId,_prFbg[ucFbgId].aucResize2FbStatus[ucRzFbId]);
        }

        ASSERT_FBM(_prFbg[ucFbgId].aucResize2FbStatus[ucRzFbId] == FBM_FB_STATUS_EMPTY);
    }
    else
    {
        // wait semaphore fail
        _prFbg[ucFbgId].aucResize2BlockFb = FBM_FB_ID_UNKNOWN;

        if (_prFbg[ucFbgId].hEmptyResize2QSemaphore.i4Count != 0)
        {
            LOG(0,"ucFbgId %d ResizeQSemaphore.i4Count %d\n",
                ucFbgId,_prFbg[ucFbgId].hEmptyResize2QSemaphore.i4Count);
        }

        ASSERT_FBM(_prFbg[ucFbgId].hEmptyResize2QSemaphore.i4Count == 0);
        FBM_MUTEX_UNLOCK(ucFbgId);
        return FBM_FB_ID_UNKNOWN;
    }

    if (ucRzFbId < FBM_MAX_FB_NS_PER_GROUP)
    {
        _FbmFbLog(ucFbgId,ucRzFbId, FBM_FB_STATUS_RESIZE, __func__, __LINE__);
        _prFbg[ucFbgId].aucResize2FbStatus[ucRzFbId] = FBM_FB_STATUS_RESIZE;
        _prFbg[ucFbgId].ucFbResize2 = ucRzFbId;
        _prFbg[ucFbgId].aucResize2SrcFbId[ucRzFbId] = ucSrcFbId;
        _prFbg[ucFbgId].aucResize2TaskId[ucRzFbId] = ucTaskId;
        _prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessResize2Fbid = ucRzFbId;
        _prFbg[ucFbgId].prPicHdr[ucSrcFbId].ucSeamlessResizeFbid = FBM_FB_ID_UNKNOWN;
        _prFbg[ucFbgId].prPicHdr[ucSrcFbId].fgSeamlessResized = FALSE;
        if(_prFbg[ucFbgId].u4Resize2BufferFlag[ucRzFbId] & SEAMLESS_FB_FLAG_MEMREST)
        {
            UINT32 u4FbSize = _prFbg[ucFbgId].rSeqHdr.u4ResizeWidth * _prFbg[ucFbgId].rSeqHdr.u4ResizeHeight;
            FBM_MemReset((VOID*)_prFbg[ucFbgId].au4Resize2AddrY[ucRzFbId],0x0,u4FbSize);
            FBM_MemReset((VOID*)_prFbg[ucFbgId].au4Resize2AddrC[ucRzFbId],0x80808080,u4FbSize>>1);
            _prFbg[ucFbgId].u4Resize2BufferFlag[ucRzFbId] &= ~(SEAMLESS_FB_FLAG_MEMREST);
        }
    }
    else
    {
        LOG(1, "[Warning] Get Empty Ref Fail (%d, %d)\n", ucFbgId, ucRzFbId);
    }

    // [LOG] FBM get empty Ref FB
    SYSLOG(FBM_PREFIX + 10 + ucFbgId, ucRzFbId, _prFbg[ucFbgId].rResize2EmptyQ.ucCount, 0);

    FBM_MUTEX_UNLOCK(ucFbgId);
#if 0
    //callback to b2r to update buffer within ready threshold
    if (!FBM_ChkFrameBufferFlag(ucFbgId, FBM_FLAG_THUMBNAIL_MODE))
    {
        if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_FB_READY_IND]))
        {
            ((FBM_FB_READY_IND_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND])(ucFbgId);
        }
        else
        {
            ASSERT_FBM(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_FB_READY_IND] == 0);
        }
    }

    x_memcpy((void*)&_prFbg[ucFbgId].prPicHdr[ucSrcFbId].rTimeB2rReleaseRzFB, (void*)(&_prFbg[ucFbgId].arRlResizeFb[ucFbId]), sizeof(HAL_TIME_T));
#endif

    return ucRzFbId;

}



void FBM_GetResizeEmptyQCount(UCHAR ucFbgId, UCHAR* pucCount)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    if (pucCount == NULL)
    {
        return;
    }

    *pucCount = _prFbg[ucFbgId].rResizeEmptyQ.ucCount;
}

BOOL FBM_IsSeamlessFB(UCHAR ucFbgId, UCHAR ucFbId)
{
    BOOL bNeedResize = FALSE;

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

    FBM_MUTEX_LOCK(ucFbgId);

    if ((_prFbg[ucFbgId].prPicHdr != NULL) && (ucFbId < FBM_MAX_FB_NS_PER_GROUP))
    {
        if (_prFbg[ucFbgId].fgAutoSeamless || _prFbg[ucFbgId].prPicHdr[ucFbId].fgSeamlessDisp)
        {
            bNeedResize = TRUE;
        }
    }
    else
    {
        bNeedResize = FALSE;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
    return bNeedResize;
}

void FBM_SetWfdFrameBufferFlag(UCHAR ucFbgId, UINT32 u4Flag)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _prFbg[ucFbgId].u4WfdFlag |= u4Flag;

    _prFbg[ucFbgId].u4_es_cnt = 1;

    FBM_MUTEX_UNLOCK(ucFbgId);
}

INT32 FBM_ChkWfdFrameBufferFlag(UCHAR ucFbgId, UINT32 u4Flag)
{
    UINT32 ucChk;

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

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].u4WfdFlag & u4Flag)
    {
        ucChk = 1;
    }
    else
    {
        ucChk = 0;
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucChk;
}

void FBM_ClrWfdFrameBufferFlag(UCHAR ucFbgId, UINT32 u4Flag)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _prFbg[ucFbgId].u4WfdFlag &= ~u4Flag;

    FBM_MUTEX_UNLOCK(ucFbgId);
}

void FBM_AccumulateWfdFrameCnt(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    _prFbg[ucFbgId].u4_es_cnt ++;

    FBM_MUTEX_UNLOCK(ucFbgId);
}

UINT32 FBM_WfdFrameStatistics(UCHAR ucFbgId)
{
    UINT32 u4_es_cnt = 0;
    if (VERIFY_FBG(ucFbgId))
    {
        return u4_es_cnt;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    u4_es_cnt = _prFbg[ucFbgId].u4_es_cnt ;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return u4_es_cnt;
}

UCHAR FBM_GetDisplayFB(UCHAR ucFbgId)
{
    UCHAR ucFbId = FBM_FB_ID_UNKNOWN;

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

    FBM_MUTEX_LOCK(ucFbgId);

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

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

        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_DISPLAYQ);

        FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_LOCK);

        _prFbg[ucFbgId].u4DispTag[ucFbId] = OMX_PENDING_DISPTAG;

        if (_prFbg[ucFbgId].fgOMXGetFirstFb == FALSE)
        {
            _prFbg[ucFbgId].ucOMXPrevFb = FBM_FB_ID_UNKNOWN;
            _prFbg[ucFbgId].fgOMXGetFirstFb = TRUE;
        }


    }

    _prFbg[ucFbgId].ucOMXPrevFb = ucFbId;

    FBM_MUTEX_UNLOCK(ucFbgId);

    return ucFbId;
}

VOID FBM_SetTagQValid(BOOL fgValid)
{
    fgFbmEnableTagQ = fgValid;
    if(fgFbmEnableTagQ)
    {
        LOG(1,"SetTagQ TRUE\n");
    }
    else
    {
        LOG(1,"SetTagQ FALSE\n");
    }
    return;
}

BOOL FBM_SetDispTag(UCHAR ucFbgId, UCHAR ucFbId,UINT64 u4Tag)
{
    if (fgFbmEnableTagQ)
    {
        return FBM_SetDispTag_UseTagQ(ucFbgId,ucFbId,u4Tag);
    }
    if((VERIFY_FBG(ucFbgId))||(VERIFY_FB(ucFbgId, ucFbId)))
    {
        return FALSE;
    }

    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
    {
        LOG(0,"omx set tag fbg=%d,fb=%d,Tag=0x%llx\n",ucFbgId,ucFbId,u4Tag);
    }

    FBM_MUTEX_LOCK(ucFbgId);
    _prFbg[ucFbgId].u4DispTag[ucFbId]=u4Tag;
    if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
    {
        LOG(0,"ucFbgId %d ucFbId %d Status %d\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
    }

    ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
    FBM_MUTEX_UNLOCK(ucFbgId);
    return TRUE;
}

BOOL FBM_QueryFbByDispTag(UINT64 u4Tag, UCHAR *pucFbgId, UCHAR *pucFbId)
{
    UCHAR ucFbgId;
    UCHAR ucFbId;

    if (fgFbmEnableTagQ)
    {
        return FBM_GetFbByDispTag_UseTagQ(u4Tag,pucFbgId,pucFbId,FALSE);
    }

    if (pucFbgId == NULL || pucFbId == NULL)
    {
        return FALSE;
    }

    *pucFbgId = FBM_FBG_ID_UNKNOWN;
    *pucFbId = FBM_FB_ID_UNKNOWN;

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

        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbId);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return TRUE;
            }

            if(_prFbg[ucFbgId].u4DispTag[ucFbId] == u4Tag)
            {
                *pucFbgId = ucFbgId;
                *pucFbId = ucFbId;

                if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
                {
                    LOG(0,"ucFbgId %d ucFbId %d Status %d\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                }

                ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    LOG(0,"query Taginfo fbg=%d,fb=%d,Tag=0x%llx\n",ucFbgId,ucFbId,u4Tag);
                }

                FBM_MUTEX_UNLOCK(ucFbgId);
                return TRUE;
            }
        }

        FBM_MUTEX_UNLOCK(ucFbgId);
    }

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

        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (_prFbg[ucFbgId].u4DropTag[ucFbId] == u4Tag)
            {
                if (_prFbg[ucFbgId].u4DispTag[ucFbId] == INVALID_DISPTAG)
                {
                    *pucFbgId = ucFbgId;
                    *pucFbId = ucFbId;
                    FBM_MUTEX_UNLOCK(ucFbgId);
                    LOG(2,"HWC query Last Tag=0x%llx fbg(%d) fb(%d)\n",u4Tag,ucFbgId,ucFbId);
                    return TRUE;
                }
            }
        }
        FBM_MUTEX_UNLOCK(ucFbgId);
    }

    LOG(0," This Tag=0x%llx is not exist,query fail.\n",u4Tag);

    return FALSE;
}

#ifndef USERDRV_KERNEL_MOD
BOOL FBM_GetFbByDispTag(UINT64 u4Tag, UCHAR *pucFbgId, UCHAR *pucFbId)
{
    UCHAR ucFbgId;
    UCHAR ucFbId;

    if (fgFbmEnableTagQ)
    {
        return FBM_GetFbByDispTag_UseTagQ(u4Tag,pucFbgId,pucFbId,TRUE);
    }

    if (pucFbgId == NULL || pucFbId == NULL)
    {
        return FALSE;
    }

    *pucFbgId = FBM_FBG_ID_UNKNOWN;
    *pucFbId = FBM_FB_ID_UNKNOWN;

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

        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbId);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return TRUE;
            }

            if(_prFbg[ucFbgId].u4DispTag[ucFbId] == u4Tag)
            {
                *pucFbgId = ucFbgId;
                *pucFbId = ucFbId;
                _prFbg[ucFbgId].u4LastB2rAcquireDispTag = u4Tag;
                _prFbg[ucFbgId].ucLastB2rAcquireFbId = ucFbId;

                _prFbg[ucFbgId].u4DispTag[ucFbId]=INVALID_DISPTAG;
                _prFbg[ucFbgId].u4DropTag[ucFbId] = u4Tag;
                _prFbg[ucFbgId].prPicHdr[ucFbId].fgWillSeqChg = FALSE;
                if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
                {
                    LOG(0,"ucFbgId %d ucFbId %d Status %d\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                }

                ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    LOG(0,"HWC got fbg=%d,fb=%d,Tag=0x%llx\n",ucFbgId,ucFbId,u4Tag);
                }

                FBM_MUTEX_UNLOCK(ucFbgId);
                return TRUE;
            }
        }

        FBM_MUTEX_UNLOCK(ucFbgId);
    }
    LOG(2," This Tag=0x%llx is not exist,HWC Can't Got it.\n",u4Tag);

    return FALSE;
}

BOOL FBM_GetFbByDispTag_Ex(UINT64 u4Tag, UCHAR *pucMainFbgId, UCHAR *pucMainFbId,UCHAR *pucSubFbgId, UCHAR *pucSubFbId)
{
    UCHAR uc1stFbgId = FBM_FBG_ID_UNKNOWN;
    UCHAR uc2ndFbgId = FBM_FBG_ID_UNKNOWN;
    UCHAR uc1stFbId = FBM_FB_ID_UNKNOWN;
    UCHAR uc2ndFbId = FBM_FB_ID_UNKNOWN;


    if (FBM_GetFbByDispTag(u4Tag, &uc1stFbgId, &uc1stFbId) == TRUE)
    {
        if(VERIFY_FBG(uc1stFbgId))
        {
            return FALSE;
        }
        if (_prFbg[uc1stFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_NONE)
        {
            *pucMainFbgId = uc1stFbgId;
            *pucMainFbId  = uc1stFbId;
            *pucSubFbgId  = uc2ndFbgId;
            *pucSubFbId   = uc2ndFbId;
            return TRUE;
        }
        if (FBM_GetFbByDispTag(u4Tag, &uc2ndFbgId, &uc2ndFbId) == TRUE)
        {
            if(VERIFY_FBG(uc2ndFbgId))
            {
                return FALSE;
            }
            if(_prFbg[uc1stFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_MAIN)
            {
                if(_prFbg[uc2ndFbgId].eDolbyType != FBM_FBG_DOLBY_TYPE_SUB)
                {
                    LOG(0,"Tag 0x%llx, 1st fbg(%d) 1st fb(%d),2nd fbg(%d) 2nd fb(%d) line(%d)\n",u4Tag,
                        uc1stFbgId,uc1stFbId,uc2ndFbgId,uc2ndFbId,__LINE__);
                    ASSERT_FBM(_prFbg[uc2ndFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_SUB);
                    return FALSE;
                }
                *pucMainFbgId = uc1stFbgId;
                *pucMainFbId  = uc1stFbId;
                *pucSubFbgId  = uc2ndFbgId;
                *pucSubFbId   = uc2ndFbId;
                return TRUE;
            }
            else if(_prFbg[uc1stFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_SUB)
            {
                if(_prFbg[uc2ndFbgId].eDolbyType != FBM_FBG_DOLBY_TYPE_MAIN)
                {
                    LOG(0,"Tag 0x%llx, 1st fbg(%d) 1st fb(%d),2nd fbg(%d) 2nd fb(%d) line(%d)\n",u4Tag,
                        uc1stFbgId,uc1stFbId,uc2ndFbgId,uc2ndFbId,__LINE__);
                    ASSERT_FBM(_prFbg[uc2ndFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_MAIN);
                    return FALSE;
                }
                *pucMainFbgId = uc2ndFbgId;
                *pucMainFbId  = uc2ndFbId;
                *pucSubFbgId  = uc1stFbgId;
                *pucSubFbId   = uc1stFbId;
                return TRUE;
            }
            else
            {
                LOG(0,"Error NOT dolby playback, please do NOT call this API\n");
                return FALSE;
            }
        }
        else
        {
            *pucMainFbgId = uc1stFbgId;
            *pucMainFbId  = uc1stFbId;
            *pucSubFbgId  = uc2ndFbgId;
            *pucSubFbId   = uc2ndFbId;
            LOG(2,"Dolby playback, can NOT get sub info\n");
            return TRUE;
        }
    }
    else
    {
        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
        {
            LOG(2," This Tag=0x%llx is not exist,Get First Fail.\n",u4Tag);
        }
        return FALSE;
    }
}

#endif
BOOL FBM_ReleaseBufferByDispTag(UINT64 u4Tag)
{
    UCHAR ucFbgId;
    UCHAR ucFbId;
    BOOL bRet = FALSE;
    UCHAR ucReleaseCount = 0;

    if (fgFbmEnableTagQ)
    {
        bRet = FBM_ReleaseBufferByDispTag_UseTagQ(u4Tag,&ucReleaseCount);
        if(bRet == TRUE)
        {
            return TRUE;
        }
    }

    for (ucFbgId = 0; ucFbgId < FBG_MAX_NS; ucFbgId++)
    {
        if(VERIFY_FBG(ucFbgId)==FALSE)
        {
            FBM_MUTEX_LOCK(ucFbgId);

            for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
            {
                if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
                {
                    LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbId);
                    FBM_MUTEX_UNLOCK(ucFbgId);
                    return FALSE;
                }
                if(_prFbg[ucFbgId].u4DispTag[ucFbId]==u4Tag)
                {
                    _prFbg[ucFbgId].u4DispTag[ucFbId]=INVALID_DISPTAG;
                    _prFbg[ucFbgId].prPicHdr[ucFbId].fgWillSeqChg = FALSE;

                    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                    {
                        LOG(0,"release fbg=%d,fb=%d,Tag=0x%llx\n",ucFbgId,ucFbId,u4Tag);
                    }
                    if((_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK) && !FBM_ChkFrameBufferPicFlag(ucFbgId, ucFbId, FBM_MM_EOS_FLAG | FBM_MM_NOT_DISPLAY_FLAG))
                    {
                        LOG(0,"FBM_ReleaseBufferByDispTag fbg=%d,fb=%d,Tag=0x%llx, status:%d\n",ucFbgId,ucFbId,u4Tag,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                        ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
                    }
                    FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
                    ucReleaseCount ++;
                    if(_prFbg[ucFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_NONE || (ucReleaseCount >= 2))
                    {
                        FBM_MUTEX_UNLOCK(ucFbgId);
                        return TRUE;
                    }
                    else
                    {
                        //should find the same tag in another fbg.
                        break;
                    }
                }
            }

            FBM_MUTEX_UNLOCK(ucFbgId);
        }
    }

    LOG(5,"FBM_ReleaseBufferByDispTag don't need Tag=0x%llx\n",u4Tag);
    return FALSE;
}

VOID FBM_ReleaseBufferByIndex(UCHAR ucFbgId, UCHAR ucFbId)
{
    if((VERIFY_FBG(ucFbgId)))
    {
        return;
    }

    if (fgFbmEnableTagQ)
    {
        FBM_ReleaseBufferByIndex_UseTagQ(ucFbgId,ucFbId);
        return;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
    {
        LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
            ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
    }
    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
    {
        LOG(0,"FBM_ReleaseBufferByIndex Clear Tag=0x%llx Fbg=%d Fb=%d Status=%d\n",
            _prFbg[ucFbgId].u4DispTag[ucFbId],
            ucFbgId,ucFbId,
            _prFbg[ucFbgId].aucFbStatus[ucFbId]);
    }
    _prFbg[ucFbgId].u4DispTag[ucFbId]=INVALID_DISPTAG;
    ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
    FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
    FBM_MUTEX_UNLOCK(ucFbgId);
    return;
}

//-------------------------------------------------------------------------
/** FBM_FlushLockToEmptyQ
 *  Flush FBM Group lock frame buffer  ->> OMX Flush API
 *  @param  ucFbgType   FBG type.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
VOID FBM_FlushLockToEmptyQ(UCHAR ucFbgId)
{
    UCHAR ucFbId;

    if (fgFbmEnableTagQ)
    {
        FBM_FlushLockToEmptyQ_UseTagQ(ucFbgId);
        return;
    }
    if(VERIFY_FBG(ucFbgId)==FALSE)
    {
        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbId);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return ;
            }
            if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK) &&
                (_prFbg[ucFbgId].u4DispTag[ucFbId] == OMX_PENDING_DISPTAG))
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    LOG(1,"omx flush lock, fbg:%d, fbid:%d, tag:0x%llx\n", ucFbgId, ucFbId, _prFbg[ucFbgId].u4DispTag[ucFbId]);
                }
                _prFbg[ucFbgId].u4DispTag[ucFbId]=INVALID_DISPTAG;
                FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
            }
        }

        FBM_MUTEX_UNLOCK(ucFbgId);
    }


    return;
}

static BOOL FBM_ReleaseBufferByDispTag_UseTagQ(UINT64 u4Tag,UCHAR *pucReleaseCount)
{
    UCHAR ucFbgId;
    UCHAR ucFbId = FBM_FB_ID_UNKNOWN;
    UCHAR ucCnt,ucIdx;
    //UCHAR ucCleanIndex = 0;
    //UCHAR ucCleanFbId;

    for (ucFbgId = 0; ucFbgId < FBG_MAX_NS; ucFbgId++)
    {
        if(VERIFY_FBG(ucFbgId)==FALSE)
        {
            FBM_MUTEX_LOCK(ucFbgId);

            ucCnt = _prFbg[ucFbgId].rTagQ.ucCount;
            for (ucIdx = 0; ucIdx < ucCnt; ucIdx++)
            {
                ucFbId = _prFbg[ucFbgId].rTagQ.aucQueue[(_prFbg[ucFbgId].rTagQ.ucReadIdx + ucIdx) % FBM_MAX_FB_NS_PER_GROUP];
                if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
                {
                    //LOG(0,"Unknown ucFbId(%d) line(%d)\n",ucFbId,__LINE__);
                }
                else
                {
                    if(_prFbg[ucFbgId].u4DispTag[ucFbId]==u4Tag)
                    {

                        if((_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK) && !FBM_ChkFrameBufferPicFlag(ucFbgId, ucFbId, FBM_MM_EOS_FLAG | FBM_MM_NOT_DISPLAY_FLAG))
                        {
                            LOG(0,"FBM_ReleaseBufferByDispTag fbg=%d,fb=%d,Tag=0x%llx, status:%d\n",ucFbgId,ucFbId,u4Tag,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                            ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
                        }

                        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                        {
                            LOG(0,"release fbg=%d,fb=%d,Tag=0x%llx line(%d)\n",ucFbgId,ucFbId,
                                _prFbg[ucFbgId].u4DispTag[ucFbId],__LINE__);
                        }
                        _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                        _prFbg[ucFbgId].prPicHdr[ucFbId].fgWillSeqChg = FALSE;
                        _prFbg[ucFbgId].rTagQ.aucQueue[(_prFbg[ucFbgId].rTagQ.ucReadIdx + ucIdx) % FBM_MAX_FB_NS_PER_GROUP] = FBM_FB_ID_UNKNOWN;
                        FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
                        (*pucReleaseCount) ++;
                        if(_prFbg[ucFbgId].eDolbyType == FBM_FBG_DOLBY_TYPE_NONE || (*pucReleaseCount >= 2))
                        {
                            FBM_MUTEX_UNLOCK(ucFbgId);
                            return TRUE;
                        }
                        else
                        {
                            //should find the same tag in another fbg.
                            break;
                        }
                    }
                }
            }
            if (ucIdx >= ucCnt)
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    LOG(0,"Can't find tagQ release fbg=%d,Tag=0x%llx line(%d)\n",ucFbgId,
                        u4Tag,__LINE__);
                }
            }

            FBM_MUTEX_UNLOCK(ucFbgId);
        }
    }

    LOG(5,"FBM_ReleaseBufferByDispTag don't need Tag=0x%llx\n",u4Tag);
    return FALSE;
}




//-------------------------------------------------------------------------
/** FBM_FlushLockFrameBuffer
 *  Flush FBM Group lock frame buffer -->B2R Flush API
 *  @param  ucFbgType   FBG type.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
void FBM_FlushLockFrameBuffer(UCHAR ucFbgId)
{
    // Note about usage
    // When vdp mode change, flush lock frame buffer

    UCHAR ucFbIdx;

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

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

    LOG(1,"B2r Flush lock Fb\n");

    // put all lock frame buffer into empty queue
    for (ucFbIdx = 0; ucFbIdx < FBM_MAX_FB_NS_PER_GROUP; ucFbIdx++)
    {
        // DispTag == invalid disptag B2r flush or,waiting vdec omx flush
        if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
        {
            LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbIdx);
            FBM_MUTEX_UNLOCK(ucFbgId);
            return ;
        }

        if ((_prFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_LOCK) &&
            ((_prFbg[ucFbgId].u1FbgAppMode != FBM_FBG_APP_OMX_DISP) ||
             ((_prFbg[ucFbgId].u1FbgAppMode == FBM_FBG_APP_OMX_DISP) && (_prFbg[ucFbgId].u4DispTag[ucFbIdx] == INVALID_DISPTAG))))
        {
            if (_prFbg[ucFbgId].ucLastB2rAcquireFbId == ucFbIdx)
            {
                _prFbg[ucFbgId].u4DispTag[ucFbIdx] = _prFbg[ucFbgId].u4LastB2rAcquireDispTag;

                // _prFbg[ucFbgId].u4LastB2rAcquireDispTag = INVALID_DISPTAG;
                // _prFbg[ucFbgId].ucLastB2rAcquireFbId = FBM_FB_ID_UNKNOWN;

                LOG(0,"The Last FB(%d) in B2r, don't set empty Tag(0x%llx)\n",
                    ucFbIdx,_prFbg[ucFbgId].u4DispTag[ucFbIdx]);
            }
            else
            {
                FBM_SetFrameBufferStatus(ucFbgId, ucFbIdx, FBM_FB_STATUS_EMPTY);
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    LOG(1,"B2r flush lock, fbg:%d, fbid:%d, tag:0x%llx\n", ucFbgId, ucFbIdx, _prFbg[ucFbgId].u4DispTag[ucFbIdx]);
                }

            }
        }
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
}

//-------------------------------------------------------------------------
/** FBM_QueryLastFrameBuffer
 *  Query the last fb in B2R ,if is the last fb,then can not set empty for b2r.
 *  @param  ucFbgType   FBG type.
 *  @return TRUE: the last fb,FALSE not last fb.
 */
//-------------------------------------------------------------------------

BOOL FBM_QueryLastFrameBuffer(UCHAR ucFbgId,UCHAR ucFbIdx)
{
    BOOL bIsLastFB = FALSE;
    if (VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }

    if (ucFbIdx >= FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbIdx);
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);

    LOG(1,"FBM_QueryLastFrameBuffer\n");

    if ((_prFbg[ucFbgId].aucFbStatus[ucFbIdx] == FBM_FB_STATUS_LOCK))
    {
        if (_prFbg[ucFbgId].ucLastB2rAcquireFbId == ucFbIdx)
        {
            bIsLastFB = TRUE;
            LOG(0,"The Last FB(%d-%d) in B2r,Tag(%lld) \n",
                ucFbgId,ucFbIdx,_prFbg[ucFbgId].u4DispTag[ucFbIdx]);
        }
        else
        {
            bIsLastFB = FALSE;

            LOG(0,"FB(%d-%d) in B2r\n",ucFbgId,ucFbIdx);

        }

    }
    else
    {
        LOG(0,"Frame buffer(%d-%d) status (%d) not locked!!\n",ucFbgId,ucFbIdx,_prFbg[ucFbgId].aucFbStatus[ucFbIdx]);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);

    return bIsLastFB;

}

static BOOL FBM_ReorderTagQ(UCHAR ucFbgId)
{
    UCHAR ucCount;
    UCHAR ucStoreValidIdx[FBM_MAX_FB_NS_PER_GROUP] = {0};
    UCHAR ucValidCount = 0;
    UCHAR ucTmpIndx;
    UINT8 i = 0;
    if(VERIFY_FBG(ucFbgId))
    {
        return FALSE;
    }
    ucCount = _prFbg[ucFbgId].rTagQ.ucCount;
    for(i = 0; i < ucCount; i++)
    {
        ucTmpIndx = (_prFbg[ucFbgId].rTagQ.ucReadIdx + i) % FBM_MAX_FB_NS_PER_GROUP;
        if(_prFbg[ucFbgId].rTagQ.aucQueue[ucTmpIndx] >= FBM_MAX_FB_NS_PER_GROUP)
        {
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
            {
                LOG(0,"old ReadIdx(%d) (%d) status(255)\n",_prFbg[ucFbgId].rTagQ.ucReadIdx,i);
            }
            _prFbg[ucFbgId].rTagQ.ucCount--; //tag is released before
        }
        else
        {
            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
            {
                LOG(0,"old ReadIdx(%d) (%d) status(%d)\n",_prFbg[ucFbgId].rTagQ.ucReadIdx,i,_prFbg[ucFbgId].rTagQ.aucQueue[ucTmpIndx]);
            }
            ucStoreValidIdx[ucValidCount] = _prFbg[ucFbgId].rTagQ.aucQueue[ucTmpIndx];
            ucValidCount ++;
        }
    }
    if(ucValidCount != _prFbg[ucFbgId].rTagQ.ucCount)
    {
        LOG(0,"Reorder TagQ Error %d %d\n",ucValidCount,_prFbg[ucFbgId].rTagQ.ucCount);
    }
    for(i = 0; i < ucValidCount; i++)
    {
        ucTmpIndx = (_prFbg[ucFbgId].rTagQ.ucReadIdx + i) % FBM_MAX_FB_NS_PER_GROUP;
        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
        {
            LOG(0,"new ReadIdx(%d) (%d) status(%d)\n",_prFbg[ucFbgId].rTagQ.ucReadIdx,i,ucStoreValidIdx[i]);
        }
        _prFbg[ucFbgId].rTagQ.aucQueue[ucTmpIndx] = ucStoreValidIdx[i];
    }
    return TRUE;
}

static BOOL FBM_SetDispTag_UseTagQ(UCHAR ucFbgId, UCHAR ucFbId,UINT64 u4Tag)
{
    UCHAR ucNextWriteIdx;
    if((VERIFY_FBG(ucFbgId))||(VERIFY_FB(ucFbgId, ucFbId)))
    {
        return FALSE;
    }

    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
    {
        LOG(0,"omx set tag fbg=%d,fb=%d,Tag=0x%llx\n",ucFbgId,ucFbId,u4Tag);
    }

    FBM_MUTEX_LOCK(ucFbgId);
    _prFbg[ucFbgId].u4DispTag[ucFbId] = u4Tag;

    if(_prFbg[ucFbgId].rTagQ.ucCount >= FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(2,"tagQ full, need reorder\n");
        FBM_ReorderTagQ(ucFbgId);
    }

    ucNextWriteIdx = (_prFbg[ucFbgId].rTagQ.ucReadIdx + _prFbg[ucFbgId].rTagQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
    _prFbg[ucFbgId].rTagQ.aucQueue[ucNextWriteIdx] = ucFbId;
    _prFbg[ucFbgId].rTagQ.ucCount++;

    if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
    {
        LOG(0,"ucFbgId %d ucFbId %d Status %d\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
    }

    ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);
    FBM_MUTEX_UNLOCK(ucFbgId);
    return TRUE;
}


static BOOL FBM_GetFbByDispTag_UseTagQ(UINT64 u4Tag, UCHAR *pucFbgId, UCHAR *pucFbId,BOOL b_get)
{
    UCHAR ucFbgId;
    UCHAR ucFbId = FBM_FB_ID_UNKNOWN;
    UCHAR ucCnt,ucIdx;
    UCHAR ucCleanIndex = 0;
    UCHAR ucCleanFbId;

    if (pucFbgId == NULL || pucFbId == NULL)
    {
        return FALSE;
    }

    *pucFbgId = FBM_FBG_ID_UNKNOWN;
    *pucFbId = FBM_FB_ID_UNKNOWN;

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

        FBM_MUTEX_LOCK(ucFbgId);

        ucCnt = _prFbg[ucFbgId].rTagQ.ucCount;
        for (ucIdx = 0; ucIdx < ucCnt; ucIdx++)
        {
            ucFbId = _prFbg[ucFbgId].rTagQ.aucQueue[(_prFbg[ucFbgId].rTagQ.ucReadIdx + ucIdx) % FBM_MAX_FB_NS_PER_GROUP];
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                //LOG(0,"Unknown ucFbId(%d) line(%d)\n",ucFbId,__LINE__);
            }
            else
            {
                if (_prFbg[ucFbgId].u4DispTag[ucFbId] == u4Tag)
                {
                    _prFbg[ucFbgId].u4DropTag[ucFbId] = u4Tag;
                    for (ucCleanIndex = 0; (ucCleanIndex <= ucIdx) && (b_get == TRUE); ucCleanIndex++)
                    {
                        if (_prFbg[ucFbgId].rTagQ.ucCount > 0)
                        {
                            ucCleanFbId = _prFbg[ucFbgId].rTagQ.aucQueue[_prFbg[ucFbgId].rTagQ.ucReadIdx];
                            _prFbg[ucFbgId].rTagQ.aucQueue[_prFbg[ucFbgId].rTagQ.ucReadIdx] = FBM_FB_ID_UNKNOWN;
                            _prFbg[ucFbgId].rTagQ.ucReadIdx =
                                (UCHAR)((_prFbg[ucFbgId].rTagQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP);
                            _prFbg[ucFbgId].rTagQ.ucCount--;

                            if(ucCleanFbId < FBM_MAX_FB_NS_PER_GROUP)
                            {
                                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                                {
                                    if (ucCleanIndex < ucIdx)
                                    {
                                        LOG(0,"HWC pre got fbg=%d,fb=%d,Tag=0x%llx line(%d)\n",ucFbgId,ucCleanFbId,
                                            _prFbg[ucFbgId].u4DispTag[ucCleanFbId],__LINE__);
                                    }
                                    else
                                    {
                                        LOG(0,"HWC got fbg=%d,fb=%d,Tag=0x%llx line(%d)\n",ucFbgId,ucCleanFbId,
                                            _prFbg[ucFbgId].u4DispTag[ucCleanFbId],__LINE__);
                                    }
                                }
                                _prFbg[ucFbgId].u4DispTag[ucCleanFbId] = INVALID_DISPTAG;

                                if (ucCleanIndex < ucIdx)
                                {
                                    FBM_SetFrameBufferStatus(ucFbgId, ucCleanFbId, FBM_FB_STATUS_EMPTY);
                                }
                            }
                        }
                        else
                        {
                            LOG(0,"ucIdx(%d) over queue count(%d) line(%d)\n",ucIdx,_prFbg[ucFbgId].rTagQ.ucCount,__LINE__);
                        }
                    }
                    *pucFbgId = ucFbgId;
                    *pucFbId = ucFbId;

                    if (b_get == TRUE)
                    {
                        _prFbg[ucFbgId].u4LastB2rAcquireDispTag = u4Tag;
                        _prFbg[ucFbgId].ucLastB2rAcquireFbId = ucFbId;

                        _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                        _prFbg[ucFbgId].prPicHdr[ucFbId].fgWillSeqChg = FALSE;
                    }
                    else
                    {
                        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                        {
                            LOG(0,"Query fbg=%d,fb=%d,Tag=0x%llx line(%d)\n",ucFbgId,ucFbId,
                                   u4Tag,__LINE__);
                        }
                    }

                    if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
                    {
                        LOG(0,"ucFbgId %d ucFbId %d Status %d\n",ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
                    }

                    ASSERT_FBM(_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK);

                    FBM_MUTEX_UNLOCK(ucFbgId);
                    return TRUE;
                }
            }
        }
        FBM_MUTEX_UNLOCK(ucFbgId);
    }

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

        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (_prFbg[ucFbgId].u4DropTag[ucFbId] == u4Tag)
            {
                if (_prFbg[ucFbgId].u4DispTag[ucFbId] == INVALID_DISPTAG)
                {
                    *pucFbgId = ucFbgId;
                    *pucFbId = ucFbId;
                    FBM_MUTEX_UNLOCK(ucFbgId);
                    LOG(2,"HWC get Last Tag=0x%llx fbg(%d) fb(%d) b_get(%d)\n",u4Tag,ucFbgId,ucFbId,b_get);
                    return TRUE;
                }
            }
        }
        FBM_MUTEX_UNLOCK(ucFbgId);
    }

    if(b_get)
    {
        LOG(2," This Tag=0x%llx is not exist,Can't get it.\n",u4Tag);
    }
    else
    {
        LOG(2," This Tag=0x%llx is not exist,Can't query it.\n",u4Tag);
    }

    return FALSE;
}


static VOID FBM_ReleaseBufferByIndex_UseTagQ(UCHAR ucFbgId, UCHAR ucFbId)
{
    UCHAR ucCnt,ucIdx;
    UCHAR ucCleanIndex = 0;
    UCHAR ucTagFbId = FBM_FB_ID_UNKNOWN;
    UCHAR ucCleanFbId;

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

    if (_prFbg[ucFbgId].aucFbStatus[ucFbId] != FBM_FB_STATUS_LOCK)
    {
        LOG(0,"ucFbgId(%d) ucFbId(%d) aucFbStatus(%d)\n",
            ucFbgId,ucFbId,_prFbg[ucFbgId].aucFbStatus[ucFbId]);
    }

    ucCnt = _prFbg[ucFbgId].rTagQ.ucCount;
    for (ucIdx = 0; ucIdx < ucCnt; ucIdx++)
    {
        ucTagFbId = _prFbg[ucFbgId].rTagQ.aucQueue[(_prFbg[ucFbgId].rTagQ.ucReadIdx + ucIdx) % FBM_MAX_FB_NS_PER_GROUP];
        if (ucTagFbId >= FBM_MAX_FB_NS_PER_GROUP)
        {
            //LOG(0,"Unknown ucFbId(%d) line(%d)\n",ucTagFbId,__LINE__);
        }
        else if(ucTagFbId == ucFbId)
        {
            break;
        }
    }
    for(ucCleanIndex = 0; (ucCleanIndex <= ucIdx) && (ucIdx < ucCnt); ucCleanIndex++)
    {
        if (_prFbg[ucFbgId].rTagQ.ucCount > 0)
        {
            ucCleanFbId = _prFbg[ucFbgId].rTagQ.aucQueue[_prFbg[ucFbgId].rTagQ.ucReadIdx];
            _prFbg[ucFbgId].rTagQ.aucQueue[_prFbg[ucFbgId].rTagQ.ucReadIdx] = FBM_FB_ID_UNKNOWN;
            _prFbg[ucFbgId].rTagQ.ucReadIdx =
                (UCHAR)((_prFbg[ucFbgId].rTagQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP);
            _prFbg[ucFbgId].rTagQ.ucCount--;

            if(ucCleanFbId < FBM_MAX_FB_NS_PER_GROUP)
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    if (ucCleanIndex < ucIdx)
                    {
                        LOG(0,"FBM_ReleaseBufferByIndex pre Clear Tag=0x%llx Fbg=%d Fb=%d Status=%d line(%d)\n",
                            _prFbg[ucFbgId].u4DispTag[ucCleanFbId],
                            ucFbgId,ucCleanFbId,
                            _prFbg[ucFbgId].aucFbStatus[ucCleanFbId],__LINE__);
                    }
                    else
                    {
                        LOG(0,"FBM_ReleaseBufferByIndex Clear Tag=0x%llx Fbg=%d Fb=%d Status=%d line(%d)\n",
                            _prFbg[ucFbgId].u4DispTag[ucCleanFbId],
                            ucFbgId,ucCleanFbId,
                            _prFbg[ucFbgId].aucFbStatus[ucCleanFbId],__LINE__);
                    }
                }
                _prFbg[ucFbgId].u4DispTag[ucCleanFbId] = INVALID_DISPTAG;
                FBM_SetFrameBufferStatus(ucFbgId, ucCleanFbId, FBM_FB_STATUS_EMPTY);
            }
        }
        else
        {
            LOG(0,"ucIdx(%d) over queue count(%d) line(%d)\n",ucIdx,_prFbg[ucFbgId].rTagQ.ucCount,__LINE__);
        }
    }
    if (ucIdx >= ucCnt)
    {
        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
        {
            LOG(0,"Can't find in tagQ FBM_ReleaseBufferByIndex Clear Tag=0x%llx Fbg=%d Fb=%d Status=%d line(%d)\n",
                _prFbg[ucFbgId].u4DispTag[ucFbId],
                ucFbgId,ucFbId,
                _prFbg[ucFbgId].aucFbStatus[ucFbId],__LINE__);
        }
        _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
        FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
    }

    FBM_MUTEX_UNLOCK(ucFbgId);
    return;
}

//-------------------------------------------------------------------------
/** FBM_FlushLockToEmptyQ
 *  Flush FBM Group lock frame buffer  ->> OMX Flush API
 *  @param  ucFbgType   FBG type.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
static VOID FBM_FlushLockToEmptyQ_UseTagQ(UCHAR ucFbgId)
{
#if 0
    UCHAR ucFbId;
    UCHAR ucCnt,ucIdx;
    UCHAR ucCleanIndex = 0;
    UCHAR ucTagFbId;
    if(VERIFY_FBG(ucFbgId)==FALSE)
    {
        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbId);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return ;
            }
            if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK) &&
                ((_prFbg[ucFbgId].u4DispTag[ucFbId] != INVALID_DISPTAG) || (_prFbg[ucFbgId].u4DispTag[ucFbId] == OMX_PENDING_DISPTAG)))
            {
                ucCnt = _prFbg[ucFbgId].rTagQ.ucCount;
                for (ucIdx = 0; ucIdx < ucCnt; ucIdx++)
                {
                    ucTagFbId = FBM_FB_ID_UNKNOWN;

                    ucTagFbId = _prFbg[ucFbgId].rTagQ.aucQueue[(_prFbg[ucFbgId].rTagQ.ucReadIdx + ucIdx) % FBM_MAX_FB_NS_PER_GROUP];
                    if (ucTagFbId >= FBM_MAX_FB_NS_PER_GROUP)
                    {
                        //LOG(0,"Unknown ucFbId(%d) line(%d)\n",ucTagFbId,__LINE__);
                    }
                    else if (ucTagFbId == ucFbId)
                    {
                        break;
                    }
                }
                for (ucCleanIndex = 0; (ucCleanIndex <= ucIdx) && (ucIdx < ucCnt); ucCleanIndex++)
                {
                    if (_prFbg[ucFbgId].rTagQ.ucCount > 0)
                    {
                        UCHAR ucCleanFbId;
                        ucCleanFbId = _prFbg[ucFbgId].rTagQ.aucQueue[_prFbg[ucFbgId].rTagQ.ucReadIdx];
                        _prFbg[ucFbgId].rTagQ.aucQueue[_prFbg[ucFbgId].rTagQ.ucReadIdx] = FBM_FB_ID_UNKNOWN;
                        _prFbg[ucFbgId].rTagQ.ucReadIdx =
                            (UCHAR)((_prFbg[ucFbgId].rTagQ.ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP);
                        _prFbg[ucFbgId].rTagQ.ucCount--;

                        if(ucCleanFbId < FBM_MAX_FB_NS_PER_GROUP)
                        {
                            if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                            {
                                if (ucCleanIndex < ucIdx)
                                {
                                    LOG(0,"omx pre flush fbg=%d,fb=%d,Tag=0x%llx line(%d)\n",ucFbgId,ucCleanFbId,_prFbg[ucFbgId].u4DispTag[ucCleanFbId],__LINE__);
                                }
                                else
                                {
                                    LOG(0,"omx flush fbg=%d,fb=%d,Tag=0x%llx line(%d)\n",ucFbgId,ucCleanFbId,_prFbg[ucFbgId].u4DispTag[ucCleanFbId],__LINE__);
                                }
                            }
                            _prFbg[ucFbgId].u4DispTag[ucCleanFbId] = INVALID_DISPTAG;
                            FBM_SetFrameBufferStatus(ucFbgId, ucCleanFbId, FBM_FB_STATUS_EMPTY);
                        }
                    }
                    else
                    {
                        LOG(0,"ucIdx(%d) over queue count(%d) line(%d)\n",ucIdx,_prFbg[ucFbgId].rTagQ.ucCount,__LINE__);
                    }
                }
                if (ucIdx >= ucCnt)
                {
                    if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                    {
                        LOG(0,"Cann't find in tagQ omx flush lock, fbg:%d, fbid:%d, tag:0x%llx\n",
                            ucFbgId, ucFbId, _prFbg[ucFbgId].u4DispTag[ucFbId]);
                    }
                    _prFbg[ucFbgId].u4DispTag[ucFbId] = INVALID_DISPTAG;
                    FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
                }
            }
        }

        FBM_MUTEX_UNLOCK(ucFbgId);
    }
#else
    UCHAR ucFbId;
    if(VERIFY_FBG(ucFbgId)==FALSE)
    {
        FBM_MUTEX_LOCK(ucFbgId);
        for (ucFbId=0; ucFbId < FBM_MAX_FB_NS_PER_GROUP; ucFbId++)
        {
            if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
            {
                LOG(0,"u4FbIdx(%d) overflow!!!\n",ucFbId);
                FBM_MUTEX_UNLOCK(ucFbgId);
                return ;
            }
            if ((_prFbg[ucFbgId].aucFbStatus[ucFbId] == FBM_FB_STATUS_LOCK) &&
                (_prFbg[ucFbgId].u4DispTag[ucFbId] == OMX_PENDING_DISPTAG))
            {
                if ((u4FbmCtrlLog&FBM_ENABLE_LOG_OMX) == FBM_ENABLE_LOG_OMX)
                {
                    LOG(1,"omx flush lock, fbg:%d, fbid:%d, tag:0x%llx\n", ucFbgId, ucFbId, _prFbg[ucFbgId].u4DispTag[ucFbId]);
                }
                _prFbg[ucFbgId].u4DispTag[ucFbId]=INVALID_DISPTAG;
                FBM_SetFrameBufferStatus(ucFbgId, ucFbId, FBM_FB_STATUS_EMPTY);
            }
        }

        FBM_MUTEX_UNLOCK(ucFbgId);
    }
#endif


    return;
}

static VOID FBM_UpdataSeqChqQueReadInx(UCHAR ucFbgId,UCHAR ucFbId,UCHAR ucReadIdx)
{
    FBM_PIC_HDR_T* pPicHdr = NULL;
    FBM_SeqChg_T* pSeqChg = NULL;

    if (VERIFY_FBG(ucFbgId))
    {
        return;
    }

    _prFbg[ucFbgId].u4FbgFlag |= _prFbg[ucFbgId].u4SeqChgFlag;

    pPicHdr = FBM_GetFrameBufferPicHdr(ucFbgId, ucFbId);

    if (pPicHdr == NULL)
    {
        return;
    }

    // just printf log to debug
    pSeqChg = _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue;
    if (pPicHdr && pSeqChg && (ucReadIdx < FBM_MAX_FB_NS_PER_GROUP))
    {
        LOG(1,"Notify(%d) ReadIdx (%d) SOC(%d) [Fb(%d) Id(%d) W/H/P(%d-%d-%d)]/[RealChangeFB(%d) W/H(%d-%d) Id(%d) PicSoc(%d)]\n",
            _prFbg[ucFbgId].rSeqChgPendingQ.ucCount,
            ucReadIdx,
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucReadIdx].rPendingSeqHdr.u4PendingSOC,
            pSeqChg[ucReadIdx].ucNewFb,
            pSeqChg[ucReadIdx].ucPicId,
            pSeqChg[ucReadIdx].rPendingSeqHdr.u4SourceWidth,
            pSeqChg[ucReadIdx].rPendingSeqHdr.u4SourceHeight,
            pSeqChg[ucReadIdx].rPendingSeqHdr.u4PicPitch,
            ucFbId,
            pPicHdr->u4SourceWidth,
            pPicHdr->u4SourceHeight,
            pPicHdr->ucPicId,
            pPicHdr->u4PicSoc);

        _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucReadIdx].rPendingSeqHdr.eSeqChqQueStatus = FBM_SEQ_CHG_QUE_STATUS_USING;
    }
    ////////////////////////////////
    ucReadIdx = (ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;

    _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx = ucReadIdx;
    _prFbg[ucFbgId].rSeqChgPendingQ.ucCount--;
    return;

}

//-------------------------------------------------------------------------
/** FBM_ChkSeqChg
 *  Check Seq Chg,this api for nptv seamless and omx path
 *  @param  ucFbgId   ucFbIdx
 *  @return TRUE: happend Seq Chg on Fb,False: no seq chg.
 */
//-------------------------------------------------------------------------
BOOL FBM_ChkSeqChg(UCHAR ucFbgId,UCHAR ucFbId,BOOL bPeek)
{
    BOOL bSeqChg = FALSE;
    UCHAR ucReadIdx = 0;
    FBM_PIC_HDR_T* pPicHdr = NULL;
    FBM_SeqChg_T* pSeqChg = NULL;

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

    if (ucFbId >= FBM_MAX_FB_NS_PER_GROUP)
    {
        LOG(0,"ucFbId(%d) overflow!!!\n",ucFbId);
        return FALSE;
    }

    pPicHdr = FBM_GetFrameBufferPicHdr(ucFbgId, ucFbId);

    if (pPicHdr)
    {
        if ((u4FbmCtrlLog&FBM_ENABLE_LOG_SEQCHG) == FBM_ENABLE_LOG_SEQCHG)
        {
            LOG(2,"FBM_ChkSeqChg (%d-%d) PTS-PicId(0x%llx-%d)\n",ucFbgId,ucFbId,pPicHdr->u4PTS,pPicHdr->ucPicId);
        }
    }
    else
    {
        LOG(0,"Cannot get fb(%d) PicHdr Line(%d)\n",ucFbId,__LINE__);
        return FALSE;
    }

    FBM_MUTEX_LOCK(ucFbgId);


    if (_prFbg[ucFbgId].rSeqChgPendingQ.ucCount > 0)
    {
        pSeqChg = _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue;
        ucReadIdx = _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx;

        if (pSeqChg && (ucReadIdx < FBM_MAX_FB_NS_PER_GROUP))
        {
            if (pPicHdr->u4PicSoc == pSeqChg[ucReadIdx].rPendingSeqHdr.u4PendingSOC)
            {
                if (!bPeek)
                {
                    FBM_UpdataSeqChqQueReadInx(ucFbgId,ucFbId,ucReadIdx);
                }
                bSeqChg = TRUE;
            }
            else
            {
                if (pPicHdr->u4PicSoc > pSeqChg[ucReadIdx].rPendingSeqHdr.u4PendingSOC)
                {
                    UINT8 ucCount = _prFbg[ucFbgId].rSeqChgPendingQ.ucCount;
                    while ((pPicHdr->u4PicSoc > pSeqChg[ucReadIdx].rPendingSeqHdr.u4PendingSOC) &&
                           (ucCount > 1))
                    {
                        ucReadIdx = (ucReadIdx + 1) % FBM_MAX_FB_NS_PER_GROUP;
                        ucCount--;
                        if (!bPeek)
                        {
                            _prFbg[ucFbgId].rSeqChgPendingQ.ucCount--;
                        }
                    }
                    if (pPicHdr->u4PicSoc == pSeqChg[ucReadIdx].rPendingSeqHdr.u4PendingSOC)
                    {
                        //get seqQ
                        if (!bPeek)
                        {
                            FBM_UpdataSeqChqQueReadInx(ucFbgId,ucFbId,ucReadIdx);
                        }
                        bSeqChg = TRUE;
                    }
                    else
                    {
                        //break because of count is ZERO
                        LOG(0,"Err seqQcount(%d) PicSoc/PendingSoc[%d --%d]\n",
                            _prFbg[ucFbgId].rSeqChgPendingQ.ucCount,
                            pPicHdr->u4PicSoc,
                            pSeqChg[ucReadIdx].rPendingSeqHdr.u4PendingSOC);
                    }
                }
            }
        }
    }


    FBM_MUTEX_UNLOCK(ucFbgId);

    return bSeqChg;

}

VOID FbmPutToSeqChgQue(UCHAR ucFbgId, UCHAR ucFbId,FBM_SeqChg_T *pLastSeqChgItem)
{
    UCHAR ucNextSeqChgWriteIdx = FBM_MAX_FB_NS_PER_GROUP;
    FBM_PIC_HDR_T* pPicHdr = NULL;
    FBM_SEQ_HDR_T* pSeqHdr =NULL;

    if (pLastSeqChgItem == NULL)
    {
        // put to seqChg Que
        ucNextSeqChgWriteIdx = (_prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx + _prFbg[ucFbgId].rSeqChgPendingQ.ucCount) % FBM_MAX_FB_NS_PER_GROUP;
        _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].ucNewFb = ucFbId;

        pPicHdr = FBM_GetFrameBufferPicHdr(ucFbgId, ucFbId);
        pSeqHdr = FBM_GetFrameBufferSeqHdr(ucFbgId);

        if (pPicHdr && pSeqHdr)
        {
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].u4PTS = pPicHdr->u4PTS;
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].ucPicId = pPicHdr->ucPicId;

            x_memcpy(&_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].rPendingSeqHdr, pSeqHdr, sizeof(FBM_SEQ_HDR_T));
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].rPendingSeqHdr.eSeqChqQueStatus = FBM_SEQ_CHG_QUE_STATUS_WILLUSE;
            _prFbg[ucFbgId].rSeqChgPendingQ.ucCount++;

            pPicHdr->u4PicSoc = pSeqHdr->u4PendingSOC;

            LOG(1,"Pending(%d) SOC[%d-%d] FBG/FB/Id(%d-%d-%d) Seq W/H/P(%d-%d-%d)\n",
                _prFbg[ucFbgId].rSeqChgPendingQ.ucCount,
                ucNextSeqChgWriteIdx,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].rPendingSeqHdr.u4PendingSOC,
                ucFbgId,ucFbId,pPicHdr->ucPicId,pSeqHdr->u4SourceWidth,pSeqHdr->u4SourceHeight,pSeqHdr->u4PicPitch);
        }
        else
        {
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].u4PTS = FBM_INVALID_PTS;
            LOG(0,"This Fb(%d) have invalid pts\n",ucFbId);
            x_memset(&_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[ucNextSeqChgWriteIdx].rPendingSeqHdr,0x0,sizeof(FBM_SEQ_HDR_T));
            LOG(0,"This Seqhdr invalid \n");
        }
    }
    else
    {
        if (pLastSeqChgItem && (pLastSeqChgItem->rPendingSeqHdr.eSeqChqQueStatus == FBM_SEQ_CHG_QUE_STATUS_WILLUSE))
        {
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].u4PTS = pLastSeqChgItem->u4PTS;
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].ucNewFb = pLastSeqChgItem->ucNewFb;
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].ucPicId = pLastSeqChgItem->ucPicId;
            x_memcpy((void*)&_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr, (void*)&pLastSeqChgItem->rPendingSeqHdr, sizeof(FBM_SEQ_HDR_T));

            _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx = 0;
            _prFbg[ucFbgId].rSeqChgPendingQ.ucCount = 1;

            LOG(1,"After flush,FBG/FB/ID(%d-%d-%d) ReadIdx[%d] W/H(%d-%d) SOC(%d) Status(%d)\n",
                ucFbgId,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].ucNewFb,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].ucPicId,
                _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.u4SourceWidth,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.u4SourceHeight,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.u4PendingSOC,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.eSeqChqQueStatus);

        }
        else
        {
            _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx = 0;
            _prFbg[ucFbgId].rSeqChgPendingQ.ucCount = 0;
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].u4PTS = FBM_INVALID_PTS;
            _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].ucNewFb = FBM_FB_ID_UNKNOWN;

            _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx = 1;

            x_memcpy((void*)&_prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr, (void*)&pLastSeqChgItem->rPendingSeqHdr, sizeof(FBM_SEQ_HDR_T));

            // this part do not need increment(ucCount++)
            // to use FBM_GetFrameBufferSeqHdrByB2R

            LOG(1,"After flush,FBG(%d) ReadIdx[%d] W/H(%d-%d) SOC(%d) Status(%d)\n",
                ucFbgId,
                _prFbg[ucFbgId].rSeqChgPendingQ.ucReadIdx,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.u4SourceWidth,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.u4SourceHeight,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.u4PendingSOC,
                _prFbg[ucFbgId].rSeqChgPendingQ.aucSeqChgQue[0].rPendingSeqHdr.eSeqChqQueStatus);
        }
    }

    return;

}

UINT32 FBM_GetVideoCodecType(UCHAR ucFbgId)
{
    if (VERIFY_FBG(ucFbgId))
    {
        return FBM_VDEC_UNKNOWN;
    }
    return _prFbg[ucFbgId].u4VDecFmt;
}

VOID _FBM_PostProcess_OutputInfo(UCHAR u4FbgId,FBM_SEQ_HDR_T* prFbmSeqHdr,FBM_PIC_POSTPROCESS_OUTPUT_T *pOutParam)
{
    return _VDP_Prescale_OutputInfo(u4FbgId,prFbmSeqHdr,pOutParam);
}

static UINT32 _FBMChkIsGetFBFromDispQ(UCHAR ucFbgId)
{
    UINT32 u4PauseType = FBM_PAUSE_TYPE_UNKOWN;
    UINT32 u4StepCmd = FBM_STEP_CMD_DEFALUT;

    if (ucFbgId >= FBG_MAX_NS)
    {
        LOG(0,"FbgId (%d) exception\n",ucFbgId);
        return FBM_GETFBFROMDISPQ_DEFALUT;
    }
    u4PauseType = _prFbg[ucFbgId].u4PauseType;

    if (u4PauseType == FBM_PAUSE_TYPE_UNKOWN)
    {
        return FBM_GETFBFROMDISPQ_DEFALUT;
    }
    else if (u4PauseType == FBM_PAUSE_TYPE_1)
    {
        u4StepCmd = _prFbg[ucFbgId].u4StepCmd;

        if (FBM_STEP_CMD_DEFALUT == u4StepCmd)
        {
            if (_prFbg[ucFbgId].fgSeqChgPause)
            {
                return FBM_GETFBFROMDISPQ_FORCE_PAUSE;
            }
            else
            {
                return FBM_GETFBFROMDISPQ_DEFALUT;
            }
        }
        else
        {
            _prFbg[ucFbgId].fgSeqChgPause = FALSE;

            if (_prFbg[ucFbgId].u4StepCnt < _prFbg[ucFbgId].u4StepThreshold)
            {
                LOG(1,"Step cur cnt(%d) Threshold(%d)\n",_prFbg[ucFbgId].u4StepCnt,_prFbg[ucFbgId].u4StepThreshold);
                return FBM_GETFBFROMDISPQ_STEP;
            }
            else
            {
                LOG(1,"Step done Cnt(%d)\n",_prFbg[ucFbgId].u4StepCnt);
                return FBM_GETFBFROMDISPQ_STEP_DONE;
            }

        }
    }
    else if (u4PauseType == FBM_PAUSE_TYPE_2)
    {
        u4StepCmd = _prFbg[ucFbgId].u4StepCmd;

        if (FBM_STEP_CMD_DEFALUT == u4StepCmd)
        {
            if ( (_prFbg[ucFbgId].fgSeqChgPause) && (_prFbg[ucFbgId].rSeqHdr.u4PendingSOC > 1) )
            {
                return FBM_GETFBFROMDISPQ_FORCE_PAUSE;
            }
            else
            {
                return FBM_GETFBFROMDISPQ_DEFALUT;
            }
        }
        else
        {
            _prFbg[ucFbgId].fgSeqChgPause = FALSE;

            if (_prFbg[ucFbgId].u4StepCnt < _prFbg[ucFbgId].u4StepThreshold)
            {
                LOG(1,"Step cur cnt(%d) Threshold(%d)\n",_prFbg[ucFbgId].u4StepCnt,_prFbg[ucFbgId].u4StepThreshold);
                return FBM_GETFBFROMDISPQ_STEP;
            }
            else
            {
                LOG(1,"Step done Cnt(%d)\n",_prFbg[ucFbgId].u4StepCnt);
                return FBM_GETFBFROMDISPQ_STEP_DONE;
            }

        }


    }
    else if (u4PauseType == FBM_PAUSE_TYPE_3)
    {
        u4StepCmd = _prFbg[ucFbgId].u4StepCmd;

        if (FBM_STEP_CMD_DEFALUT == u4StepCmd)
        {
            return FBM_GETFBFROMDISPQ_FORCE_PAUSE;

        }
        else
        {
            if (_prFbg[ucFbgId].u4StepCnt < _prFbg[ucFbgId].u4StepThreshold)
            {
                LOG(1,"Step cur cnt(%d) Threshold(%d)\n",_prFbg[ucFbgId].u4StepCnt,_prFbg[ucFbgId].u4StepThreshold);
                return FBM_GETFBFROMDISPQ_STEP;
            }
            else
            {
                LOG(1,"Step done Cnt(%d)\n",_prFbg[ucFbgId].u4StepCnt);
                return FBM_GETFBFROMDISPQ_STEP_DONE;
            }

        }

    }
    else
    {
        return FBM_GETFBFROMDISPQ_DEFALUT;
    }

    return FBM_GETFBFROMDISPQ_DEFALUT;

}

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

    _prFbg[ucFbgId].u4StepCnt++;

    LOG(1,"Update step Cnt(%d)\n",_prFbg[ucFbgId].u4StepCnt);
    return ;
}
