Files
MAX_CARLINK_A270S/MXC_A27-PCB4.5-270S/lib/hx170dec/src/h264_pp_pipeline.c
2025-01-21 16:49:37 +08:00

428 lines
14 KiB
C

/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced --
-- on all copies and should not be removed. --
-- --
--------------------------------------------------------------------------------
--
-- Description : H264 decoder and PP pipeline support
--
------------------------------------------------------------------------------
--
-- Version control information, please leave untouched.
--
-- $RCSfile: h264_pp_pipeline.c,v $
-- $Revision: 1.14 $
-- $Date: 2010/03/01 13:19:08 $
--
------------------------------------------------------------------------------*/
#include "basetype.h"
#include "h264_pp_pipeline.h"
#include "h264_pp_multibuffer.h"
#include "h264hwd_container.h"
#include "h264hwd_debug.h"
#include "h264hwd_util.h"
#ifndef TRACE_PP_CTRL
#define TRACE_PP_CTRL(...) do{}while(0)
#else
#undef TRACE_PP_CTRL
#define TRACE_PP_CTRL(...) printf(__VA_ARGS__)
#endif
/*------------------------------------------------------------------------------
Function name : h264RegisterPP
Description :
Return type : i32
Argument : const void * decInst
Argument : const void *ppInst
Argument : (*PPRun)(const void *)
Argument : void (*PPEndCallback)(const void *)
------------------------------------------------------------------------------*/
i32 h264RegisterPP(const void *decInst, const void *ppInst,
void (*PPDecStart) (const void *, const DecPpInterface *),
void (*PPDecWaitEnd) (const void *),
void (*PPConfigQuery) (const void *, DecPpQuery *),
void (*PPDisplayIndex) (const void *, u32))
{
decContainer_t *pDecCont;
pDecCont = (decContainer_t *) decInst;
if(decInst == NULL || pDecCont->pp.ppInstance != NULL ||
ppInst == NULL || PPDecStart == NULL || PPDecWaitEnd == NULL
|| PPConfigQuery == NULL)
{
TRACE_PP_CTRL("h264RegisterPP: Invalid parameter\n");
return -1;
}
if(pDecCont->asicRunning)
{
TRACE_PP_CTRL("h264RegisterPP: Illegal action, asicRunning\n");
return -2;
}
pDecCont->pp.ppInstance = ppInst;
pDecCont->pp.PPConfigQuery = PPConfigQuery;
pDecCont->pp.PPDecStart = PPDecStart;
pDecCont->pp.PPDecWaitEnd = PPDecWaitEnd;
pDecCont->pp.PPNextDisplayId = PPDisplayIndex;
pDecCont->pp.decPpIf.ppStatus = DECPP_IDLE;
pDecCont->pp.ppInfo.multiBuffer = 0;
h264PpMultiInit(pDecCont, 0);
pDecCont->storage.ppUsed = 1;
TRACE_PP_CTRL("h264RegisterPP: Connected to PP instance 0x%08x\n",
(size_t) ppInst);
return 0;
}
/*------------------------------------------------------------------------------
Function name : h264UnregisterPP
Description :
Return type : i32
Argument : const void * decInst
Argument : const void *ppInst
------------------------------------------------------------------------------*/
i32 h264UnregisterPP(const void *decInst, const void *ppInst)
{
decContainer_t *pDecCont;
pDecCont = (decContainer_t *) decInst;
ASSERT(decInst != NULL && ppInst == pDecCont->pp.ppInstance);
if(ppInst != pDecCont->pp.ppInstance)
{
TRACE_PP_CTRL("h264UnregisterPP: Invalid parameter\n");
return -1;
}
if(pDecCont->asicRunning)
{
TRACE_PP_CTRL("h264UnregisterPP: Illegal action, asicRunning\n");
return -2;
}
pDecCont->pp.ppInstance = NULL;
pDecCont->pp.PPConfigQuery = NULL;
pDecCont->pp.PPDecStart = NULL;
pDecCont->pp.PPDecWaitEnd = NULL;
TRACE_PP_CTRL("h264UnregisterPP: Disconnected from PP instance 0x%08x\n",
(size_t) ppInst);
return 0;
}
/*------------------------------------------------------------------------------
Function name : h264PreparePpRun
Description :
Return type : void
Argument : decContainer_t * pDecCont
------------------------------------------------------------------------------*/
void h264PreparePpRun(decContainer_t * pDecCont)
{
const storage_t *pStorage = &pDecCont->storage;
DecPpInterface *decPpIf = &pDecCont->pp.decPpIf;
const dpbStorage_t *dpb = pStorage->dpb;
/* PP not connected or still running (not waited when first field of frame
* finished */
if(pDecCont->pp.ppInstance == NULL ||
decPpIf->ppStatus == DECPP_PIC_NOT_FINISHED)
{
return;
}
if(dpb->noReordering && !dpb->numOut)
{
TRACE_PP_CTRL
("h264PreparePpRun: No reordering and no output => PP no run\n");
/* decoder could create fake pictures in DPB, which will never go to output.
* this is the case when new access unit detetcted but no valid slice decoded.
*/
return;
}
if(pDecCont->pp.ppInfo.multiBuffer == 0) /* legacy single buffer mode */
{
/* in some situations, like field decoding,
* the dpb->numOut is not reset, but, dpb->numOut == dpb->outIndex */
if(dpb->numOut != 0) /* we have output */
{
TRACE_PP_CTRL
("h264PreparePpRun: output picture => PP could run!\n");
if(dpb->outBuf[dpb->outIndexR].data == pStorage->currImage->data)
{
/* we could have pipeline */
TRACE_PP_CTRL("h264PreparePpRun: decode == output\n");
if(pStorage->activeSps->frameMbsOnlyFlag == 0 &&
pStorage->secondField)
{
TRACE_PP_CTRL
("h264PreparePpRun: first field only! Do not run PP, yet!\n");
return;
}
if(pStorage->currImage->picStruct != FRAME)
{
u32 opposit_field = pStorage->currImage->picStruct ^ 1;
if(dpb->currentOut->status[opposit_field] != EMPTY)
{
decPpIf->usePipeline = 0;
TRACE_PP_CTRL
("h264PreparePpRun: second field of frame! Pipeline cannot be used!\n");
}
}
else if(!pStorage->activeSps->mbAdaptiveFrameFieldFlag)
{
decPpIf->usePipeline =
pDecCont->pp.ppInfo.pipelineAccepted & 1;
}
else
decPpIf->usePipeline = 0;
if(decPpIf->usePipeline)
{
TRACE_PP_CTRL
("h264PreparePpRun: pipeline=ON => PP will be running\n");
decPpIf->ppStatus = DECPP_RUNNING;
if(!pStorage->prevNalUnit->nalRefIdc)
{
pDecCont->asicBuff->disableOutWriting = 1;
TRACE_PP_CTRL
("h264PreparePpRun: Not reference => Disable decoder output writing\n");
}
}
else
{
TRACE_PP_CTRL
("h264PreparePpRun: pipeline=OFF => PP has to run after DEC\n");
}
}
else
{
decPpIf->ppStatus = DECPP_RUNNING;
decPpIf->usePipeline = 0;
TRACE_PP_CTRL
("h264PreparePpRun: decode != output => pipeline=OFF => PP run in parallel\n");
}
}
else
{
TRACE_PP_CTRL
("h264PreparePpRun: no output picture => PP no run!\n");
}
return;
}
/* multibuffer mode */
TRACE_PP_CTRL("h264PreparePpRun: MULTIBUFFER!\n");
if(pDecCont->pp.queuedPicToPp == NULL &&
pStorage->activeSps->frameMbsOnlyFlag == 0 && pStorage->secondField)
{
TRACE_PP_CTRL
("h264PreparePpRun: no queued picture and first field only! Do not run PP, yet!\n");
return;
}
if(pDecCont->pp.queuedPicToPp == NULL &&
pStorage->currentMarked == HANTRO_FALSE)
{
TRACE_PP_CTRL
("h264PreparePpRun: no queued picture and current pic NOT for display! Do not run PP!\n");
return;
}
if(pStorage->currImage->picStruct != FRAME)
{
TRACE_PP_CTRL("h264PreparePpRun: 2 Fields! Pipeline cannot be used!\n");
/* we shall not have EMPTY output marked for display, missing fields are acceptable */
ASSERT((pDecCont->pp.queuedPicToPp != NULL) ||
(dpb->currentOut->status[0] != EMPTY) ||
(dpb->currentOut->status[1] != EMPTY));
decPpIf->usePipeline = 0;
}
else if(!pStorage->activeSps->mbAdaptiveFrameFieldFlag)
{
decPpIf->usePipeline = pDecCont->pp.ppInfo.pipelineAccepted & 1;
}
else
decPpIf->usePipeline = 0;
if(decPpIf->usePipeline)
{
decPpIf->ppStatus = DECPP_RUNNING;
TRACE_PP_CTRL
("h264PreparePpRun: pipeline=ON => PP will be running\n");
}
else
{
if(pDecCont->pp.queuedPicToPp != NULL)
{
decPpIf->ppStatus = DECPP_RUNNING;
TRACE_PP_CTRL
("h264PreparePpRun: pipeline=OFF, queued picture => PP run in parallel\n");
}
else
{
TRACE_PP_CTRL
("h264PreparePpRun: pipeline=OFF, no queued picture => PP no run\n");
/* do not process pictures added to DPB but not intended for display */
if(dpb->noReordering ||
dpb->currentOut->toBeDisplayed == HANTRO_TRUE)
{
if(!pStorage->secondField) /* do not queue first field */
{
pDecCont->pp.queuedPicToPp = dpb->currentOut->data;
}
}
}
}
}
/*------------------------------------------------------------------------------
Function name : h264PpMultiAddPic
Description : Add a new picture to the PP processed table (frist free place).
Return the tabel position where added.
Return type : u32
Argument : decContainer_t * pDecCont
Argument : const DWLLinearMem_t * data
------------------------------------------------------------------------------*/
u32 h264PpMultiAddPic(decContainer_t * pDecCont, const DWLLinearMem_t * data)
{
u32 nextFreeId;
ASSERT(pDecCont->pp.ppInfo.multiBuffer != 0);
for(nextFreeId = 0; nextFreeId <= pDecCont->pp.multiMaxId; nextFreeId++)
{
if(pDecCont->pp.sentPicToPp[nextFreeId] == NULL)
{
break;
}
}
ASSERT(nextFreeId <= pDecCont->pp.multiMaxId);
if(nextFreeId <= pDecCont->pp.multiMaxId)
pDecCont->pp.sentPicToPp[nextFreeId] = data;
return nextFreeId;
}
/*------------------------------------------------------------------------------
Function name : h264PpMultiRemovePic
Description : Reomove a picture form the PP processed list.
Return the position which was emptied.
Return type : u32
Argument : decContainer_t * pDecCont
Argument : const DWLLinearMem_t * data
------------------------------------------------------------------------------*/
u32 h264PpMultiRemovePic(decContainer_t * pDecCont, const DWLLinearMem_t * data)
{
u32 picId;
ASSERT(pDecCont->pp.ppInfo.multiBuffer != 0);
for(picId = 0; picId <= pDecCont->pp.multiMaxId; picId++)
{
if(pDecCont->pp.sentPicToPp[picId] == data)
{
break;
}
}
ASSERT(picId <= pDecCont->pp.multiMaxId);
if(picId <= pDecCont->pp.multiMaxId)
pDecCont->pp.sentPicToPp[picId] = NULL;
return picId;
}
/*------------------------------------------------------------------------------
Function name : h264PpMultiFindPic
Description : Find a picture in the PP processed list. If found, return
the position. If not found, return an value bigger than
the max.
Return type : u32
Argument : decContainer_t * pDecCont
Argument : const DWLLinearMem_t * data
------------------------------------------------------------------------------*/
u32 h264PpMultiFindPic(decContainer_t * pDecCont, const DWLLinearMem_t * data)
{
u32 picId;
ASSERT(pDecCont->pp.ppInfo.multiBuffer != 0);
for(picId = 0; picId <= pDecCont->pp.multiMaxId; picId++)
{
if(pDecCont->pp.sentPicToPp[picId] == data)
{
break;
}
}
return picId;
}
/*------------------------------------------------------------------------------
Function name : h264PpMultiInit
Description : Initialize the PP processed list.
Return type : void
Argument : decContainer_t * pDecCont
Argument : u32 maxBuffId - max ID in use (buffs = (maxBuffId + 1))
------------------------------------------------------------------------------*/
void h264PpMultiInit(decContainer_t * pDecCont, u32 maxBuffId)
{
u32 i;
const u32 buffs =
sizeof(pDecCont->pp.sentPicToPp) / sizeof(*pDecCont->pp.sentPicToPp);
ASSERT(maxBuffId < buffs);
pDecCont->pp.queuedPicToPp = NULL;
pDecCont->pp.multiMaxId = maxBuffId;
for(i = 0; i < buffs; i++)
{
pDecCont->pp.sentPicToPp[i] = NULL;
}
}
u32 h264UseDisplaySmoothing(const void *decInst)
{
decContainer_t *pDecCont = (decContainer_t*)decInst;
if (pDecCont->storage.useSmoothing)
return HANTRO_TRUE;
else
return HANTRO_FALSE;
}