/*++ Copyright (c) 1995-1996 Microsoft Corporation Module Name: medistrm.h Abstract: Contains constants and class declarations for the abstract MediaStream object. A MediaStream represents a single unidirectional stream, such as a received Video channel. --*/ #ifndef _MEDISTRM_H_ #define _MEDISTRM_H_ #include "dtmf.h" #include /* Assume 8 byte packing throughout */ class DataPump; class TxStream; class RxStream; class AcmFilter; class VcmFilter; class MediaControl; class BufferPool; class AudioPacket; class VideoPacket; class SendMediaStream : public IMediaChannel { friend class SendAudioStream; protected: DataPump *m_pDP; TxStream *m_SendStream; MediaControl *m_InMedia; UINT m_CaptureDevice; // device id used for recording UINT m_PreviousCaptureDevice; // device id used for recording IRTPSession *m_Net; IRTPSend *m_pRTPSend; BYTE m_RTPPayload; // payload type //BufferPool *m_NetBufferPool; DWORD m_SendTimestamp; DWORD m_SavedTickCount; DWORD m_ThreadFlags; DWORD m_DPFlags; BOOL m_fSending; MEDIA_FORMAT_ID m_PrevFormatId; DWORD m_dwDstSize; FLOWSPEC m_flowspec; HRESULT SetFlowSpec(); HANDLE m_hCapturingThread; DWORD m_CaptureThId; CRITICAL_SECTION m_crsQos; // IQOS interface pointer and two resources requests: one for BW and one for CPU struct { int cResourceRequests; RESOURCEREQUEST aResourceRequest[2]; } m_aRRq; // Performance statistics struct { DWORD dwMsCap; // Capture CPU usage (ms) DWORD dwMsComp; // Compression CPU usage (ms) DWORD dwBits; // Compressed audio or video frame size (bits) DWORD dwCount; // Number of video frames captured or audio packets recorded DWORD dwOldestTs; // Oldest QoS callback timestamp DWORD dwNewestTs; // Most recent QoS callback timestamp HKEY hPerfKey; // Handle to CPU perf data collection reg key on Win95/98 DWORD dwSmoothedCPUUsage; // Previous CPU usage value - used to compute slow-varying average in CPU usage BOOL fWinNT; // Are we running on WinNT or Win95/98? struct { // Structure used to extract CPU usage performance on NT DWORD cbPerfData; PBYTE pbyPerfData; HANDLE hPerfData; LONGLONG llPerfTime100nSec; PLONGLONG pllCounterValue; DWORD dwProcessorIndex; DWORD dwPercentProcessorIndex; DWORD dwNumProcessors; } NtCPUUsage; } m_Stats; RTP_STATS m_RTPStats; // network stats public: SendMediaStream() { InitializeCriticalSection(&m_crsQos); }; virtual ~SendMediaStream() { DeleteCriticalSection(&m_crsQos); } // Implementation of IMediaChannel::GetState STDMETHODIMP_(DWORD) GetState() { if (m_DPFlags & DPFLAG_STARTED_SEND) return MSSTATE_STARTED; else if (m_DPFlags & DPFLAG_CONFIGURED_SEND) return MSSTATE_CONFIGURED; else return MSSTATE_UNCONFIGURED; } virtual HRESULT Initialize(DataPump *) = 0; virtual DWORD Send() = 0; virtual void EndSend() = 0; virtual HRESULT STDMETHODCALLTYPE SetNetworkInterface(IUnknown *pUnknown); } ; class RecvMediaStream : public IMediaChannel { friend class DataPump; friend BOOL RTPRecvCallback(DWORD_PTR,WSABUF *); protected: DataPump *m_pDP; RxStream *m_RecvStream; MediaControl *m_OutMedia; UINT m_RenderingDevice; // device id used for playback IRTPSession *m_Net; IRTPRecv *m_pIRTPRecv; //BufferPool *m_NetBufferPool; DWORD m_ThreadFlags; DWORD m_DPFlags; BOOL m_fReceiving; DWORD m_PlaybackTimestamp; // last played sample HANDLE m_hRecvThreadStopEvent; HANDLE m_hRenderingThread; DWORD m_RenderingThId; UINT m_nRecvBuffersPending; DWORD m_dwSrcSize; FLOWSPEC m_flowspec; HRESULT SetFlowSpec(); public: RecvMediaStream(){}; virtual HRESULT Initialize(DataPump *) = 0; virtual BOOL IsEmpty() = 0; // Implementation of IMediaChannel::GetState STDMETHODIMP_(DWORD) GetState() { if (m_DPFlags & DPFLAG_STARTED_RECV) return MSSTATE_STARTED; else if (m_DPFlags & DPFLAG_CONFIGURED_RECV) return MSSTATE_CONFIGURED; else return MSSTATE_UNCONFIGURED; } virtual HRESULT RTPCallback(WSABUF *pWsaBuf, DWORD timestamp, UINT seq, UINT fMark)=0; virtual HRESULT GetCurrentPlayNTPTime(NTP_TS *)=0; virtual HRESULT StartRecv(HWND)=0; virtual HRESULT StopRecv()=0; virtual HRESULT STDMETHODCALLTYPE SetNetworkInterface(IUnknown *pUnknown); virtual HRESULT DTMFBeep() {return S_OK;} virtual HRESULT OnDTMFBeep() {return S_OK;} }; class SendVideoStream : public SendMediaStream, public IVideoRender, public IVideoChannel { friend class DataPump; protected: CCaptureChain* m_pCaptureChain; VIDEOFORMATEX m_fDevSend; VIDEOFORMATEX m_fCodecOutput; RECT m_cliprect; DWORD m_maxfps; DWORD m_frametime; int *m_pTSTable; // NULL if table isn't used DWORD m_dwCurrentTSSetting; VcmFilter *m_pVideoFilter; IUnknown *m_pIUnknown; // Pointer to IUnkown from which we'll query the Stream Signal interface class MediaPacket *m_pNextPacketToRender; // current recv video frame UINT m_cRendering; // count of packets given out by GetFrame() HANDLE m_hRenderEvent; // IVideoRender event for recv notification LPFNFRAMEREADY m_pfFrameReadyCallback; // callback function CRITICAL_SECTION m_crs; CRITICAL_SECTION m_crsVidQoS; // Allows QoS thread to read the video statistics while capture and compression are running // the capture thread (and it's launch function) static DWORD CALLBACK StartCaptureThread(LPVOID pVoid); DWORD CapturingThread(); HRESULT SendPacket(VideoPacket *pVP, UINT *puBytesSent); STDMETHODIMP_(void) UnConfigure(void); LONG m_lRefCount; public: SendVideoStream(): SendMediaStream(){m_Net=NULL; m_lRefCount=0; }; virtual ~SendVideoStream(); // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(void); virtual ULONG STDMETHODCALLTYPE Release(void); // IMediaChannel APIs // new version of Configure() HRESULT STDMETHODCALLTYPE Configure( BYTE *pFormat, UINT cbFormat, BYTE *pChannelParams, UINT cbParams, IUnknown *pUnknown); STDMETHODIMP Start(void); STDMETHODIMP Stop(void); HRESULT STDMETHODCALLTYPE SetNetworkInterface(IUnknown *pUnknown) { return SendMediaStream::SetNetworkInterface(pUnknown); } STDMETHODIMP_(DWORD) GetState() { return SendMediaStream::GetState(); } HRESULT STDMETHODCALLTYPE SetMaxBitrate(UINT uMaxBitrate); // IVideoChannel virtual HRESULT __stdcall SetTemporalSpatialTradeOff(DWORD dwVal); virtual HRESULT __stdcall GetTemporalSpatialTradeOff(DWORD *pdwVal); virtual HRESULT __stdcall SendKeyFrame(void); virtual HRESULT __stdcall ShowDeviceDialog(DWORD dwFlags); virtual HRESULT __stdcall GetDeviceDialog(DWORD *pdwFlags); // IProperty methods STDMETHODIMP GetProperty(DWORD dwProp, PVOID pBuf, LPUINT pcbBuf); STDMETHODIMP SetProperty(DWORD dwProp, PVOID pBuf, UINT cbBuf); // IVideoRender methods STDMETHODIMP Init( DWORD_PTR dwUser, LPFNFRAMEREADY pfCallback); STDMETHODIMP Done(void); STDMETHODIMP GetFrame(FRAMECONTEXT* pfc); STDMETHODIMP ReleaseFrame(FRAMECONTEXT *pfc); // Other virtual methods virtual HRESULT Initialize(DataPump *); // Non virtual methods static HRESULT CALLBACK QosNotifyVideoCB(LPRESOURCEREQUESTLIST lpResourceRequestList, DWORD_PTR dwThis); void UnConfigureSendVideo(BOOL fNewDeviceSettings, BOOL fNewDevice); void StartCPUUsageCollection(void); BOOL GetCPUUsage(PDWORD pdwOverallCPUUsage); void StopCPUUsageCollection(void); BOOL SetTargetRates(DWORD dwTargetFrameRate, DWORD dwTargetBitrate); DWORD Send(); void EndSend(); }; class RecvVideoStream : public RecvMediaStream, public IVideoRender { friend class DataPump; protected: VIDEOFORMATEX m_fDevRecv; RECT m_cliprect; class MediaPacket *m_pNextPacketToRender; // current recv video frame UINT m_cRendering; // count of packets given out by GetFrame() HANDLE m_hRenderEvent; // IVideoRender event for recv notification LPFNFRAMEREADY m_pfFrameReadyCallback; // callback function CRITICAL_SECTION m_crs; VcmFilter *m_pVideoFilter; IUnknown *m_pIUnknown; // Pointer to IUnkown from which we'll query the Stream Signal interface IStreamSignal *m_pIStreamSignal; // Pointer to I-Frame request interface CRITICAL_SECTION m_crsIStreamSignal; // Used to serialize access to the interface between Stop() and the RTP callback UINT m_ulLastSeq; // Last received RTP sequence number DWORD m_dwLastIFrameRequest; // When was the last I-frame request sent? Used to make sure we don't send requests too often BOOL m_fDiscontinuity; // Signals that a discontinuity (RTP packet lost or receive frame buffer overflow) was detected CRITICAL_SECTION m_crsVidQoS; // Allows QoS thread to read the video statistics while capture and compression are running static DWORD CALLBACK StartRenderingThread(PVOID pVoid); DWORD RenderingThread(); STDMETHODIMP_(void) UnConfigure(void); LONG m_lRefCount; public: RecvVideoStream() : RecvMediaStream(){m_Net=NULL; m_lRefCount=0; }; virtual ~RecvVideoStream(); // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(void); virtual ULONG STDMETHODCALLTYPE Release(void); // IMediaChannel APIs HRESULT STDMETHODCALLTYPE Configure( BYTE *pFormat, UINT cbFormat, BYTE *pChannelParams, UINT cbParams, IUnknown *pUnknown); STDMETHODIMP Start(void); STDMETHODIMP Stop(void); HRESULT STDMETHODCALLTYPE SetMaxBitrate(UINT uMaxBitrate) { return E_NOTIMPL; } // IProperty methods STDMETHODIMP GetProperty(DWORD dwProp, PVOID pBuf, LPUINT pcbBuf); STDMETHODIMP SetProperty(DWORD dwProp, PVOID pBuf, UINT cbBuf); // IVideoRender methods STDMETHODIMP Init( DWORD_PTR dwUser, LPFNFRAMEREADY pfCallback); STDMETHODIMP Done(void); STDMETHODIMP GetFrame(FRAMECONTEXT* pfc); STDMETHODIMP ReleaseFrame(FRAMECONTEXT *pfc); // Other virtual methods virtual HRESULT Initialize(DataPump *); virtual BOOL IsEmpty(); HRESULT GetCurrentPlayNTPTime(NTP_TS *); virtual HRESULT StartRecv(HWND); virtual HRESULT StopRecv(); virtual HRESULT RTPCallback(WSABUF *pWsaBuf, DWORD timestamp, UINT seq, UINT fMark); // Non virtual methods }; extern char LogScale[]; class AudioSilenceDetector { private: UINT m_uManualSilenceLevel; // silence level in unit of 1/1000 DWORD m_dwMaxStrength; // signal strength in units of 1/1000 INT m_iSilenceLevel; // adaptive silence threshold INT m_iSilenceAvg; // scale factor 256 INT m_iTalkAvg; // average strength of non-silent signal public: AudioSilenceDetector(); void SetSilenceLevel(UINT level) {m_uManualSilenceLevel = level;} UINT GetSilenceLevel(void) {return m_uManualSilenceLevel;} UINT GetSignalStrength(void) {return LogScale[m_dwMaxStrength >> 8];} BOOL SilenceDetect(WORD strength); }; class SendAudioStream : public SendMediaStream, public IAudioChannel, public IDTMFSend { friend class DataPump; private: WAVEFORMATEX m_fDevSend; WAVEFORMATEX m_wfCompressed; AcmFilter *m_pAudioFilter; // this will replace m_fSendFilter MMIOSRC m_mmioSrc; AudioSilenceDetector m_AudioMonitor; BOOL m_bAutoMix; static DWORD CALLBACK StartRecordingThread (LPVOID pVoid); DWORD RecordingThread(); HRESULT SendPacket(AudioPacket *pAP, UINT *puBytesSent); STDMETHODIMP_(void) UnConfigure(void); LONG m_lRefCount; DTMFQueue *m_pDTMF; HRESULT __stdcall SendDTMF(); public: SendAudioStream() : SendMediaStream(){m_Net=NULL;m_lRefCount=0;}; virtual ~SendAudioStream(); // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(void); virtual ULONG STDMETHODCALLTYPE Release(void); // IMediaChannel APIs // new version of Configure() HRESULT STDMETHODCALLTYPE Configure( BYTE *pFormat, UINT cbFormat, BYTE *pChannelParams, UINT cbParams, IUnknown *pUnknown); STDMETHODIMP Start(void); STDMETHODIMP Stop(void); HRESULT STDMETHODCALLTYPE SetNetworkInterface(IUnknown *pUnknown) { return SendMediaStream::SetNetworkInterface(pUnknown); } STDMETHODIMP_(DWORD) GetState() { return SendMediaStream::GetState(); } HRESULT STDMETHODCALLTYPE SetMaxBitrate(UINT uMaxBitrate); // IAudioChannel STDMETHODIMP GetSignalLevel(UINT *pSignalStrength); // IDTMFSend virtual HRESULT __stdcall AddDigit(int nDigit); virtual HRESULT __stdcall ResetDTMF(); // IProperty methods STDMETHODIMP GetProperty(DWORD dwProp, PVOID pBuf, LPUINT pcbBuf); STDMETHODIMP SetProperty(DWORD dwProp, PVOID pBuf, UINT cbBuf); // Other virtual methods virtual HRESULT Initialize(DataPump *pdp); // Non virtual methods static HRESULT CALLBACK QosNotifyAudioCB(LPRESOURCEREQUESTLIST lpResourceRequestList, DWORD_PTR dwThis); HRESULT OpenSrcFile (void); HRESULT CloseSrcFile (void); DWORD Send(); void EndSend(); }; class RecvAudioStream : public RecvMediaStream, public IAudioChannel { friend class DataPump; private: WAVEFORMATEX m_fDevRecv; IAppAudioCap* m_pAudioCaps; // pointer to the audio capabilities object // mmio file operations MMIODEST m_mmioDest; AcmFilter *m_pAudioFilter; // this will replace m_fSendFilter AudioSilenceDetector m_AudioMonitor; CRITICAL_SECTION m_crsAudQoS; // Allows QoS thread to read the audio statistics while recording and compression are running static DWORD CALLBACK StartPlaybackThread(LPVOID pVoid); DWORD PlaybackThread(); STDMETHODIMP_(void) UnConfigure(void); LONG m_lRefCount; virtual HRESULT DTMFBeep(); public: RecvAudioStream() :RecvMediaStream(){m_Net=NULL;m_lRefCount=0;}; virtual ~RecvAudioStream(); // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(void); virtual ULONG STDMETHODCALLTYPE Release(void); // IMediaChannel APIs HRESULT STDMETHODCALLTYPE Configure( BYTE *pFormat, UINT cbFormat, BYTE *pChannelParams, UINT cbParams, IUnknown *pUnknown); STDMETHODIMP Start(void); STDMETHODIMP Stop(void); HRESULT STDMETHODCALLTYPE SetNetworkInterface(IUnknown *pUnknown) { return RecvMediaStream::SetNetworkInterface(pUnknown); } STDMETHODIMP_(DWORD) GetState() { return RecvMediaStream::GetState(); } HRESULT STDMETHODCALLTYPE SetMaxBitrate(UINT uMaxBitrate) { return E_NOTIMPL; } // IAudioChannel STDMETHODIMP GetSignalLevel(UINT *pSignalStrength); // IProperty methods STDMETHODIMP GetProperty(DWORD dwProp, PVOID pBuf, LPUINT pcbBuf); STDMETHODIMP SetProperty(DWORD dwProp, PVOID pBuf, UINT cbBuf); // Other virtual inherited methods virtual HRESULT Initialize(DataPump *); virtual BOOL IsEmpty(); HRESULT GetCurrentPlayNTPTime(NTP_TS *); virtual HRESULT StartRecv(HWND); virtual HRESULT StopRecv(); virtual HRESULT RTPCallback(WSABUF *pWsaBuf, DWORD timestamp, UINT seq, UINT fMark); }; #include /* End byte packing */ #endif // _MEDISTRM_H_