⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiostream.c

📁 driver wdk
💻 C
📖 第 1 页 / 共 3 页
字号:
//
//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 + -