📄 mae1200.cpp
字号:
// SDK\INC
#include <windows.h>
// DDK\INC
#include <ceddk.h>
#include <devload.h>
#include <ddkreg.h>
// OAK\INC
#include <nkintr.h>
// <BSP>\INC
#include <bceddk.h>
#include "stdafx.h"
// Use this define to discard (not display) frames later than threshold
//#define NO_SHOW_LATE 1
#define NO_SHOW_LATE_THRESHOLD 33 //msec
// KK - rev2 - Turn this flag on to debug FE register programming (reference pointers and related stuff)
//#define REG_DEBUG 1
// au1200 header files
#include "MAE1200.h"
#include "au1200_lcd.h"
#include "au1200.h"
#include "queue.h"
#include "mae_hal.h"
#include "mae_interface.h"
#include "mae_global.h"
#include "time64.h"
#include <Mmsystem.h>
#define MAE_THREAD_PRIORITY 40
//#define MAE_ROTATION_TEST
#define USE_STOPSTATE 1
//#define SLOW_SUBMITS_ON_PAUSE
static int gMaeInit=0;
static int nPriority = 21;
static MAEhandler_t MAEhandler;
static au1xxxmae_ioctl_t *ioc;
static au1xxxmae_ioctl_t *lcd_ioc;
static HANDLE hEventYUVBufferAvailable;
static HANDLE g_hEventIoctlStart;
static HANDLE g_hEventIoctlComplete;
static AU1200_LCD lcd_info;
static BOOL gOpenFlag = FALSE;
static BOOL g_bSavedLcdRegisters = FALSE;
static int gOpenCounter = 0;
static BOOL g_bGotAudioPTS = FALSE;
static DWORD g_RegistryIgnorePTS = 0;
DWORD g_bFlushing = 0; /* flushing active */
int g_Speed=1;
static BOOL g_bLCDScanEnabled = FALSE;
static BOOL nFirstDisplayFrame = TRUE;
static DWORD g_FrameOutNum = 0;
HANDLE g_hEndOfStreamSemaphore = NULL;
extern "C" DWORD g_WaitForEOS;
DWORD nRequestDone = 0; /* is there an outstanding REQUESTed buffer */
extern "C" RECT g_RectPlayer;
extern "C" RECT g_RectScreen;
#ifdef YUV_DUMPS
#define INT_STATE_NONE 0
#define INT_STATE_FE_DONE 1
#define INT_STATE_BE_DONE 2
#define INT_STATE_BOTH_DONE 3
static int nFrameState = INT_STATE_NONE;
#endif
#define HANDLE_NON_STANDARD_DIVX_CERT_CLIPS
#define DISPLAY_THRESHOLD 3 // msec
#define WARNING_THRESHOLD 10000 // msec
#define RESYNC_MAX_THRESHOLD 10000 // msec
#define DISPLAY_MAX_WAIT 2000 // msec
#define MAE_BOTH_INT 0x80000000
#define MAE_FE_INT 0x200
#define MAE_BE_INT 0x10
#define MAE_STATE_NONE 0x00 /* no state - interrupts not started */
#define MAE_STATE_PAUSING 0x01 /* requesting a pause */
#define MAE_STATE_PAUSED 0x02 /* paused (at least one frame processed) */
#define MAE_STATE_PREROLL 0x04 /* preroll */
#define MAE_STATE_STARTING 0x08 /* start playing */
#define MAE_STATE_PLAYING 0x10 /* playing */
#define MAE_STATE_STOPPING 0x20 /* requesting a stop */
#define MAE_STATE_STOPPED 0x40 /* interrupt completed transition to stop */
#define IsBEStopped() (g_BEState==MAE_STATE_NONE || g_BEState==MAE_STATE_STOPPED)
#define IsFEStopped() (g_FEState==MAE_STATE_NONE || g_FEState==MAE_STATE_STOPPED)
/* IsRunning return success if MAE is in a state where it's queues are Active */
#define IsRunning() (g_BEState&(MAE_STATE_PREROLL|MAE_STATE_STARTING|MAE_STATE_PLAYING))
#define IsPaused() (g_BEState&(MAE_STATE_PAUSED))
static DWORD g_FEState=MAE_STATE_NONE;
static DWORD g_BEState=MAE_STATE_NONE;
ContextTime_t g_ContextTime;
MAE_MODE_STRUCT g_cur_mode;
/* enum/flag/string translation table entry (for debug) */
typedef struct EnumDesc_s {
unsigned int uiEnum;
TCHAR *pszDesc;
} EnumDesc_t;
#define DECLARE_ENUM(_uiEnum, _szDesc) { _uiEnum, _szDesc }
#define RunStateStr(_eState) sp_flagstostr(enumtabRunState, _eState)
static EnumDesc_t enumtabRunState[] = {
DECLARE_ENUM(MAE_STATE_NONE, TEXT("NONE")),
DECLARE_ENUM(MAE_STATE_PAUSING, TEXT("PAUSING")),
DECLARE_ENUM(MAE_STATE_PAUSED, TEXT("PAUSED")),
DECLARE_ENUM(MAE_STATE_PREROLL, TEXT("PREROLL")),
DECLARE_ENUM(MAE_STATE_STARTING, TEXT("STARTING")),
DECLARE_ENUM(MAE_STATE_PLAYING, TEXT("PLAYING")),
DECLARE_ENUM(MAE_STATE_STOPPING, TEXT("STOPPING")),
DECLARE_ENUM(MAE_STATE_STOPPED, TEXT("STOPPED")),
DECLARE_ENUM(MAE_STATE_NONE, TEXT("NONE")),
DECLARE_ENUM(0xFFFFFFFF, TEXT("Unknown"))
};
static TCHAR szFrameType[3][12] =
{
{TEXT("I Frame")},
{TEXT("P Frame")},
{TEXT("B Frame")}
};
unsigned long PowerMgmtThread();
void wake_decoder(void);
void wake_fe(void);
void enable_overlay(DWORD uiPlane);
void disable_overlay(DWORD uiPlane);
void save_lcd_registers();
void restore_lcd_registers();
void clear_lcd_pipeline(void);
void enable_lcd_scan(void);
void disable_lcd_scan(void);
void halt_mae(void);
void flush_mae(int);
void flush_maeq(void);
void flush_rgbq(void);
PMAEQ_T new_besw(void);
#ifndef USE_IOCTL_THREAD
void write_system_time_clock(ContextTime_t *ContextTime);
#else
void write_system_time_clock(ContextTime_t ContextTime);
#endif
unsigned long display_frame();
extern "C" void print_registers();
void do_display() ;
extern "C" ULONG getPRId(void);
extern "C" ULONG getconfig1(void);
// #define DISPLAY_FPS 1
// #define SEND_FPS_TO_CLIENT 1
// #define WaitForSingleObject(x, y) MGDWaitForSingleObject((x), (y), __FILE__, __LINE__)
// #define MGD_WAIT_LIMIT 10000
#ifdef DISPLAY_FPS
unsigned long g_totaltime,g_totalframes;
long g_frame_cnt;
DWORD endtime,starttime;
#endif
#ifdef SEND_FPS_TO_CLIENT
static HANDLE hFile = NULL;
static HANDLE hMapFile = NULL;
static LPVOID lpBuffer = NULL;
static float fMaxFPS = -1.0f;
static float fMinFPS = 100000.0f;
#endif
#ifdef WaitForSingleObject
inline DWORD MGDWaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds, char *File, int line)
{
DWORD rv = WAIT_TIMEOUT;
if (dwMilliseconds == INFINITE)
{
// We will not be doing infinite waits because they suck
while(rv == WAIT_TIMEOUT)
{
rv = WaitForSingleObject(hHandle, MGD_WAIT_LIMIT);
if (rv == WAIT_TIMEOUT)
{
// this is our shortcircuited infinite wait path
printf("Infinite loop found at %s:%d\n", File, line);
}
}
}
else
{
rv = WaitForSingleObject(hHandle, dwMilliseconds);
}
return ( rv );
}
#endif
int sp_strcat(TCHAR *pdst, const TCHAR *psrc)
{
int count=0;
/* find the end of destination string */
while (*pdst)
{
pdst++;
count++;
}
/* append psrc->pdst */
while (*psrc)
{
*pdst=*psrc;
pdst++;
psrc++;
count++;
}
*pdst=0;
return count;
}
/*
** sp_flagstostr()
** Convert flags to a string (note: this also uses enum tables).
*/
TCHAR *sp_flagstostr(EnumDesc_t *pEnumTable, unsigned int uiFlags)
{
static TCHAR pszTmpStr[2][128]={TEXT("")};
static uiTmpStrIndex=0; /* allows nested calls to return different string pointers */
TCHAR *pszStr;
EnumDesc_t *pEnumEntry=NULL;
unsigned int uiPos;
unsigned int uiFlagCount=0;
pszStr=pszTmpStr[uiTmpStrIndex];
uiTmpStrIndex=(uiTmpStrIndex+1)%2; /* bump temp str pointer */
pszStr[0]=0;
if (pEnumTable)
{
for (uiPos=0; pEnumTable[uiPos].uiEnum!=0xFFFFFFFF; uiPos++)
if (pEnumTable[uiPos].uiEnum &&
(pEnumTable[uiPos].uiEnum&uiFlags)==pEnumTable[uiPos].uiEnum)
{
pEnumEntry=pEnumTable+uiPos;
/* found matching flag */
if (uiFlagCount)
sp_strcat(pszStr, TEXT("|")); /* seperator */
sp_strcat(pszStr, pEnumEntry->pszDesc);
uiFlagCount++;
}
if (!uiFlagCount) /* no flags matched, search for exact match (handles NONE values) */
for (uiPos=0; pEnumTable[uiPos].uiEnum!=0xFFFFFFFF; uiPos++)
if (pEnumTable[uiPos].uiEnum==uiFlags)
{
pEnumEntry=pEnumTable+uiPos;
/* found matching flag */
if (uiFlagCount)
sp_strcat(pszStr, TEXT("|")); /* seperator */
sp_strcat(pszStr, pEnumEntry->pszDesc);
uiFlagCount++;
}
}
if (!uiFlagCount) /* no matching flags in table */
{
/* Return enum in form of: "0x12345678" */
//pszStr[0]='0';
//pszStr[1]='x';
//sp_uitoah(uiFlags, pszStr+2, 0);
//pszStr[10]=0;
}
return pszStr;
}
void change_FEstate(unsigned int eNewState)
{
if (g_FEState!=eNewState)
{
DPRINTF(MSG_STATE, (TEXT("mae: FEstate %s -> %s\n"),
RunStateStr(g_FEState), RunStateStr(eNewState)));
if (eNewState==MAE_STATE_NONE || eNewState==MAE_STATE_STOPPED)
{
/* disable lcd interrupt in stopped states */
disable_lcd_scan();
}
else if ((eNewState&(MAE_STATE_PREROLL|MAE_STATE_STARTING|MAE_STATE_PLAYING|MAE_STATE_PAUSING|MAE_STATE_PAUSED))!=0)
{
/* enable lcd interrupt on any non-stopped states */
enable_lcd_scan();
}
g_FEState = eNewState; /* change state */
if (g_FEState!=MAE_STATE_NONE && g_FEState!=MAE_STATE_STOPPED) /* FE not in stopped state, so mae_int should be active */
{
/* signal mae_interrupt to pick up state change */
wake_fe();
wake_decoder();
}
else if ((g_FEState==MAE_STATE_NONE || g_FEState==MAE_STATE_STOPPED) &&
(g_BEState==MAE_STATE_NONE || g_BEState==MAE_STATE_STOPPED)) /* both FE and BE are stopped */
{
halt_mae();
}
}
}
void change_BEstate(unsigned int eNewState)
{
if (g_BEState!=eNewState)
{
DPRINTF(MSG_STATE, (TEXT("mae: BEstate %s -> %s\n"),
RunStateStr(g_BEState), RunStateStr(eNewState)));
/* handle special event on state changes */
if (eNewState==MAE_STATE_NONE || eNewState==MAE_STATE_STOPPING || eNewState==MAE_STATE_STOPPED)
{
disable_overlay(MAE_PLANE);
}
else if ((eNewState&(MAE_STATE_PLAYING))!=0)
{
if (!g_bFlushing) /* during Flushing ignore state changes - don't change overlay state */
enable_overlay(MAE_PLANE);
}
if (eNewState==MAE_STATE_NONE || eNewState==MAE_STATE_STOPPED)
g_FrameOutNum = 0;
g_BEState = eNewState; /* change state */
if (g_FEState!=MAE_STATE_NONE && g_FEState!=MAE_STATE_STOPPED) /* FE not in stopped state, so mae_int should be active */
{
/* signal mae_interrupt to pick up state change */
wake_fe();
}
else if ((g_FEState==MAE_STATE_NONE || g_FEState==MAE_STATE_STOPPED) &&
(g_BEState==MAE_STATE_NONE || g_BEState==MAE_STATE_STOPPED)) /* both FE abd BE are stopped */
{
halt_mae();
}
}
}
int isFEstate(unsigned int eStateFlags)
{
return ((g_FEState&eStateFlags)!=0 || g_FEState==eStateFlags);
}
int isBEstate(unsigned int eStateFlags)
{
return ((g_BEState&eStateFlags)!=0 || g_BEState==eStateFlags);
}
int waitfor_FEstate(unsigned int eStateFlags, unsigned int uiTimeOut)
{
unsigned int uiTotalWait=0;
int bStateMatched=0;
while (g_FEState!=MAE_STATE_NONE)
{
if ((g_FEState&eStateFlags)!=0 || g_FEState==eStateFlags)
{
bStateMatched=1;
break;
}
DPRINTF(MSG_STATE, (TEXT("waitfor_FEstate(%s) current=%s\n"),
RunStateStr(eStateFlags), RunStateStr(g_FEState)));
if (uiTimeOut && uiTotalWait>=uiTimeOut)
break; /* timeout reached */
Sleep(50);
uiTotalWait+=50;
}
DPRINTF(MSG_STATE, (TEXT("waitfor_FEstate(%s) done: current=%s time=%d\n"),
RunStateStr(eStateFlags), RunStateStr(g_FEState), uiTotalWait));
return bStateMatched;
}
int waitfor_BEstate(unsigned int eStateFlags, unsigned int uiTimeOut)
{
unsigned int uiTotalWait=0;
int bStateMatched=0;
while (g_bLCDScanEnabled)
{
if ((g_BEState&eStateFlags)!=0 || g_BEState==eStateFlags)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -