📄 pg_api.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2005-2006 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file pg_api.cpp
*
* $Revision: 1.7 $
*
* declarations of external API for PG module
*
*/
#include "vcitypes.h"
#include "osapi.h"
#include <stdlib.h>
#include "pg_defs.h"
#include "pg_parse.h"
#include "pg_render.h"
#include "pg_graphics.h"
#include "pg_api.h"
#include "utility.h"
#define DEBUG_PG_API DBG_ERROR
#define DBG_ON(x) (DEBUG_PG_API >= x)
#define PG_HANDLE_VALUE 0x21098765 /* arbitrary, but enforced */
/* structures used throughout the module */
PGINFO PGInfo;
PGSTATS PGStats;
OBJECT_DEFINITION_SEGMENT PGObjList[PG_MAX_ODS]; /* our array of Objects (images) */
PALETTE PGPalettes[PG_MAX_PALETTES];
/* local prototypes */
static PG_STATUS PGScanForStartCode(BYTE *Buffer, ULONG Size, ULONG *Offset);
static PG_STATUS PGReadPESHeader(BYTE *PESStart);
static PG_STATUS PGWaitForSpaceAvail(ULONG Size);
static PG_STATUS PGAssemblePesHeader(BYTE *Buffer, ULONG Size, USHORT *ReadBytes);
static PG_STATUS PGAssembleSegmentData(BYTE *Buffer, ULONG Size, USHORT *ReadBytes);
static PG_STATUS PGAddParseMessage(ULONG BufferStart, ULONG BufferLength, ULONG DTS, ULONG PTS, ULONG Flags, BYTE MultiPES);
static void PGSendEmptyMessageToStream(cStream *Stream);
static void PGClearAddDataVars();
/**
* PGCreate - create semaphores and threads, get everything ready for Run
*
* @param PG_HANDLE handle - handle to the PG module
* @param screen_width -- width of primary surface
* @param screen_height -- height of primary surface
* @param dfb -- handle to directfb
* @param sfc -- handle to primary surface for pg/textst
* @param disp_layer -- handle to presentation display layer
*
* @return PG_STATUS
*/
PG_STATUS PGCreate(PG_HANDLE *handle, int screen_width, int screen_height,
IDirectFB *dfb, IDirectFBDisplayLayer *disp_layer)
{
char * string = getenv("player_pg_heap_size");
uint32 pg_pool_size = 0;
DBGPRINT(DBG_ON(DBG_TRACE), ("--PGCreate\n"));
if ( (dfb == NULL) || (disp_layer == NULL) )
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: NULL pointer\n"));
return (PG_STATUS_ERROR);
}
/* our entry point, we get called here and setup our state */
memset(&PGInfo, 0, sizeof(PGInfo));
memset(PGObjList, 0, PG_MAX_ODS * sizeof(OBJECT_DEFINITION_SEGMENT));
memset(PGPalettes, 0, PG_MAX_PALETTES * sizeof(PALETTE));
memset(&PGStats, 0, sizeof(PGSTATS));
PGInfo.CurrentState = PG_STATE_UNINITIALIZED;
/* set dfb info */
PGInfo.DFBInfo.pDFBHandle = dfb;
PGInfo.DFBInfo.DispLayer = disp_layer;
PGInfo.DFBInfo.ScreenWidth = screen_width;
PGInfo.DFBInfo.ScreenHeight = screen_height;
if ( getenv( "HDMV_GRFX_HALF_WIDTH" ) )
{
PGInfo.RLEHalfWidth = 1;
DbgPrint(("(*) PG Half Width Enabled\n"));
}
else
{
PGInfo.RLEHalfWidth = 0;
}
if ( getenv( "HDMV_GRFX_FRAME_DROPPING" ) )
{
PGInfo.FrameDropping = 1;
DbgPrint(("(*) PG Frame Dropping Enabled\n"));
}
else
{
PGInfo.FrameDropping = 0;
}
if ( getenv( "HDMV_GRFX_PROFILE" ) )
{
PGStats.Profiling = 1;
DbgPrint(("(*) PG Profiling Enabled\n"));
}
else
{
PGStats.Profiling = 0;
}
/* create our palettes with default colors */
if (PG_STATUS_SUCCESS != PGGraphicsCreateAllPalettes())
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PG: Failed to create all palettes\n"));
return PG_STATUS_ERROR;
}
/* turn pg display on */
if (PGInfo.DFBInfo.DispLayer->SetLevel(PGInfo.DFBInfo.DispLayer, PG_DISPLAY_LEVEL) != DFB_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to set the level to 1\n"));
return PG_STATUS_ERROR;
}
/* get the primary surface for the PG diplay layer */
if (PGInfo.DFBInfo.DispLayer->GetSurface(PGInfo.DFBInfo.DispLayer, &PGInfo.DFBInfo.PrimarySurface) != DFB_OK)
{
DbgPrint(("PGCreate: Failed to get surface\n"));
goto errout;
}
/* set pg preallocated surface pool size */
if (string)
{
/* user defined */
pg_pool_size = strtoul(string, NULL, 10)*1024*1024;
}
else
{
/* default to 16MB */
pg_pool_size = 16*1024*1024;
}
/* Create surface manager */
if (PGInfo.DFBInfo.pDFBHandle->CreateSurfaceManager(PGInfo.DFBInfo.pDFBHandle, pg_pool_size,
1024, DSMT_SURFACEMANAGER_BUDDY, &PGInfo.DFBInfo.SurfaceManager) != DFB_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to create surface manager\n"));
goto errout;
}
/* allocate PGParseBuffer */
PGInfo.PGParseBuffer = (BYTE *)OS_MemAlloc(SIZE_PG_CODED_DATA_BUFFER);
if (PGInfo.PGParseBuffer == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("\n PGCreate(): Could not alloc PGParseBuffer\n\n"));
goto errout;
}
/* semaphore access to the Render task */
PGInfo.RenderLock = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);
if (0 == PGInfo.RenderLock)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to create RenderLock semaphore\n"));
goto errout;
}
/* semaphore access to the Render task */
PGInfo.BlitLock = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);
if (0 == PGInfo.BlitLock)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to create BlitLock semaphore\n"));
goto errout;
}
/* semaphore access to state changes (pgrun pgstop pgadddata) */
PGInfo.StateLock = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);
if (0 == PGInfo.StateLock)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to create StateLock semaphore\n"));
goto errout;
}
/* the parse wait semaphore, NOTE created EMPTY */
PGInfo.ParseWait.WaitSem = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
if (0 == PGInfo.ParseWait.WaitSem)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to create Parsewait semaphore\n"));
goto errout;
}
/* the render wait semaphore, NOTE created EMPTY */
PGInfo.RenderWait.WaitSem = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
if (0 == PGInfo.RenderWait.WaitSem)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGCreate: Failed to create Renderwait semaphore\n"));
goto errout;
}
/* create pg message queue*/
PGInfo.PGParseQ = new cStream;
PGInfo.PGParseQPool = OS_MemAlloc(sizeof(PG_PARSE_MSG) * PG_PARSE_Q_DEPTH);
if ((NULL == PGInfo.PGParseQ) || (NULL == PGInfo.PGParseQPool))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Unable to create PG Parse Q!\n"));
goto errout;
}
else
{
PGInfo.PGParseQ->Initialize(PGInfo.PGParseQPool, PG_PARSE_Q_DEPTH, sizeof(PG_PARSE_MSG), "PG_PARSE_Q");
}
/* create pgparse task */
PGInfo.PGParseTask = OS_TaskSpawnParam("PG Parse Task", PG_PARSE_PRIORITY,
PG_PARSE_STACK_SIZE, PGParse, NULL, NULL);
if (OS_FAILURE == PGInfo.PGParseTask)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("\nUnable to create PG Parse thread!\n"));
goto errout;
}
/* create the user selection timer */
if (OS_OK != OS_TimerCreate(&PGInfo.PGFlipTimer, PGGraphicsFlip))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGCreate(): Unable to create the Timer User Selection\n"));
goto errout;
}
/* we are now initialized */
PGInfo.CurrentState = PG_STATE_INITIALIZED;
PGInfo.ShowGraphics = PG_HIDE_GRAPHICS;
/* allocate a handle here? or just give anything back */
*handle = (PVOID)PG_HANDLE_VALUE;
return PG_STATUS_SUCCESS;
errout:
/* free everything and return an error */
if (PGInfo.PGFlipTimer != 0)
{
OS_TimerDelete(PGInfo.PGFlipTimer);
PGInfo.PGFlipTimer = 0;
}
if (PGInfo.PGParseTask)
{
OS_TaskDelete(PGInfo.PGParseTask);
PGInfo.PGParseTask = 0;
}
if (PGInfo.PGParseQ)
{
delete PGInfo.PGParseQ;
PGInfo.PGParseQ = NULL;
}
if (PGInfo.PGParseQPool)
{
OS_MemFree(PGInfo.PGParseQPool);
PGInfo.PGParseQPool = NULL;
}
if (PGInfo.RenderLock)
{
OS_SemDelete(PGInfo.RenderLock);
PGInfo.RenderLock = 0;
}
if (PGInfo.BlitLock)
{
OS_SemDelete(PGInfo.BlitLock);
PGInfo.BlitLock = 0;
}
if (PGInfo.StateLock)
{
OS_SemDelete(PGInfo.StateLock);
PGInfo.StateLock = 0;
}
if (PGInfo.ParseWait.WaitSem)
{
OS_SemDelete(PGInfo.ParseWait.WaitSem);
PGInfo.ParseWait.WaitSem = 0;
}
if (PGInfo.RenderWait.WaitSem)
{
OS_SemDelete(PGInfo.RenderWait.WaitSem);
PGInfo.RenderWait.WaitSem = 0;
}
if (PGInfo.PGParseBuffer != NULL)
{
OS_MemFree(PGInfo.PGParseBuffer);
PGInfo.PGParseBuffer = NULL;
}
/* release dfb surface */
if (PGInfo.DFBInfo.PrimarySurface != NULL)
{
PGInfo.DFBInfo.PrimarySurface->Release(PGInfo.DFBInfo.PrimarySurface);
}
/* release surface manager */
if (PGInfo.DFBInfo.SurfaceManager != NULL)
{
PGInfo.DFBInfo.SurfaceManager->Release(PGInfo.DFBInfo.SurfaceManager);
}
return PG_STATUS_ERROR;
}
/**
* PGDelete - stop threads and free all memory
*
* @param PG_HANDLE handle - handle to the PG module
*
* @return PG_STATUS
*/
PG_STATUS PGDelete(PG_HANDLE handle)
{
if (handle != (PVOID)PG_HANDLE_VALUE)
{
return PG_STATUS_INVALID_HANDLE;
}
DBGPRINT(DBG_ON(DBG_TRACE), ("--PGDelete()\n"));
/* must be in the stopped or initialized state to shutdown */
if ((PG_STATE_STOPPED == PGInfo.CurrentState) || (PG_STATE_INITIALIZED == PGInfo.CurrentState))
{
/* set the exit flag for the parser and renderer */
PGInfo.QuitFlags = PG_FLAGS_EXIT;
/* que an empty message to render and parse */
PGSendEmptyMessageToStream(PGInfo.PGParseQ);
/* wait for tasks to quit */
OS_TaskJoin(PGInfo.PGParseTask);
/* turn pg display off */
PGGraphicsDeleteAllPalettes();
PGGraphicsClearBuffer(NULL, 0);
PGInfo.DFBInfo.DispLayer->SetLevel(PGInfo.DFBInfo.DispLayer, -1);
PGGraphicsFlip();
/* destroy all threads and cleanup memory */
if (PGInfo.PGParseTask)
{
OS_TaskDelete(PGInfo.PGParseTask);
PGInfo.PGParseTask = 0;
}
if (PGInfo.PGParseQ)
{
PGInfo.PGParseQ->Destroy();
delete PGInfo.PGParseQ;
PGInfo.PGParseQ = NULL;
}
if (PGInfo.PGParseQPool)
{
OS_MemFree(PGInfo.PGParseQPool);
PGInfo.PGParseQPool = NULL;
}
if (PGInfo.RenderLock)
{
OS_SemDelete(PGInfo.RenderLock);
PGInfo.RenderLock = 0;
}
if (PGInfo.BlitLock)
{
OS_SemDelete(PGInfo.BlitLock);
PGInfo.BlitLock = 0;
}
if (PGInfo.StateLock)
{
OS_SemDelete(PGInfo.StateLock);
PGInfo.StateLock = 0;
}
if (PGInfo.ParseWait.WaitSem)
{
OS_SemDelete(PGInfo.ParseWait.WaitSem);
PGInfo.ParseWait.WaitSem = 0;
}
if (PGInfo.RenderWait.WaitSem)
{
OS_SemDelete(PGInfo.RenderWait.WaitSem);
PGInfo.RenderWait.WaitSem = 0;
}
if (PGInfo.PGParseBuffer != NULL)
{
OS_MemFree(PGInfo.PGParseBuffer);
PGInfo.PGParseBuffer = NULL;
}
if (PGInfo.PGFlipTimer != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -