📄 decoder.c
字号:
/**************************************************************************
* Name : decoder.c
* Title : M24VA video decode acceleration API
* Author : Dave Bartlett
* Created : 23/04/02
*
* Copyright : 2003 by Imagination Technologies. All rights reserved.
* : No part of this software, either material or conceptual
* : may be copied or distributed, transmitted, transcribed,
* : stored in a retrieval system or translated into any
* : human or computer language in any form by any means,
* : electronic, mechanical, manual or other-wise, or
* : disclosed to third parties without the express written
* : permission of Imagination Technologies Limited, Unit 8,
* : HomePark Industrial Estate, King's Langley, Hertfordshire,
* : WD4 8LZ, U.K.
*
* Description : M24VA video decode acceleration API (Marathon)
*
* Platform :
*
Version : $Revision: 1.38 $
Modifications :
$Log: decoder.c $
--- Revision Logs Removed ---
--- Revision Logs Removed ---
--- Revision Logs Removed ---
*/
/***************************************************** Configuration options */
#ifdef DEBUG
#define DEBUG_MODE
#endif
/*****************************************************************************/
#include <windows.h>
#include <ddraw.h>
#include <Pkfuncs.h>
#include <drvescape.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "img_defs.h"
#include "services.h"
#include "syscommon.h"
/********************************************************* IMG include files */
#include "pvrapi.h"
#include "pvrvadd.h"
#include "m24vahw.h"
#include "decdisp.h"
#include "mbx13ddef.h"
#include <ceddk.h>
/*****************************************************************************/
#ifdef DEBUG_MODE
#define M24VA_PDUMP(arg) if(g_eScriptMode != M24VA_NoScript) M24VA_SimScriptLog arg
#define DEBUG_MODE_ONLY(x) x
#else
#define M24VA_PDUMP(arg)
#define DEBUG_MODE_ONLY(x)
#endif
#define M24VA_READREG(reg) M24VA_ReadReg(reg)
#define M24VA_WRITEREG(reg,val,suf) M24VA_WriteReg(reg, val)
#define M24VA_FRAMEFREE(p) FrameFree(p)
#define M24VA_FRAMEALLOCATE(w,h,f) FrameAllocate(w, h, f)
#define SP_WRITE_MASK (2*1024/4 - 1);
/********************************************************** Internal defines */
typedef enum
{ M24VA_NoScript, /* Do not generate script */
M24VA_LogAccesses, /* Use h/w log, in script, accesses */
} SCRIPT_MODE;
typedef struct _M24VA_SP_
{
IMG_UINT32 *pui32SlavePortLinAddr; /* Pointer to SP */
IMG_UINT32 iu32SPFree; /* Free space in SP fifo's*/
IMG_UINT32 *pSPBufferBase; /* Slave Port Write Buffer Base */
IMG_UINT32 *pSPBuffer; /* Next usable location in Buffer */
IMG_UINT32 *pSPFlushThreshold;
IMG_UINT32 ui32SPAddOn;
#ifdef DEBUG_MODE
IMG_UINT32 ui32AccessCount;
IMG_UINT32 ui32Polls;
IMG_UINT32 ui32Trys;
IMG_UINT32 ui32Overflows;
#endif
} M24VA_SP;
/********************************************* M24VA state control structure */
/* The driver buffers up cmds and residual data internally before writing to the hardware.
* The size of these buffer must be less than the size of the hardware FIFOs for the
* algorithm to work. The sizes are in 32 bit wrords.
*/
#define M24VA_SW_CMD_FIFO_SIZE (0x1f)
#define M24VA_SW_IDCT_FIFO_SIZE (0x3f)
#define M24VA_SW_IZZ_FIFO_SIZE (0x1f)
typedef struct _M24VA_STATE_
{
IMG_UINT32 *pui32DeviceResource;
IMG_UINT32 ui32CurrentProcessID;
M24VA_SP sIDCTSlavePort;
M24VA_SP sCMDSlavePort;
IMG_BOOL bHardwareInUse;
HDC hdcDriver;
IMG_HANDLE hServices;
PVRSRV_DEV_DATA sM24VADevData;
PVRSRV_HW_INFO sHWInfo;
IMG_UINT32 aui32CMDWriteBuffer[M24VA_SW_CMD_FIFO_SIZE*2];
M24VA_SP sIZZSlavePort;
IMG_UINT32 aui32IZZWriteBuffer[M24VA_SW_IZZ_FIFO_SIZE*2];
IMG_UINT32 *pRegisters;
/* Frame dimensions's */
IMG_UINT32 ui32Width;
IMG_UINT32 ui32Height;
IMG_BOOL bDummyImageWriteSent;
IMG_BOOL bFCInProgress;
#ifdef DEBUG_MODE
/* Access stats */
IMG_UINT32 ui32RegAccessCount;
IMG_UINT32 ui32FlushCount;
IMG_UINT32 ui32InterruptPolls;
IMG_UINT32 ui32InterruptTrys;
IMG_UINT32 ui32InterruptOverflows;
#endif
} M24VA_STATE;
/************************************************* Internal global variables */
static M24VA_STATE g_M24VAState = { FALSE };
static SCRIPT_MODE g_eScriptMode = M24VA_NoScript;
extern PVRSRV_SYNC_INFO *gpsLastSyncObject;
#ifdef DEBUG_MODE
/* Log file details */
static char g_szLogFileName[1024];
static FILE* g_pfLogFile;
#endif
/********************************************** Internal function prototypes */
static DWORD M24VA_ReadReg(DWORD dwAddr);
static void M24VA_WriteReg(DWORD dwAddr, DWORD dwData);
static M24VAError FrameFree(PINT_SM_HANDLE pSurface);
static PINT_SM_HANDLE FrameAllocate(DWORD dwWidth, DWORD dwHeight,
M24VA_SURF_FORMAT eFormat);
void UpdateSPFreeCounters();
static void AcquireMPEG();
static void ReleaseMPEG();
/*********************** Internal inline functions, slaveport buffered writes */
/*****************************************************************************
FUNCTION : AcquireMPEG
PURPOSE : Acquire MPEG mutex to prevent power state transitions.
PARAMETERS :
RETURNS : nothing
Notes :
*****************************************************************************/
static void AcquireMPEG()
{
IMG_UINT32 ui32Result;
IMG_UINT32 ui32Count = 0;
IMG_UINT32 ui32Ms = 0;
while (ui32Result = InterlockedTestExchange(g_M24VAState.pui32DeviceResource, 0, g_M24VAState.ui32CurrentProcessID))
{
Sleep(ui32Ms);
/*
we have to handle thread starvation and block this thread
if we fail to acquire the lock after some number of tries
*/
if(ui32Count++ == 100)
{
ui32Ms = 1;
}
}
/* Verify that mutex has been acquired. */
assert(ui32Result == 0);
#ifdef DEBUG
if(ui32Result != 0)
{
OutputDebugString(TEXT("HostAcquireMutex: failed\n"));
}
#endif
}
/*****************************************************************************
FUNCTION : ReleaseMPEG
PURPOSE : Release MPEG mutex to allow power state transitions.
PARAMETERS :
RETURNS : nothing
Notes :
*****************************************************************************/
static void ReleaseMPEG()
{
PVRSRV_ERROR eError = PVRSRV_OK;
if (*g_M24VAState.pui32DeviceResource == g_M24VAState.ui32CurrentProcessID)
{
*g_M24VAState.pui32DeviceResource = 0;
}
#ifdef DEBUG
else
{
/* Process does not have permission to release mutex. */
OutputDebugString(TEXT("HostReleaseMutex: Mutex is not locked with expected value\n"));
assert(0);
}
#endif
}
/*****************************************************************************
FUNCTION : M24VA_SPBufferFlush
PURPOSE : Flush slave port
PARAMETERS :
RETURNS : nothing
Notes :
*****************************************************************************/
M24VAError M24VA_SPBufferFlush(M24VA_SP *psSlavePort)
{
#ifndef INIFINTELY_FAST_HW
int iPolls, iTrys;
IMG_UINT32 ui32DataToWrite;
M24VAError eRtn = M24VAError_OK;
/************************************* Ensure space in slave port FIFO's */
assert((psSlavePort->pSPBufferBase != NULL));
/* Verify that pSPBuffer points to a legal location within slave port write buffer. */
assert(((psSlavePort->pSPBuffer <= psSlavePort->pSPFlushThreshold) && (psSlavePort->pSPBuffer >= psSlavePort->pSPBufferBase)));
ui32DataToWrite = psSlavePort->pSPBuffer - psSlavePort->pSPBufferBase;
/* Verify that ui32DataToWrite and iu32SPFree values are correct for the CMD buffer
and IZZ buffer (IDCT buffer is not in use). */
assert(((ui32DataToWrite >= 0) && (ui32DataToWrite <= (M24VA_SW_CMD_FIFO_SIZE * 2))));
assert(((psSlavePort->iu32SPFree >= 0) && (psSlavePort->iu32SPFree <= (M24VA_SW_CMD_FIFO_SIZE * 2))));
if(psSlavePort->iu32SPFree < ui32DataToWrite)
{
for(iTrys = 10; iTrys; iTrys --)
{
for(iPolls = 100; iPolls; iPolls--)
{
DEBUG_MODE_ONLY(psSlavePort->ui32Polls++);
UpdateSPFreeCounters();
if(psSlavePort->iu32SPFree >= ui32DataToWrite) goto HaveSpace;
}
DEBUG_MODE_ONLY(psSlavePort->ui32Trys++);
Sleep(1);
}
/* Error Slaveport overflow, cmd lost */
DEBUG_MODE_ONLY(psSlavePort->ui32Overflows++);
/* Timeout condition should not occur. */
assert(0);
return(M24VAError_WriteTimedOut);
}
HaveSpace:
#endif
/************************************************************ Write data */
DEBUG_MODE_ONLY(psSlavePort->ui32AccessCount+=ui32DataToWrite);
{
IMG_UINT32 *pui32Source = psSlavePort->pSPBufferBase;
IMG_UINT32 *pui32Dest = psSlavePort->pui32SlavePortLinAddr + psSlavePort->ui32SPAddOn;
psSlavePort->ui32SPAddOn = (psSlavePort->ui32SPAddOn + ui32DataToWrite) & SP_WRITE_MASK;
psSlavePort->iu32SPFree -= ui32DataToWrite;
while(ui32DataToWrite--)
{
#ifdef INIFINTELY_FAST_HW
IMG_UINT32 iu32Dummy = *pui32Source++;
#else
M24VA_PDUMP(("WRW :SP:%08X %08X\n", psSlavePort->pSPBufferBase, *pui32Source));
*pui32Dest++ = *pui32Source++;
#endif // INIFINTELY_FAST_HW
}
psSlavePort->pSPBuffer = psSlavePort->pSPBufferBase;
}
return(eRtn);
}
/*****************************************************************************
FUNCTION : M24VA_IZZ_SPBufferWrite
PURPOSE : Buffered write to the IZZ slaveport
PARAMETERS :
RETURNS : nothing
Notes :
*****************************************************************************/
__inline static M24VAError M24VA_IZZ_SPBufferWrite(IMG_UINT32 *pui23SPData,
IMG_UINT32 ui32DataSize)
{
M24VAError eRtn = M24VAError_OK;
register IMG_UINT32 *pui32Buffer = g_M24VAState.sIZZSlavePort.pSPBuffer;
register IMG_UINT32 *pui32Threshold = g_M24VAState.sIZZSlavePort.pSPFlushThreshold;
/* Transfer Data to Buffer, assumes alway one free location in buffer */
while(ui32DataSize--)
{
*pui32Buffer++ = *pui23SPData++;
if(pui32Buffer >= pui32Threshold)
{
g_M24VAState.sIZZSlavePort.pSPBuffer = pui32Buffer;
AcquireMPEG();
M24VA_SPBufferFlush(&g_M24VAState.sCMDSlavePort);
eRtn = M24VA_SPBufferFlush(&g_M24VAState.sIZZSlavePort);
ReleaseMPEG();
pui32Buffer = g_M24VAState.sIZZSlavePort.pSPBuffer;
}
}
g_M24VAState.sIZZSlavePort.pSPBuffer = pui32Buffer;
return(eRtn);
}
/******************************************************** External functions */
/*****************************************************************************
FUNCTION : M24VA_Initialise
PURPOSE : Initialise m24va interface, acquire hardware
PARAMETERS : ui32Param - implemention specific parameter
RETURNS : M24VAError
Notes : Map M24VA hardware into our address space
*****************************************************************************/
M24VAError PVRAPI M24VA_Initialise(IMG_PVOID pvParam)
{
UNREFERENCED_PARAMETER(pvParam);
if(g_M24VAState.bHardwareInUse)
{
return(M24VAError_HardwareNotAvailable);
}
memset(&g_M24VAState, 0, sizeof(g_M24VAState));
g_M24VAState.bHardwareInUse = TRUE;
/****************************************************** Acquire hardware */
{
DRVESC_M24VA_ACQUIRE_PARAMS sM24VAAcquire;
if(!g_M24VAState.hdcDriver)
{
g_M24VAState.hdcDriver = GetWindowDC(NULL);
}
sM24VAAcquire.dwAcquire = TRUE;
sM24VAAcquire.dwProcessID = GetCurrentProcessId();
if(ExtEscape(g_M24VAState.hdcDriver, DRVESC_M24VA_ACQUIRE, 0, NULL,
sizeof(sM24VAAcquire), (LPSTR)&sM24VAAcquire) < 0)
{
g_M24VAState.bHardwareInUse = FALSE;
ReleaseDC(NULL, g_M24VAState.hdcDriver);
return(M24VAError_HardwareNotAvailable);
}
}
/* Connect to services acquire device */
PVRSRVConnect(NULL, &g_M24VAState.hServices);
if(PVRSRVAcquireDeviceData(g_M24VAState.hServices, 0, &g_M24VAState.sM24VADevData, PVRSRV_DEVICE_TYPE_M24VA) != PVRSRV_OK)
{
PVRSRVDisconnect(g_M24VAState.hServices);
g_M24VAState.hServices = NULL;
M24VA_Deinitialise();
return(M24VAError_HardwareNotAvailable);
}
if(PVRSRVConnectMPEGApplication(&g_M24VAState.sM24VADevData, IMG_TRUE))
{
PVRSRVDisconnect(g_M24VAState.hServices);
g_M24VAState.hServices = NULL;
M24VA_Deinitialise();
return(M24VAError_HardwareNotAvailable);
}
if(PVRSRVGetHWInfo(&g_M24VAState.sM24VADevData, &g_M24VAState.sHWInfo) != PVRSRV_OK)
{
PVRSRVReleaseDeviceData(&g_M24VAState.sM24VADevData);
PVRSRVDisconnect(g_M24VAState.hServices);
g_M24VAState.hServices = NULL;
M24VA_Deinitialise();
return(M24VAError_HardwareNotAvailable);
}
g_M24VAState.pRegisters = g_M24VAState.sHWInfo.pvRegsBase;
g_M24VAState.sCMDSlavePort.pui32SlavePortLinAddr = g_M24VAState.sHWInfo.sDeviceSpecific.sM24VA.pvSPCmd;
g_M24VAState.sCMDSlavePort.pSPBufferBase = g_M24VAState.aui32CMDWriteBuffer;
g_M24VAState.sCMDSlavePort.pSPBuffer = g_M24VAState.aui32CMDWriteBuffer;
g_M24VAState.sCMDSlavePort.pSPFlushThreshold = &g_M24VAState.aui32CMDWriteBuffer[M24VA_SW_CMD_FIFO_SIZE];
g_M24VAState.sCMDSlavePort.ui32SPAddOn = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -