|
|
// $Header: G:/SwDev/WDM/Video/bt848/rcs/Field.h 1.12 1998/05/08 18:18:51 tomz Exp $
#ifndef __FIELD_H
#define __FIELD_H
/* Type: VideoStream
* Purpose: Identifies a video stream channel * Note: Not all of these are used today. It should be a fairly minor job to * start using them, though */ typedef enum { VS_Below = -1, VS_Field1, VS_Field2, VS_VBI1, VS_VBI2, VS_Analog, VS_CC, VS_EDS, VS_Raw, VS_Above } VideoStream;
#define STREAM_IDX_CAPTURE 0
#define STREAM_IDX_PREVIEW 1
#define STREAM_IDX_VBI 2
#define STREAM_IDX_ANALOG 3
#include "mytypes.h"
#include "scaler.h"
#include "pscolspc.h"
#include "viddefs.h"
#include "queue.h"
#include "preg.h"
#include "chanifac.h"
const MaxProgsForField = 2;
typedef Queue<DataBuf> VidBufQueue;
/* Class: Field
* Purpose: Encapsulates the operation of a single video field provided by BtPisces * Attributes: * Operations: */
extern "C" VOID STREAMAPI AdapterCancelPacket(IN PHW_STREAM_REQUEST_BLOCK Srb);
class Field { private: PsColorSpace LocalColSpace_; VidBufQueue *BufQue_; DWORD dwPitch_; bool Started_; int SkipCount_; long TimePerFrame_; LONGLONG LapsedTime_; LONG FrameTiming_; VideoStream VidStrm_;
// used to notify video channel
ChanIface *callback_;
bool Paired_; bool ready_;
// this is used by the video channel to report timestamps
LONGLONG InterruptCounter_; LONGLONG FrameCounter_;
RegField &CaptureEnable_;
public:
bool Interrupt_;
Field( RegField &CapEn, RegBase *ColReg, RegBase *WordSwap, RegBase *ByteSwap ); virtual ~Field() {}
inline void CancelSrbList( ) { while( !BufQue_->IsEmpty( ) ) { DataBuf buf = BufQue_->Get(); AdapterCancelPacket( buf.pSrb_ ); }
BufQue_->Flush(); }
void Notify( PVOID pTag, bool skipped ) { if ( callback_ ) callback_->Notify( pTag, skipped ); }
void SetStreamID( VideoStream ); VideoStream GetStreamID();
void ResetCounters();
virtual ErrorCode SetAnalogWindow( MRect &r ) = 0; virtual void GetAnalogWindow( MRect &r ) = 0;
virtual ErrorCode SetDigitalWindow( MRect &r ) = 0; virtual void GetDigitalWindow( MRect &r ) = 0;
void SetBufPitch( DWORD dwP ) { dwPitch_ = dwP; DebugOut((1, "SetBufPitch(%d)\n", dwPitch_)); } DWORD GetBufPitch() { return dwPitch_; }
virtual void SetColorFormat( ColFmt aColor ) { LocalColSpace_.SetColorFormat( aColor ); }
virtual ColFmt GetColorFormat() { return LocalColSpace_.GetColorFormat(); }
DataBuf GetNextBuffer();
void SetFrameRate( long time ); void SetPaired( bool p ); bool GetPaired();
void SetReady( bool flag ); bool GetReady();
void SetBufQuePtr( VidBufQueue *pQ ) { BufQue_ = pQ; } VidBufQueue &GetCurrentQue() { return *BufQue_; }
void SetCallback( ChanIface *iface ) { callback_ = iface;}
State Start(); void Stop(); bool IsStarted() { return Started_; }
State Skip();
// called by the BtPiscess::ProcessRISCIntr()
void GotInterrupt() { InterruptCounter_++; }
void GetCounters( LONGLONG &FrameNo, LONGLONG &drop );
void SetStandardTiming( LONG t ); LONG GetStandardTiming();
};
/* Class: FieldWithScaler
* Purpose: Adds scaling capability to a field * Attributes: * Operations: */ class FieldWithScaler : public Field { private: Scaler LocalScaler_;
public: FieldWithScaler( RegField &CapEn, VidField field, RegBase *ColReg, RegBase *WordSwap, RegBase *ByteSwap ) : LocalScaler_( field ), Field( CapEn, ColReg, WordSwap, ByteSwap ) {}
virtual ErrorCode SetAnalogWindow( MRect &r ) { return LocalScaler_.SetAnalogWin( r ); } virtual void GetAnalogWindow( MRect &r ) { LocalScaler_.GetAnalogWin( r ); }
virtual ErrorCode SetDigitalWindow( MRect &r ) { return LocalScaler_.SetDigitalWin( r ); } virtual void GetDigitalWindow( MRect &r ) { LocalScaler_.GetDigitalWin( r ); }
void VideoFormatChanged( VideoFormat format ); void TurnVFilter( State s ); };
/* Class: VBIField
* Purpose: Encapsulates the operation of a VBI data 'field' * Attributes: * Operations: */ class VBIField : public Field { private: DECLARE_VBIPACKETSIZE; DECLARE_VBIDELAY;
MRect AnalogWin_; MRect DigitalWin_;
public: VBIField( RegField &CapEn ) : Field( CapEn, NULL, NULL, NULL ), CONSTRUCT_VBIPACKETSIZE, CONSTRUCT_VBIDELAY {}
virtual void SetColorFormat( ColFmt ) {} virtual ColFmt GetColorFormat() { return CF_VBI; };
virtual ErrorCode SetAnalogWindow( MRect &r ) { AnalogWin_ = r; return Success; } virtual void GetAnalogWindow( MRect &r ) { r = AnalogWin_; }
virtual ErrorCode SetDigitalWindow( MRect &r ) { DigitalWin_ = r; DWORD dwNoOfDWORDs = r.Width() / 4; // SetBufPitch( r.Width() * ColorSpace( CF_VBI ).GetBitCount() / 8 );
VBI_PKT_LO = (BYTE)dwNoOfDWORDs; VBI_PKT_HI = dwNoOfDWORDs > 0xff; // set the 9th bit
VBI_HDELAY = r.left; return Success; } virtual void GetDigitalWindow( MRect &r ) { r = DigitalWin_; }
~VBIField() {} };
inline Field::Field( RegField &CapEn, RegBase *ColReg, RegBase *WordSwap, RegBase *ByteSwap ) : SkipCount_( 0 ), CaptureEnable_( CapEn ), LocalColSpace_( CF_RGB32, *ColReg, *WordSwap, *ByteSwap ), Started_( false ), callback_( NULL ), BufQue_( NULL ), dwPitch_( 0 ), TimePerFrame_( 333667 ), LapsedTime_( 0 ),InterruptCounter_( 0 ), FrameCounter_( 0 ), Interrupt_( true ), FrameTiming_( 333667 ) { }
/* Method: Field::SetFrameRate
* Purpose: Sets frame rate * Input: time: long, time in 100s nanoseconds per frame */ inline void Field::SetFrameRate( long time ) { TimePerFrame_ = time;
// this is needed to make sure very first get returns a buffer
LapsedTime_ = time; }
inline void Field::SetStreamID( VideoStream st ) { VidStrm_ = st; }
inline VideoStream Field::GetStreamID() { return VidStrm_; }
inline void Field::SetPaired( bool p ) { Paired_ = p; }
inline bool Field::GetPaired() { return Paired_; }
inline void Field::GetCounters( LONGLONG &FrameNo, LONGLONG &drop ) { // Frame number is what frame index we should be on.
// Use interrupt count, not just frames returned.
FrameNo = InterruptCounter_;
// Drop count = number of interrupts - number of completed buffers
drop = InterruptCounter_ - FrameCounter_; if ( drop > 0 ) { drop--;
// We've reported the drops, so show frame count as caught
// up to interrupt count
FrameCounter_ += drop; DebugOut((1, "%d,", drop)); } else if ( drop < 0 ) { DebugOut((1, "*** %d ***,", drop)); } else { DebugOut((1, "0,")); } }
inline void Field::ResetCounters() { FrameCounter_ = InterruptCounter_ = 0; }
inline void Field::SetReady( bool flag ) { ready_ = flag; }
inline bool Field::GetReady() { return ready_; }
inline void Field::SetStandardTiming( LONG t ) { FrameTiming_ = t; }
inline LONG Field::GetStandardTiming() { return FrameTiming_; }
/* Method: Field::GetNextBuffer
* Purpose: Returns next buffer from the queue, if time is correct for it. * Input: None */ inline DataBuf Field::GetNextBuffer() { // that's how long it takes to capture a frame of video
LapsedTime_ += GetStandardTiming(); DataBuf buf;
// [TMZ] [!!!] - hack, disable wait 'cause it doesn't work
//if ( LapsedTime_ >= TimePerFrame_ ) {
if ( 1 ) {
// have to increment the frame number if we want that frame only
if ( IsStarted() ) { GotInterrupt(); }
//#define FORCE_BUFFER_SKIP_TESTING
#ifdef FORCE_BUFFER_SKIP_TESTING
static int iTestSkip = 0; BOOL bEmpty = BufQue_->IsEmpty(); DebugOut((0, "Queue(%x) bEmpty = %d\n", BufQue_, bEmpty)); if ( iTestSkip++ & 1 ) { // Every other query should look like the buffer is empty.
bEmpty = TRUE; DebugOut((1, " [override] set bEmpty = %d\n", bEmpty)); } if ( !bEmpty ) { buf = BufQue_->Get(); DebugOut((1, " GotBuf addr %X\n", buf.pData_ ) ); LapsedTime_ = 0; FrameCounter_++; } else { DebugOut((1, " No buffer in que at %d\n",LapsedTime_)); if ( !IsStarted() ) { InterruptCounter_--; FrameCounter_--; } } #else
if ( !BufQue_->IsEmpty() ) { buf = BufQue_->Get(); DebugOut((1, "GotBuf addr %X\n", buf.pData_ ) ); LapsedTime_ = 0; FrameCounter_++; } else { DebugOut((1, "No buffer in que at %d\n",LapsedTime_)); if ( !IsStarted() ) { InterruptCounter_--; FrameCounter_--; } } #endif
} DebugOut((1, "returning buf {pSrb=%x, pData=%x}\n", buf.pSrb_, buf.pData_ ) ); return buf; }
/* Method: Field::Start
* Purpose: Initiates the data flow out of decoder into the FIFO * Input: None * Output: State: Off if channel was off; On if channel was on */ inline State Field::Start() { Trace t("Field::Start()");
Started_ = true; State RetVal = SkipCount_ >= MaxProgsForField ? Off : On; SkipCount_--; if ( SkipCount_ < 0 ) SkipCount_ = 0; CaptureEnable_ = On; return RetVal; }
inline void Field::Stop() { Trace t("Field::Stop()");
Started_ = false; CaptureEnable_ = Off; LapsedTime_ = TimePerFrame_; }
/* Method: Field::Skip
* Purpose: Increments the skip count and stops the data flow if it exceeds the max * Input: None * Output: State: Off if channel is stopped; On if channel remains running */ inline State Field::Skip() { Trace t("Field::Skip()");
SkipCount_++; if ( SkipCount_ >= MaxProgsForField ) { Stop(); return Off; } return On; }
inline void FieldWithScaler::VideoFormatChanged( VideoFormat format ) { LocalScaler_.VideoFormatChanged( format ); }
inline void FieldWithScaler::TurnVFilter( State s ) { LocalScaler_.TurnVFilter( s ); }
#endif
|