windows-nt/Source/XPSP1/NT/drivers/wdm/dvd/mini/jbs/dmpeg.c

395 lines
8 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// MODULE : DMPEG.C
// PURPOSE : Entry point to lowlevel driver
// AUTHOR : JBS Yadawa
// CREATED : 7/20/96
//
//
// Copyright (C) 1996 SGS-THOMSON Microelectronics
//
//
// REVISION HISTORY :
//
// DATE :
//
// COMMENTS :
//
#include "common.h"
#include "dmpeg.h"
#include "memio.h"
#include "codedma.h"
#include "sti3520A.h"
#include "staudio.h"
#include "board.h"
#include "error.h"
#include "debug.h"
#include "i20reg.h"
#include "zac3.h"
#include "staudio.h"
#define CTRL_POWER_UP 0 // After reset
#define CTRL_INIT 1 // Initialisation + test of the decoders
#define CTRL_READY 2 // File openned
#define CTRL_INIT_SYNC 3 // Initial sync.: defines start of audio and video
#define CTRL_DECODE 4 // Normal decode
#define CTRL_IDLE 5 // idle state
#define SLOW_MODE 0
#define PLAY_MODE 1
#define FAST_MODE 2
CARD Card, *pCard = NULL;
CTRL Ctrl, *pCtrl;
DWORD OldlatchedSTC;
DWORD OldvideoPTS;
static BOOL Avsync;
static BOOL synchronizing;
static BYTE *tmpBuf;
static ULONG tmpBase;
static DWORD tmpAdr;
static BYTE I20Intr;
static BOOL IntCtrl(void);
static BYTE Irq;
BOOL dmpgOpen(ULONG Base, BYTE *DmaBuf, DWORD PhysicalAddress)
{
BOOL Found=FALSE;
tmpBuf = DmaBuf;
tmpBase = Base;
tmpAdr = PhysicalAddress;
if(!BoardOpen(Base))
{
DPF((Trace,"Board initialization failed!!\n"));
}
// Open Audio and Video
pCard = &Card;
pCard->pVideo = &(pCard->Video);
VideoOpen();
pCard->pAudio = &(pCard->Audio);
AudioOpen (pCard->pAudio);
pCtrl = &Ctrl;
pCtrl->ErrorMsg = NO_ERROR;
pCtrl->CtrlState = CTRL_POWER_UP;
pCtrl->AudioOn = FALSE;
pCtrl->VideoOn = FALSE;
Avsync = FALSE;
BoardDisableIRQ();
VideoInitDecoder(DUAL_PES);// Initialise video in PES by default
pCtrl->CtrlState = CTRL_INIT_SYNC;
VideoInitPesParser(VIDEO_STREAM);
InitAC3Decoder();
AudioInitPesParser(AUDIO_STREAM);
BoardEnableIRQ();
VideoMaskInt (); // Restore Video interrupt mask
DPF((Trace,"Calling Code DMA open!!\n"));
return CodeDmaOpen(DmaBuf, PhysicalAddress);
}
BOOL dmpgClose(void)
{
DPF((Trace,"dmpgClose!!\n"));
if(pCard == NULL)
return FALSE;
VideoClose( );
AudioClose( );
BoardClose();
CodeDmaClose();
return TRUE;
}
BOOL dmpgPlay()
{
DPF((Trace,"dmpgPlay!!\n"));
if(pCard == NULL)
return FALSE;
VideoRestoreInt (); // Restore Video interrupt mask
pCtrl->DecodeMode = PLAY_MODE;
AudioSetMode(pCtrl->DecodeMode, 0);
VideoSetMode(pCtrl->DecodeMode, 0);
if (pCtrl->CtrlState == CTRL_IDLE)
pCtrl->CtrlState = CTRL_DECODE;
VideoDecode();
AudioDecode();
AC3Command(AC3_UNMUTE); //ckw
AC3Command(AC3_PLAY); //ckw
AudioTransfer(TRUE); //ckw
return TRUE;
}
void dmpgReset(void)
{
dmpgPause();
dmpgSeek();
VideoMaskInt();
}
BOOL dmpgPause(void)
{
DPF((Trace,"dmpgPause!!\n"));
if(pCard == NULL)
return FALSE;
switch(pCtrl->CtrlState)
{
case CTRL_POWER_UP:
case CTRL_INIT:
case CTRL_READY:
break;
case CTRL_INIT_SYNC:
AudioPause();
VideoPause();
AudioTransfer(FALSE); //ckw
AC3Command(AC3_MUTE); //ckw
pCtrl->AudioOn = FALSE;
pCtrl->VideoOn = FALSE;
pCtrl->ActiveState = CTRL_INIT_SYNC;
pCtrl->CtrlState = CTRL_IDLE;
break;
case CTRL_DECODE:
AudioPause();
VideoPause();
AudioTransfer(FALSE); //ckw
AC3Command(AC3_MUTE); //ckw
pCtrl->ActiveState = CTRL_DECODE;
pCtrl->CtrlState = CTRL_IDLE;
break;
case CTRL_IDLE:
break;
}
return TRUE;
}
BOOL dmpgSeek(void)
{
DPF((Trace,"dmpgSeek!!\n"));
if(pCard == NULL)
return FALSE;
CodeDmaFlush();
pCtrl->CtrlState = CTRL_INIT_SYNC;
VideoSeekDecoder(DUAL_PES);
return TRUE;
}
BOOL dmpgStop(void)
{
DPF((Trace,"dmpgStop!!\n"));
if(pCard == NULL)
return FALSE;
VideoMaskInt();
dmpgPause();
// dmpgClose();
// dmpgOpen(tmpBase, tmpBuf, tmpAdr);
return TRUE;
}
UINT dmpgSendVideo(BYTE *pPacket, DWORD uLen)
{
// DPF((Trace,"dmpgSendVideo!!\n"));
UINT uRet;
if(pCard == NULL)
return FALSE;
uRet = (UINT)CodeDmaSendData(pPacket, uLen);
return uRet;
}
UINT dmpgSendAudio(BYTE *pPacket, DWORD uLen)
{
LONG abl, abf;
// DPF((Trace,"dmpgSendAudio!!\n"));
if(pCard == NULL)
return 0;
abl = VideoGetABL();
if((LONG)pCard->pVideo->AudioBufferSize - abl <= 2L)
{
// DebugPrint((DebugLevelTrace, "Audio Buffer FULL!!\n"));
return 0;
}
abf = (pCard->pVideo->AudioBufferSize - abl -1) << 8;
// DebugPrint((DebugLevelError,"SendAudio : %X %X %X %X %X %X, BBL = %x Size = %x\n",pPacket[0], pPacket[1], pPacket[2], pPacket[3], pPacket[4], pPacket[5], abl, pCard->pVideo->AudioBufferSize));
if(abf < uLen)
{
SendAC3Data(pPacket, abf);
return abf;
}
else
{
SendAC3Data(pPacket, uLen);
return uLen;
}
}
BOOL dmpgInterrupt(void)
{
BOOL bRet = FALSE;
I20Intr = memInByte(I20_INTRSTATUS);
memOutByte(I20_INTRSTATUS, I20Intr);
if(I20Intr & IFLAG_CODEDMA)
{
bRet = TRUE;
CodeDmaInterrupt();
}
if(I20Intr & IFLAG_GIRQ1)
{
bRet = TRUE;
IntCtrl();
}
return bRet;
}
void dmpgEnableIRQ()
{
DPF((Trace,"IrqEnabled!!\n"));
VideoRestoreInt();
BoardEnableIRQ();
}
void dmpgDisableIRQ()
{
DPF((Trace,"IrqDisabled!!\n"));
VideoMaskInt();
BoardDisableIRQ();
}
void CtrlInitSync(void)
{
switch (pCtrl->CtrlState) {
case CTRL_INIT_SYNC:
/*
Initial synchronisation: the video decoder is always started.
In case of system stream, the STC is initialised in interrupt with first
video PTS available the video state becomes VIDEO_DECODE
When the STC becomes equal (or higher) than the first Audio PTS the audio
decoding can be enabled
In case of Audio only bitstreams the video is stopped and audio enabled
In case of Video only bitstreams, the video decoding continues while
audio is disabled
*/
if (VideoGetState() == StateDecode) {
// the STC is initialized in interrupt with (first video PTS - 3 fields)
DWORD Stc;
DWORD PtsAudio;
Stc = AudioGetSTC();
if (AudioIsFirstPTS()) {
PtsAudio = AudioGetPTS();
// if (Stc >= PtsAudio)
{
// AudioDecode();
pCtrl->CtrlState = CTRL_DECODE;
}
}
}
pCtrl->ErrorMsg = VideoGetErrorMsg();
break;
case CTRL_DECODE: // Audio and Video decoders are running
if (pCtrl->ErrorMsg == NO_ERROR)
pCtrl->ErrorMsg = VideoGetErrorMsg();
if (pCtrl->ErrorMsg == NO_ERROR)
pCtrl->ErrorMsg = AudioGetErrorMsg();
break;
default :
break;
}
}
static BOOL IntCtrl(void)
{
long diff;
WORD lattency;
BOOL STIntr = FALSE;
BoardEnterInterrupt();
VideoMaskInt();
// AudioMaskInt();
// STIntr|=AudioAudioInt();
STIntr = VideoVideoInt();
if (Avsync) {
CtrlInitSync();
if (VideoIsFirstDTS()) {
// True only on the start of decode of the first picture with an assoicated valid PTS
DWORD FirstStc;
FirstStc = VideoGetFirstDTS();
AudioInitSTC(FirstStc);
synchronizing = 0;
}
if (AudioGetState() == AUDIO_DECODE) {
if (VideoIsFirstField()) {
synchronizing++;
if (synchronizing >= 20)
{
// We must verify the synchronisation of the video on the audio STC
DWORD latchedSTC, videoPTS;
WORD mode;
latchedSTC = AudioGetVideoSTC();
videoPTS = VideoGetPTS();
mode =pCard->pVideo->StreamInfo.displayMode;
lattency = 2200; /* 1.5 field duration for 60 Hz video */
if (mode == 0) {
lattency = 2700; /* 1.5 field duration for 50 Hz video */
}
diff = latchedSTC - videoPTS;
OldlatchedSTC = latchedSTC;
OldvideoPTS = videoPTS;
//---- If desynchronized
if (labs(diff) > (long)lattency) {
if (diff < 0)
{
VideoRepeat ();
}
else
{
VideoSkip ();
}
}
synchronizing = 0;
}
}
}
}
BoardLeaveInterrupt();
VideoRestoreInt();
// AudioRestoreInt();
return STIntr;
}