📄 audiostream.c
字号:
//
//File name: AudioStream.C
//This file contains code to handle audio interface of SAA7146
#include "ave2k.h"
#include "ave2kregs.h"
#include "ave2kutil.h"
#include "channel2.h"
#include "audiostream.h"
#include "audioctrl.h"
#include "rps.h"
#include "dsp.h"
#include "debi.h"
void ShiftAudio(PDEVICE_EXTENSION pDE, int nChannel);
static int WaitRPS(PDEVICE_EXTENSION pDE);
static int StartAudioRPS(PDEVICE_EXTENSION pDE, int Channel);
static void DisableDataTransfer(PDEVICE_EXTENSION pDE, int nChannel);
void ResetDSP(PDEVICE_EXTENSION pDE, int nChannel);
int Reset(PDEVICE_EXTENSION pDE, int nChannel);
int LoadDSPCode(PDEVICE_EXTENSION pDE, int nChannel);
BOOLEAN Reset7113LLC(PDEVICE_EXTENSION pDE, int nChannel);
//External defined global variables shared by all devices
//extern DISPLAY_PARAMETER DisplayParameter;
BOOLEAN InitAudioDespList(PAUDIODESPLIST pAudioDespList, PVOID Buffer,
PAUDIODESP pDespBuf, ULONG NumOfDesp)
{
PAUDIODESP pCurDesp;
PAUDIOSTREAMSECTOR pCurData;
ULONG i;
//give the first descriptor and data address
pCurDesp=pDespBuf;
pCurData=(PAUDIOSTREAMSECTOR)Buffer;
//RtlZeroMemory(Buffer,NumOfDesp*sizeof(AUDIOSTREAMSECTOR));
RtlZeroMemory(pDespBuf,NumOfDesp*sizeof(AUDIODESP));
for(i=0; i<NumOfDesp; i++){
pCurDesp->Flags.bufferlen=sizeof(AUDIOSTREAMSECTOR);
pCurDesp->pData = (PUCHAR)pCurData;
//move to next one
if(i != (NumOfDesp-1))
pCurDesp->pNext=pCurDesp +1;
else
pCurDesp->pNext=pDespBuf;
pCurDesp ++;
pCurData ++;
}
//Initialize the list
pAudioDespList->pHead = pAudioDespList->pReadPointer=pAudioDespList->pWritePointer=
pDespBuf;
return TRUE;
}
#ifdef _DEBUG
char HexToChar(int n)
{
if(n<=9)
return n+'0';
return n-10+'A';
}
void DumpBuffer(unsigned char *pBuf)
{
char Out[120];
unsigned char c;
char hex[3];
int i;
Out[0]=0;
hex[2]=' ';
hex[3]=0;
strcpy(Out, "XX XX ");
for(i=0; i<30; i++){
c=*pBuf++;
hex[0]=HexToChar(c>>4);
hex[1]=HexToChar(c&0x0f);
strcat(Out, hex);
if(i==5 || i==21)
strcat(Out, "- ");
if(i==13)
strcat(Out, "\n");
}
strcat(Out, "\n");
KdPrint((Out));
}
#endif
#define FC_SUCCESS 0
#define FC_STUFF_PACKET 1
#define FC_FILTER_OUT 2
#define FC_OUT_OF_SYNC 3
#define FC_SHIFT 4
static BOOLEAN CheckSectorFormat(
PAUDIOSTREAMSECTOR pSector,
//UCHAR *Buffer,
//int BufLen,
ULONG DataFilter
)
{
unsigned char *pTemp;
int nTempCount,i;
if((0xffffffff != *((PULONG)&pSector->CDSync[2]))||
(0xffffffff != *((PULONG)&pSector->CDSync[6])) ||
(pSector->CDSync[10]!=0xff) || (pSector->CDSync[11]!=0x0))
{
//KdPrint(("Out of sync detected.\n"));
//to avoid the first 'out of sync'
if((0 == *((PULONG)&pSector->CDSync[2]))&&
(0 == *((PULONG)&pSector->CDSync[6])))
return FC_FILTER_OUT;
nTempCount=0;
//if sequence is good
pTemp=(PUCHAR)pSector+24;
for(i=0; i<4; i++)
if(*(PULONG)pTemp++==0xba010000)
return FC_FILTER_OUT;
pTemp=(PUCHAR)pSector+2;
for(i=0; i<20; i++)
if(*pTemp==0xff || *pTemp==0){
pTemp++;
nTempCount++;
}
else
break;
//if(nTempCount>10)
// if(*pbFirst){
// KdPrint(("First out of sync in REVD1\n"));
// return FC_SHIFT;
// }
if(nTempCount>=10 && nTempCount<=12){
//pTemp=(PUCHAR)pSector+24;
//if(*(PULONG)(pTemp+2)==0)
return FC_SHIFT;
//for(i=0; i<8; i++)
// if(*pTemp++==0xba)
// return FC_SHIFT;
}
return FC_OUT_OF_SYNC;
}
//else{
// if(*pbFirst)
// KdPrint(("Begin sync.\n"));
// *pbFirst=FALSE;
//}
if(((PUCHAR)pSector)[19] != 0x0f &&
((PUCHAR)pSector)[19] != 0x7f)
return FC_STUFF_PACKET;
if(DataFilter==AVE2K_STREAM_VIDEO &&
((PUCHAR)pSector)[19] != 0x0f)
return FC_FILTER_OUT;
if(DataFilter==AVE2K_STREAM_AUDIO &&
((PUCHAR)pSector)[19] != 0x7f)
return FC_FILTER_OUT;
//RtlCopyMemory(Buffer, pSector->MPEGData, BufLen);
return FC_SUCCESS;
}
BOOLEAN AudioDespListRead(PDEVICE_EXTENSION pDE, ULONG BufLen, int nChannel)
{
BOOLEAN bHasDSPBug = FALSE;
BOOLEAN bReadSuccess = FALSE;
PAUDIOSTREAMSECTOR pSector;
PAUDIODESPLIST pAudioDespList=(nChannel==0)?(&pDE->AudioBufferList1):(&pDE->AudioBufferList2);
UCHAR *Buffer=(nChannel==0)?(pDE->ReadIrpDataBuffer):(pDE->CurrentAlternateIrpBuffer);
ULONG DataFilter=pDE->DataFilter[nChannel];
int nCheck;
//There is a bug in DSP, which cause leading word is lost in the frame
//A correct frame should start with 0x00 0xff, but a wrong frame start with
//0xff, 0xff
PAUDIODESP pCurDesp=pAudioDespList->pReadPointer;
do{
if(pCurDesp->Flags.ownbit == 0 ||
pCurDesp->Flags.datalen != sizeof(AUDIOSTREAMSECTOR)||
BufLen > sizeof(AUDIOSTREAMSECTOR)
)
return FALSE;
if(BufLen == 2324){
//Following code copy only MPEG data
if(pCurDesp->pData[0]!=0x00 ||
pCurDesp->pData[1]!=0xff)
bHasDSPBug = TRUE;
if(!bHasDSPBug)
pSector=(PAUDIOSTREAMSECTOR)(pCurDesp->pData);
else
pSector=(PAUDIOSTREAMSECTOR)(pCurDesp->pData-2);
pDE->nTotalCount[nChannel]++;
if(pDE->nTotalCount[nChannel]>75*3600*5){//75*3600*5
DisableDataTransfer(pDE, nChannel);
bReadSuccess=FALSE;
pDE->nErrorRecover[nChannel]=ERR_RESTART;
return FALSE;
}
nCheck=CheckSectorFormat(pSector, DataFilter);
switch(((PUCHAR)pSector)[19]){
case 0x0f:
pDE->Stat[nChannel].VideoPacket++;
pDE->nStillStuff[nChannel]=0;
if(pDE->bFirstVideo && ((PUCHAR)pSector)[39]==0xe0){
SetCompressFrameRate(pDE, pDE->nOnFrame[nChannel], pDE->nOffFrame[nChannel]);
pDE->bFirstVideo=FALSE;
}
break;
case 0x7f:
pDE->Stat[nChannel].AudioPacket++;
pDE->nStillStuff[nChannel]=0;
break;
case 0x1f:
pDE->Stat[nChannel].StuffPacket++;
pDE->nStillStuff[nChannel]++;
//nCheck=FC_SUCCESS;
break;
case 0x00:
pDE->Stat[nChannel].UnknownPacket++;
break;
default:
pDE->nStillStuff[nChannel]=0;
//pDE->Stat[nChannel].UnknownPacket++;
//if(nCheck!=FC_OUT_OF_SYNC)
// nCheck=FC_SHIFT;
break;
}
switch(nCheck){
case FC_SUCCESS:
bReadSuccess=TRUE;
break;
case FC_OUT_OF_SYNC:
//restart:
#ifdef _DEBUG
DumpBuffer((PUCHAR)pSector+2);
#endif
//increase counter
pDE->Stat[nChannel].OutOfSync++;
//disable DMA
DisableDataTransfer(pDE, nChannel);
bReadSuccess=FALSE;
pDE->nErrorRecover[nChannel]=ERR_RESYNC;
return FALSE;
case FC_STUFF_PACKET:
case FC_FILTER_OUT:
bReadSuccess=FALSE;
break;
case FC_SHIFT:
#ifdef _DEBUG
DumpBuffer((PUCHAR)pSector+2);
#endif
pDE->Stat[nChannel].OutOfSync++;
DisableDataTransfer(pDE, nChannel);
bReadSuccess=FALSE;
pDE->nErrorRecover[nChannel]=ERR_SHIFT;
pDE->ExStat[nChannel]|=EXSTAT_SHIFT;
return FALSE;
}
#if 0
pDE->TestCount[nChannel]++;
if(pDE->TestCount[nChannel]>500){
//pDE->TestCount[nChannel]=0;
// *(PULONG)pSector->MPEGData=0;
// //nCheck=FC_OUT_OF_SYNC;
DisableDataTransfer(pDE, nChannel);
//pDE->nErrorRecover[nChannel]=ERR_RESTART;
bReadSuccess=FALSE;
return FALSE;
}
#endif
if(bReadSuccess==TRUE){
if(*(PULONG)pSector->MPEGData!=0xba010000){
DisableDataTransfer(pDE, nChannel);
bReadSuccess=FALSE;
pDE->nErrorRecover[nChannel]=ERR_RELOAD;
pDE->ExStat[nChannel]|=EXSTAT_DATAERROR;
return FALSE;
}
else{
//pDE->TestCount[nChannel]++;
//if(pDE->nEat[nChannel]==0)
RtlCopyMemory(Buffer, pSector->MPEGData, BufLen);
//else{
// bReadSuccess=FALSE;
// pDE->nEat[nChannel]--;
//}
}
}
else{
if(pDE->nStillStuff[nChannel]>pDE->nStuffLimit[nChannel]){
DisableDataTransfer(pDE, nChannel);
bReadSuccess=FALSE;
pDE->nErrorRecover[nChannel]=ERR_RESTART;
pDE->ExStat[nChannel]|=EXSTAT_COMPSTOP;
pDE->nStillStuff[nChannel]=0;
return FALSE;
}
}
}
else{
//Following code copy all data including VCD header
if(pCurDesp->pData[0]!=0x00 ||
pCurDesp->pData[1]!=0xff)
bHasDSPBug = TRUE;
if(!bHasDSPBug)
RtlCopyMemory(Buffer, pCurDesp->pData, BufLen);
else{
RtlCopyMemory(Buffer+2, pCurDesp->pData, BufLen-2);
Buffer[0]=0x0;
Buffer[1]=0xff;
}
bReadSuccess = TRUE;
}
pCurDesp->Flags.datalen = 0;
pCurDesp->Flags.ownbit =0;
pAudioDespList->pReadPointer = pCurDesp->pNext;
if(TRUE == bReadSuccess)
break;
}while(1);
return TRUE;
}
static void DisableDataTransfer(PDEVICE_EXTENSION pDE, int nChannel)
{
if(nChannel==0){
pDE->IERValue &= ~0X8008;//disable A2 input interrupt
Ave2kWriteRegister(pDE,IER, pDE->IERValue);
Ave2kWriteRegister(pDE,MC1,0x00040000);//disable A2 input DMA
//init audio list
//InitAudioDespList(
// &pDE->AudioBufferList1,
// pDE->DataCommonBuffer1.BaseAddress,
// pDE->DespBuffer1,
// NUMOFAUDIODESCRIPTOR);
//init and start RPS
//StartAudioRPS(pDE, 0);
}
else{
pDE->IERValue &= ~0X2010;//disable A2 input interrupt
Ave2kWriteRegister(pDE,IER, pDE->IERValue);
Ave2kWriteRegister(pDE,MC1,0x00010000);//disable A1 input DMA
//init audio list
//InitAudioDespList(
// &pDE->AudioBufferList2,
// pDE->DataCommonBuffer2.BaseAddress,
// pDE->DespBuffer2,
// NUMOFAUDIODESCRIPTOR);
//init and start RPS
//StartAudioRPS(pDE, 1);
}
}
//These functions involve synchronously access audio buffer access
//This function is call in ISR to save received data to buffer list
//Revision 2: In this version, this function is only called to update descriptor, so they
//describes current status of DMA buffer
BOOLEAN SyncAudioWrite(PVOID SynchronizeContext)
{
PDEVICE_EXTENSION pDE;
PUCHAR DMAPointer; //Virtual address of current DMA pointer
ULONG CurOffset;
ULONG Distance; //distance between write pointer and current DMA pointer
PUCHAR LimitPointer;
PAUDIODESPLIST pDespList;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -