📄 mae1200.cpp
字号:
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl ISDISPLAYED=%d fe=%s be=%s\n"),
uiFramesDisplayed, RunStateStr(g_FEState), RunStateStr(g_BEState) ));
*(DWORD *) pBufOut = uiFramesDisplayed;
}
break;
case AU1XXXMAE_VIDEOROTATION:
{
DPRINTF(MSG_IOCTL, (TEXT("In AU1XXXMAE_VIDEOROTATION switch ")));
set_video_rotation();
}
break;
case AU1XXXMAE_FLUSH: /* flush and resync */
case AU1XXXMAE_FLUSH_QUEUES: /* don't resync */
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH fe=%s be=%s bFlushing=%d FrameOut=%d\n"),
RunStateStr(g_FEState), RunStateStr(g_BEState), g_bFlushing, g_FrameOutNum ));
if (IsFEStopped() && IsBEStopped())
{
/* if were already stopped, then all has been flushed */
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH already stopped\n") ));
}
else
{
DWORD mask;
unsigned int bResync=(dwCode==AU1XXXMAE_FLUSH);
unsigned int SaveBEState=g_BEState;
g_bFlushing = 1; /* flag that Flushing is busy */
if (!IsFEStopped())
{
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH stopping FE\n") ));
change_FEstate(MAE_STATE_STOPPING);
}
if (IsRunning()) /* if we were running, pause first to give interrupt time to finish */
{
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH pausing BE\n") ));
change_BEstate(MAE_STATE_PAUSING);
waitfor_BEstate(~MAE_STATE_PAUSING, 300);
}
else
{
/* wait for mae thread to transition to stopped */
/* The interrupts will flush everything when they transition to STOPPED state. */
waitfor_FEstate(~MAE_STATE_STOPPING, 300);
}
EnterCS(g_CriticalSection);
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH restoring states\n") ));
mask = mask_interrupts(gbl_mask | (1 << AU1200_LCD_INT));
g_FrameOutNum = 0; // note, change_BEstate will also reset on STOPPED
/* recover BE & FE run states prior to Flushing */
if (SaveBEState!=MAE_STATE_NONE && SaveBEState!=MAE_STATE_STOPPED)
change_FEstate(MAE_STATE_STARTING);
if (SaveBEState==MAE_STATE_PREROLL)
change_BEstate(MAE_STATE_PREROLL);
else if (SaveBEState==MAE_STATE_PAUSING || SaveBEState==MAE_STATE_PAUSED)
change_BEstate(MAE_STATE_PAUSING); /* force BE to pick up next frame and pause again */
else if (SaveBEState!=MAE_STATE_NONE && SaveBEState!=MAE_STATE_STOPPED)
change_BEstate(SaveBEState);
DPRINTF(MSG_IOCTL|MSG_STATE, (TEXT("MAE_Ioctl FLUSH done fe=%s be=%s\n"),
RunStateStr(g_FEState), RunStateStr(g_BEState) ));
g_bFlushing = 0; /* Flushing done */
unmask_interrupts(mask);
LeaveCS(g_CriticalSection);
}
break;
case AU1XXXMAE_ENDOFSTREAM:
{
/* this returns whether an EOS has been encountered (queues drained of all frames) */
DWORD mask, bGotEOS=0;
DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM fe=%s be=%s waitEOS=%d\n"),
RunStateStr(g_FEState), RunStateStr(g_BEState), g_WaitForEOS ));
EnterCS(g_CriticalSection);
mask = mask_interrupts(gbl_mask | (1 << AU1200_LCD_INT));
ResetEvent(g_hEndOfStreamSemaphore);
g_WaitForEOS = 1;
unmask_interrupts(mask);
LeaveCS(g_CriticalSection);
/* we check multiple times for EOS since it may be set when the rgb queue is starving */
while (bGotEOS<4 && isBEstate(MAE_STATE_PREROLL|MAE_STATE_STARTING|MAE_STATE_PLAYING))
{
DWORD dwReturn;
DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM check: fe=%s be=%s\n"),
RunStateStr(g_FEState), RunStateStr(g_BEState) ));
dwReturn = WaitForSingleObject(g_hEndOfStreamSemaphore,300);
if(dwReturn == WAIT_OBJECT_0)
{
bGotEOS++;
g_WaitForEOS = 1;
}
else
{
DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM timeout\n")));
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,TEXT("PowerManager/ActivityTimer/UserActivity"));
SetEvent(hEvent);
CloseHandle(hEvent);
}
if (!pmms->be_proc && !pmms->fe_proc) /* all queues are empty */
{
DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM queues empty\n")));
break;
}
}
g_WaitForEOS = 0;
*(DWORD *) pBufOut = bGotEOS;
DPRINTF(MSG_IOCTL|MSG_STATE|MSG_TIME, (TEXT("MAE_Ioctl ENDOFSTREAM done: GotEOS=%d fe=%s be=%s\n"),
bGotEOS, RunStateStr(g_FEState), RunStateStr(g_BEState) ));
}
break;
case AU1XXXMAE_GETCURRENTSTATE:
{
DPRINTF(MSG_IOCTL, (TEXT("MAE_Ioctl GETCURRENTSTATE fe=%s be=%s\n"),
RunStateStr(g_FEState), RunStateStr(g_BEState) ));
*(DWORD *) pBufOut = (DWORD)g_FEState;
}
break;
#ifdef YUV_DUMPS
case AU1XXXMAE_GETINTERRUPTSTATE:
{
// The decoder(s) will wait until it receives a FE_DONE
// indication before starting to dump out the YUV data
DPRINTF(MSG_IOCTL, (TEXT("MAE_Ioctl GETINTERRUPTSTATE")));
*(DWORD *) pBufOut = (DWORD)nFrameState;
// Clear the flag now to make sure that we indicate
// FE_DONE iff we received an interrupt
if (nFrameState == INT_STATE_FE_DONE)
nFrameState = INT_STATE_NONE;
}
break;
#endif
case AU1XXXMAE_GETDIVXSTR:
{
PDIVX_DRM_STRUCT pDivX_drm=(DIVX_DRM_STRUCT *)pBufOut;
unsigned int salt[8] = { 0x9defc909, 0x301ec998, 0xcde43ceb, 0x66dd8015,
0xf5086c66, 0x268d0a3a, 0x89af5557, 0xd19c7d87};
pDivX_drm->reg30 = au_readl(0xB4012030) ^ salt[0];
pDivX_drm->reg34 = au_readl(0xB4012034) ^ salt[1];
pDivX_drm->reg60 = au_readl(0xB4012060) ^ salt[2];
pDivX_drm->prid = (DWORD)getPRId() ^ salt[3];
pDivX_drm->config1 = (DWORD)getconfig1() ^ salt[4];
pDivX_drm->reg1000 = au_readl(0xB4013000) ^ salt[5];
pDivX_drm->reg100c = au_readl(0xB401300C) ^ salt[6];
pDivX_drm->reg101c = au_readl(0xB4013010) ^ salt[7];
}
break;
case AU1XXXMAE_GETPRID:
{
DPRINTF(MSG_IOCTL, (TEXT("MAE_Ioctl GETPRID\n")));
*(DWORD *) pBufOut = (DWORD)getPRId();
}
break;
default :
RetVal = FALSE;
break;
}
DPRINTF (MSG_IOCTL, (TEXT("-MAE_IOControl %s \r\n"), (RetVal == TRUE) ? TEXT("Success") : TEXT("Error")));
return(RetVal);
}
// Allocate physical contigous memory for the MAE device
// Memory is now allocated from a region reserved in the config.bib file
BOOL AllocateDeviceMemory(void)
{
BOOL bRet = 0;
PVOID BaseAddress;
#ifdef YUV_DUMPS
UINT32 size = SIZE_MAE_MASTER_STRUCT + SIZE_AVSYNC + SIZE_MAEQ + SIZE_DATAQ + SIZE_YUVQ + SIZE_RGBQ
+ SIZE_DESCRIPTOR_BASE + SIZE_DATA_BUFFER_BASE + SIZE_RGB_FRAMES_BASE
+ SIZE_YUV_FRAMES_BASE + SIZE_SCRATCH_PAD_BASE;
nTotalAllocatedSize = size;
#else
UINT32 size = SIZE_MAE_MASTER_STRUCT + SIZE_AVSYNC + SIZE_MAEQ + SIZE_DATAQ + SIZE_YUVQ + SIZE_RGBQ
+ SIZE_DESCRIPTOR_BASE + SIZE_DATA_BUFFER_BASE;
nTotalAllocatedSize = size;
#endif
DPRINTF(MSG_MEMORY, (TEXT("AllocateDeviceMemory: master struct size: 0x%x (%d bytes)\n"), sizeof(MAE_MASTER_T), sizeof(MAE_MASTER_T)));
DPRINTF(MSG_MEMORY, (TEXT("AllocateDeviceMemory: mem to be allocated: 0x%x (%d bytes)"), size, size));
// This value comes from our config.bib file
gMaePhysBaseAddress = 0x00100000;
// Only large data buffers should be cacheable.
//
unsigned long noCacheSize = SIZE_MAE_MASTER_STRUCT +
SIZE_DESCRIPTOR_BASE; // + SIZE_RGBQ + SIZE_YUVQ + SIZE_DATAQ + SIZE_MAEQ + SIZE_AVSYNC;
size -= noCacheSize;
// Align to page (4K) boundary
//
noCacheSize = (noCacheSize + 4095) & ~4095;
size = (size + 4095) & ~4095;
BaseAddress = VirtualAlloc(0, size + noCacheSize, MEM_RESERVE, PAGE_NOACCESS);
//bRet = VirtualCopy(BaseAddress, (PVOID)(gMaePhysBaseAddress | 0x80000000), size, PAGE_READWRITE | PAGE_NOCACHE);
// Map non-cacheable area
//
bRet = VirtualCopy(BaseAddress, (PVOID)((gMaePhysBaseAddress) >> 8), noCacheSize, PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE);
if (!bRet)
{
RPRINTF(MSG_ERROR,(TEXT("Failed mapping non-cacheable space!!!\n")));
}
// This turns on caching.
bRet = VirtualCopy((PVOID)((ULONG)BaseAddress + noCacheSize), (PVOID)((gMaePhysBaseAddress + noCacheSize) >> 8), size, PAGE_PHYSICAL | PAGE_READWRITE);
if (!bRet)
{
RPRINTF(MSG_ERROR,(TEXT("Failed mapping cacheable space!!!\n")));
VirtualFree(BaseAddress, 0, MEM_RELEASE);
return FALSE;
}
gVirtualBaseAddress = (unsigned long)BaseAddress;
KRNL_MAE_MASTER_STRUCT = gVirtualBaseAddress;
KRNL_DESCRIPTOR_BASE = KRNL_MAE_MASTER_STRUCT + SIZE_MAE_MASTER_STRUCT;
KRNL_RGBQ = gVirtualBaseAddress + noCacheSize;
KRNL_YUVQ = KRNL_RGBQ + SIZE_RGBQ;
KRNL_DATAQ = KRNL_YUVQ + SIZE_YUVQ;
KRNL_MAEQ = KRNL_DATAQ + SIZE_DATAQ;
KRNL_AVSYNC = KRNL_MAEQ + SIZE_MAEQ;
KRNL_DATA_BUFFER_BASE = KRNL_AVSYNC + SIZE_AVSYNC;
KRNL_RGB_FRAMES_BASE = KRNL_DATA_BUFFER_BASE + SIZE_DATA_BUFFER_BASE;
KRNL_YUV_FRAMES_BASE = KRNL_RGB_FRAMES_BASE + SIZE_RGB_FRAMES_BASE;
KRNL_SCRATCH_PAD_BASE = KRNL_YUV_FRAMES_BASE + SIZE_YUV_FRAMES_BASE;
DPRINTF (MSG_MEMORY, (TEXT("Non Cacheable Base = 0x%X\n"), gVirtualBaseAddress));
DPRINTF (MSG_MEMORY, (TEXT("Cacheable Base = 0x%X\n"), gVirtualBaseAddress + noCacheSize));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_MAE_MASTER_STRUCT = 0x%X\n"), KRNL_MAE_MASTER_STRUCT));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_DESCRIPTOR_BASE = 0x%X\n"), KRNL_DESCRIPTOR_BASE));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_RGBQ = 0x%X\n"), KRNL_RGBQ));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_YUVQ = 0x%X\n"), KRNL_YUVQ));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_DATAQ = 0x%X\n"), KRNL_DATAQ));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_MAEQ = 0x%X\n"), KRNL_MAEQ));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_AVSYNC = 0x%X\n"), KRNL_AVSYNC));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_DATA_BUFFER_BASE = 0x%X\n"), KRNL_DATA_BUFFER_BASE));
DPRINTF (MSG_MEMORY, (TEXT("\n")));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_RGB_FRAMES_BASE = 0x%X, size 0x%X\n"),
KRNL_RGB_FRAMES_BASE, SIZE_RGB_FRAMES_BASE));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_YUV_FRAMES_BASE = 0x%X, size 0x%X\n"),
KRNL_YUV_FRAMES_BASE, SIZE_YUV_FRAMES_BASE));
DPRINTF (MSG_MEMORY, (TEXT("KRNL_SCRATCH_PAD_BASE = 0x%X, size 0x%X\n"),
KRNL_SCRATCH_PAD_BASE, SIZE_SCRATCH_PAD_BASE));
// establish the debug pointer structure. This is squeezed in the 4k page
// used by avsync....
pdbgout = (PDBGOUT)KRNL_AVSYNC;
return TRUE;
}
void ReadRegistryKeys(void)
{
HKEY hKey;
ULONG BytesReturned;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("Drivers\\BuiltIn\\MAE1200"),0,0,&hKey) == ERROR_SUCCESS) {
RegQueryValueEx(hKey,TEXT("IgnorePTS"),0,NULL,(PUCHAR)&g_RegistryIgnorePTS,&BytesReturned);
RegCloseKey(hKey);
}
DPRINTF (MSG_INIT, (TEXT("ReadRegistryKeys end IgnorePTS:%d\n"),g_RegistryIgnorePTS));
}
void ShowVersion(void)
{
TCHAR szTemp[1024];
wsprintf (szTemp,TEXT("Maedriver, v%d.%d.%d.%d\n"), kVersion_Main,kVersion_Sub,kVersion_Build,kVersion_BuildSub);
OutputDebugString(szTemp);
}
void mae_wake_up_function(void)
{
UINT32 fe_armed = FALSE;
UINT32 be_armed = FALSE;
DPRINTF (MSG_FUNCTION, (TEXT("mae_wake_up_function\n")));
if(pmms->StillSleeping)
{
DPRINTF (MSG_STATE, (TEXT("mae_wake_up_function() StillSleeping\n")));
if(pmms->yuv_free && pmms->rgb_free)
{
if (pmms->state & ENABLE_FE) {
// not the last frame, re-arm the front end
my_fe_armed=fe_armed = run_fe_hw();
#ifdef DUMP_FE
DPRINTF(MSG_TIME, (TEXT("@wake_up@\n")));
dump_fe();
#endif
// note: if run_fe_hw returns false,
// cannot rearm the fe even though the system has it enabled. To keep the
// pipeline intact we freeze the be because the fe cannot feed it. With the
// be left on it could consume the forward anchor before it should be.
}
// The next temporal buffer is chosen and enabled for processing
if ((pmms->state & ENABLE_BE) && !(pmms->state & MAE_FREEZE)) {
my_be_armed=be_armed = run_be_hw();
}
pmms->StillSleeping = 0;
// really start the FE and BE, arm interrupts
kickstart_hw(fe_armed, be_armed);
}
}
}
UINT32 clear_rgbq_planes(void)
{
UINT32 rgb_buffer_addr = KRNL_RGB_FRAMES_BASE;
DPRINTF (MSG_FUNCTION, (TEXT("clear_rgbq_planes entry:\n")));
memset((PVOID)rgb_buffer_addr, 0, SIZE_RGB_FRAME*NUM_RGBQ_ELEMENTS);
return 0;
}
//
// Queue element processing routines
//
void clean_maeq(PMAEQ_T el)
{
if (!el) return;
el->anchor_flag = 0;
el->sent_to_be = 0;
el->state_change = 0;
el->endframe_flag = 0;
el->update_mode_flag = 0;
el->interlacing_on = 0;
el->interlaced_frame_done = 1;
el->topfield_length = 0;
el->stream_type = 0;
el->dummysubmit = 0;
el->prog_frame = 1;
el->nFlushMAE = 0;
}
// assumes that interrupts have been disabled and that mae is not currently running
UINT32 init_maeq_list(UINT32 num)
{
UINT32 i=0;
UINT32 size;
PMAEQ_T el;
char sstr[256]="";
UINT32 addr = KRNL_MAEQ;
DPRINTF(MSG_FUNCTION, (TEXT("init_maeq_list entry\n")));
// limit the number of elements to what is supported
if (num > MAX_NUM_MAEQ_ELEMENTS)
num = MAX_NUM_MAEQ_ELEMENTS;
// create free list
size = sizeof(MAEQ_T);
DPRINTF(MSG_MEMORY, (TEXT("init_maeq_list creating %d maeq elements of size %d bytes each\n"), num, size));
while (i<num) {
el = (PMAEQ_T)addr;
DLCL_APPEND(MAEQ_T, &pmms->maeq_free, el);
addr += size;
i++;
}
return 0;
}
void init_desc_ring(void)
{
pmms->pDescRingStart = pmms->pCurDescPtr = (PUINT32) KRNL_DESCRIPTOR_BASE; //allocate_descriptor_memory(DEFAULT_DESCRIPTORS_SIZE, LOCK_MEM);
pmms->pDescRingEnd = (PUINT32)((char *)(pmms->pDescRingStart) + SIZE_DESCRIPTOR_BASE);
// We need at least one empty descriptor after each valid descriptor. In case of interlaced mode, we will an additional descriptor
pmms->pDescRingEnd--;
pmms->pDescRingEnd--;
pmms->pDescRingEnd--;
pmms->pDescRingEnd--;
DPRINTF(MSG_MEMORY, (TEXT("
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -