/*++ Copyright (c) 1995-1996 Microsoft Corporation Module Name: datapump.h Abstract: Contains constants and class declarations for the DataPump object. The DataPump controls the streaming of audio/video information between the network and the local record/playback source. It contains or references several subclasses that deal with the multimedia devices, compression apis, buffer streaming and the network transport. --*/ #ifndef _DATAPUMP_H_ #define _DATAPUMP_H_ #include "PacketSender.h" #include "imstream.h" #include "ThreadEvent.h" #include /* Assume 8 byte packing throughout */ typedef HANDLE DPHANDLE; //move this to nac.. #define MEDIA_ID_AUDIO 1 #define MEDIA_ID_VIDEO 2 #define DEF_SILENCE_LIMIT 10 #define DEF_MISSING_LIMIT 10 #define DP_PROP_DUPLEX_TYPE 100 // internal version of PROP_DUPLEX_TYPE // needs to be above the PROP_xxx range in iprop.h #define DP_MASK_PLATFORM 0xFF000000UL #define DP_FLAG_ACM 0x01000000UL #define DP_FLAG_QUARTZ 0x02000000UL #define DP_FLAG_MMSYSTEM 0x04000000UL #define DP_FLAG_AUDIO DP_FLAG_MMSYSTEM #define DP_FLAG_DIRECTSOUND 0x08000000UL #define DP_FLAG_VCM 0x10000000UL #define DP_FLAG_VIDEO 0x20000000UL #define DP_MASK_TRANSPORT 0x00F00000UL #define DP_FLAG_SEND 0x00100000UL #define DP_FLAG_RECV 0x00200000UL #define DP_MASK_DUPLEX 0x00030000UL #define DP_FLAG_HALF_DUPLEX 0x00010000UL #define DP_FLAG_FULL_DUPLEX 0x00020000UL #define DP_MASK_WAVE_DEVICE 0x00000300UL #define DP_FLAG_PLAY_CAP 0x00000100UL #define DP_FLAG_RECORD_CAP 0x00000200UL #define DP_MASK_VOICESWITCH 0x00007000UL // used to r/w mode of voice switching #define DP_FLAG_AUTO_SWITCH 0x00001000UL // MODE:normal operation #define DP_FLAG_MIC_ON 0x00002000UL // MODE:manual "talk" control #define DP_FLAG_MIC_OFF 0x00004000UL // MODE:"mute" #define DP_FLAG_AUTO_SILENCE_DETECT 0x00008000 // use auto thresholding (when auto-switching) // m_DPFlags is made up of the following plus some of the DP_XXX flags above #define DPFLAG_INITIALIZED 0x00000001 #define DPFLAG_STARTED_SEND 0x00000002 #define DPFLAG_STARTED_RECV 0x00000004 #define DPFLAG_CONFIGURED_SEND 0x00000008 #define DPFLAG_CONFIGURED_RECV 0x00000010 #define DPFLAG_ENABLE_PREVIEW 0x00000020 // preview mode (video) #define DPFLAG_AV_SYNC 0x00000040 // enable synchronization #define DPFLAG_REAL_THING 0x00000080 // Allows distinction between preview and real call in Configure/Unconfigure #define DPFLAG_ENABLE_SEND 0x00400000 // packets are recorded and sent #define DPFLAG_ENABLE_RECV 0x00800000 // packets are recved and played // ThreadFlags #define DPTFLAG_STOP_MASK 0xFF #define DPTFLAG_STOP_SEND 0x1 #define DPTFLAG_STOP_RECV 0x2 #define DPTFLAG_STOP_RECORD 0x4 #define DPTFLAG_STOP_PLAY 0x8 #define DPTFLAG_PAUSE_RECV 0x10 #define DPTFLAG_PAUSE_SEND 0x20 #define DPTFLAG_PAUSE_CAPTURE 0x40 #define DPTFLAG_SEND_PREAMBLE 0x100 // send I frames #define MAX_MMIO_PATH 128 // the number of times the device must "fail" before a // stream event notification gets sent #define MAX_FAILCOUNT 3 typedef struct tagMMIOSRC { BOOL fPlayFromFile; HMMIO hmmioSrc; MMCKINFO ckSrc; MMCKINFO ckSrcRIFF; DWORD dwDataLength; DWORD dwMaxDataLength; TCHAR szInputFileName[MAX_MMIO_PATH]; BOOL fLoop; BOOL fStart; BOOL fStop; BOOL fDisconnectAfterPlayback; WAVEFORMATEX wfx; } MMIOSRC; typedef struct tagMMIODEST { BOOL fRecordToFile; HMMIO hmmioDst; MMCKINFO ckDst; MMCKINFO ckDstRIFF; DWORD dwDataLength; DWORD dwMaxDataLength; TCHAR szOutputFileName[MAX_MMIO_PATH]; } MMIODEST; namespace AudioFile { HRESULT OpenSourceFile(MMIOSRC *pSrcFile, WAVEFORMATEX *pwf); HRESULT ReadSourceFile(MMIOSRC *pSrcFile, BYTE *pData, DWORD dwBytesToRead); HRESULT CloseSourceFile(MMIOSRC *pSrcFile); HRESULT OpenDestFile(MMIODEST *pDestFile, WAVEFORMATEX *pwf); HRESULT WriteDestFile(MMIODEST *pDestFile, BYTE *pData, DWORD dwBytesToWrite); HRESULT CloseDestFile(MMIODEST *pDestFile); }; extern HANDLE g_hEventHalfDuplex; #define MAX_TIMESTAMP 0xffffffffUL /* TTimeout is used to schedule a thread timeout notification and is used along with the ThreadTimer class. Derive from the TTimeOut abstract class by defining the TimeoutIndication virtual function and pass an instance of the derived class to ThreadTimer::SetTimeout() after setting the time interval. */ class TTimeout { public: TTimeout() {pNext = pPrev = this;} void SetDueTime(DWORD msWhen) {m_DueTime = msWhen;} DWORD GetDueTime(void) {return m_DueTime;} friend class ThreadTimer; private: class TTimeout *pNext; // ptrs for doubly-linked-list class TTimeout *pPrev; // DWORD m_DueTime; // absolute time when this will fire void InsertAfter(class TTimeout *pFirst) { pNext = pFirst->pNext; pPrev = pFirst; pFirst->pNext = this; pNext->pPrev = this; }; void Remove(void) { pNext->pPrev = pPrev; pPrev->pNext = pNext; pNext = this; // make next and prev self-referential so that Remove() is idempotent pPrev = this; } protected: virtual void TimeoutIndication() {}; }; /* Implements a mechanism for a worker thread to schedule timeouts. The client calls SetTimeout(TTimeout *) to schedule an interval callback and CancelTimeout() to cancel a scheduled timeout. The main loop of the worker thread must call UpdateTime(curTime) periodically, at which point any elapsed timeouts will be triggered. UpdateTime() returns the time when it next needs to be called, which is usually the time of the earliest scheduled timeout. NOTE: All methods are expected to be called from the same thread so there is no need for critical sections.. */ class ThreadTimer { public: void SetTimeout(TTimeout *pTObj); void CancelTimeout(TTimeout *pTObj); DWORD UpdateTime (DWORD curTime); private: TTimeout m_TimeoutList; DWORD m_CurTime; BOOL IsEmpty() {return (&m_TimeoutList == m_TimeoutList.pNext);} }; //flags for Start()/Stop() #define DP_STREAM_SEND 1 #define DP_STREAM_RECV 2 // Number of video frames used to compute QoS stats // We need at least 30 entries since the max frames // per sec capture rate is 30. 32 allows us to figure // out the integer stats per frame using a simple shift. #define NUM_QOS_VID_ENTRIES 32 // The sizes of the IP and UDP header added to each packet // need to be added to the size of the compressed packet #define IP_HEADER_SIZE 20 #define UDP_HEADER_SIZE 8 class MediaStream; class SendMediaStream; class RecvMediaStream; class DataPump : public IMediaChannelBuilder, public IVideoDevice, public IAudioDevice { friend class SendAudioStream; friend class RecvAudioStream; friend class RecvDSAudioStream; public: DataPump(); ~DataPump(); // IMediaChannelBuilder STDMETHODIMP Initialize(HWND hWnd, HINSTANCE hInst); STDMETHODIMP CreateMediaChannel(UINT flags, IMediaChannel **ppObj); STDMETHODIMP SetStreamEventObj(IStreamEventNotify *pNotify); // Internal void AddMediaChannel(UINT flags, IMediaChannel *pMediaChannel); void RemoveMediaChannel(UINT flags, IMediaChannel *pMediaChannel); HRESULT GetMediaChannelInterface(UINT flags, IMediaChannel **ppI); HRESULT StartReceiving(RecvMediaStream *pMS); HRESULT StopReceiving(RecvMediaStream *pMS); void ReleaseResources(); STDMETHODIMP StreamEvent(UINT uDirection, UINT uMediaType, UINT uEventType, UINT uSubCode); // IUnknown methods STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // IQOS interface pointer and two resources requests: one for BW and one for CPU LPIQOS m_pIQoS; // Recv thread timeout scheduler ThreadTimer m_RecvTimer; CRITICAL_SECTION m_crs; // serializes access to multithread-safe methods // the app handles are global static HWND m_hAppWnd; static HINSTANCE m_hAppInst; PacketSender m_PacketSender; ThreadEventProxy *m_pTEP; BOOL m_bDisableRSVP; // IVideoDevice Methods // Capture Device related methods HRESULT __stdcall GetNumCapDev(); HRESULT __stdcall GetMaxCapDevNameLen(); HRESULT __stdcall EnumCapDev(DWORD *pdwCapDevIDs, TCHAR *pszCapDevNames, DWORD dwNumCapDev); HRESULT __stdcall GetCurrCapDevID(); HRESULT __stdcall SetCurrCapDevID(int nCapDevID); // IAudioDevice Methods HRESULT __stdcall GetRecordID(UINT *puWaveDevID); HRESULT __stdcall SetRecordID(UINT uWaveDevID); HRESULT __stdcall GetPlaybackID(UINT *puWaveDevID); HRESULT __stdcall SetPlaybackID(UINT uWaveDevID); HRESULT __stdcall GetDuplex(BOOL *pbFullDuplex); HRESULT __stdcall SetDuplex(BOOL bFullDuplex); HRESULT __stdcall GetSilenceLevel(UINT *puLevel); HRESULT __stdcall SetSilenceLevel(UINT uLevel); HRESULT __stdcall GetAutoMix(BOOL *pbAutoMix); HRESULT __stdcall SetAutoMix(BOOL bAutoMix); HRESULT __stdcall GetDirectSound(BOOL *pbDS); HRESULT __stdcall SetDirectSound(BOOL bDS); HRESULT __stdcall GetMixer(HWND hwnd, BOOL bPlayback, IMixer **ppMixer); protected: struct MediaChannel { public: SendMediaStream *pSendStream; RecvMediaStream *pRecvStream; } m_Audio, m_Video; UINT m_uRef; // receive thread stuff HANDLE m_hRecvThread; DWORD m_RecvThId,m_nReceivers; HANDLE m_hRecvThreadAckEvent; // ack from recv thread // temp variables for communicating with recv thread HANDLE m_hRecvThreadSignalEvent; // signal to recv thread RecvMediaStream *m_pCurRecvStream; UINT m_CurRecvMsg; friend DWORD __stdcall StartDPRecvThread(PVOID pDP); // pDP == pointer to DataPump DWORD CommonRecvThread(void); DWORD CommonWS2RecvThread(void); HRESULT RecvThreadMessage(UINT msg, RecvMediaStream *pMS); HRESULT SetStreamDuplex(IMediaChannel *pStream, BOOL bFullDuplex); // datapump only needs to keep track of the device ID for // video. Gets a bit more complicated for Audio. UINT m_uVideoCaptureId; // IAudioDevice stuff UINT m_uWaveInID; UINT m_uWaveOutID; BOOL m_bFullDuplex; UINT m_uSilenceLevel; // 0-999 (manual) 1000- (automatic) BOOL m_bAutoMix; BOOL m_bDirectSound; }; // messages used to signal recv thread // must not conflict with message ids used by AsyncSock #define MSG_START_RECV (WM_USER + 20) #define MSG_STOP_RECV (WM_USER + 21) #define MSG_EXIT_RECV (WM_USER + 22) #define MSG_PLAY_SOUND (WM_USER + 23) #include /* End byte packing */ #endif //_DATAPUMP_H