Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

884 lines
29 KiB

  1. // Copyright (c) 1994 - 1999 Microsoft Corporation. All Rights Reserved.
  2. //
  3. // implements Video capture using Win95 16 bit capture drivers
  4. //
  5. extern const AMOVIESETUP_FILTER sudVFWCapture ;
  6. // forward declarations
  7. class CCapStream; // the filter's video stream output pin
  8. class CCapOverlay; // the filter's overlay preview pin
  9. class CCapPreview; // the filter's non-overlay preview pin
  10. class CVfwCapture; // the filter class
  11. // this structure contains all settings of the capture
  12. // filter that are user settable
  13. //
  14. typedef struct _vfwcaptureoptions {
  15. UINT uVideoID; // id of video driver to open
  16. DWORD dwTimeLimit; // stop capturing at this time???
  17. DWORD dwTickScale; // frame rate rational
  18. DWORD dwTickRate; // frame rate = dwRate/dwScale in ticks/sec
  19. DWORD usPerFrame; // frame rate expressed in microseconds per frame
  20. DWORD dwLatency; // time added for latency, in 100ns units
  21. UINT nMinBuffers; // number of buffers to use for capture
  22. UINT nMaxBuffers; // number of buffers to use for capture
  23. UINT cbFormat; // sizeof VIDEOINFO stuff
  24. VIDEOINFOHEADER * pvi; // pointer to VIDEOINFOHEADER (media type)
  25. } VFWCAPTUREOPTIONS;
  26. #define NUM_DROPPED 100 // remember 100 of them
  27. typedef struct _capturestats {
  28. DWORDLONG dwlNumDropped;
  29. DWORDLONG dwlDropped[NUM_DROPPED];
  30. DWORDLONG dwlNumCaptured;
  31. DWORDLONG dwlTotalBytes;
  32. DWORDLONG msCaptureTime;
  33. double flFrameRateAchieved;
  34. double flDataRateAchieved;
  35. } CAPTURESTATS;
  36. #if 0 // -- moved to uuids.h
  37. DEFINE_GUID(CLSID_CaptureProperties,
  38. 0x1B544c22, 0xFD0B, 0x11ce, 0x8C, 0x63, 0x00, 0xAA, 0x00, 0x44, 0xB5, 0x1F);
  39. #endif
  40. DEFINE_GUID(IID_VfwCaptureOptions,
  41. 0x1B544c22, 0xFD0B, 0x11ce, 0x8C, 0x63, 0x00, 0xAA, 0x00, 0x44, 0xB5, 0x20);
  42. DECLARE_INTERFACE_(IVfwCaptureOptions,IUnknown)
  43. {
  44. // IUnknown methods
  45. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppv) PURE;
  46. STDMETHOD_(ULONG,AddRef)(THIS) PURE;
  47. STDMETHOD_(ULONG,Release)(THIS) PURE;
  48. // IVfwCaptureOptions methods
  49. STDMETHOD(VfwCapSetOptions)(THIS_ const VFWCAPTUREOPTIONS * pOpt) PURE;
  50. STDMETHOD(VfwCapGetOptions)(THIS_ VFWCAPTUREOPTIONS * pOpt) PURE;
  51. STDMETHOD(VfwCapGetCaptureStats)(THIS_ CAPTURESTATS * pcs) PURE;
  52. STDMETHOD(VfwCapDriverDialog)(THIS_ HWND hwnd, UINT uDrvType, UINT uQuery) PURE;
  53. };
  54. #define STUPID_COMPILER_BUG
  55. //
  56. // CVfwCapture represents an video capture driver
  57. //
  58. // -- IBaseFilter
  59. // -- IMediaFilter
  60. // -- ISpecifyPropertyPages
  61. // -- IVfwCaptureOptions
  62. //
  63. // UNTESTED code to make the h/w overlay pin support stream control
  64. // (unnecessary since overlay is supposedly free)
  65. // #define OVERLAY_SC
  66. class CVfwCapture :
  67. public CBaseFilter,
  68. public IPersistPropertyBag,
  69. public IAMVfwCaptureDialogs,
  70. public CPersistStream,
  71. public IAMFilterMiscFlags
  72. {
  73. public:
  74. // constructors etc
  75. CVfwCapture(TCHAR *, LPUNKNOWN, HRESULT *);
  76. ~CVfwCapture();
  77. // create a new instance of this class
  78. static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *);
  79. // override this to say what interfaces we support where
  80. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  81. DECLARE_IUNKNOWN
  82. public:
  83. // IAMVfwCaptureDialogs stuff
  84. STDMETHODIMP HasDialog(int iDialog);
  85. STDMETHODIMP ShowDialog(int iDialog, HWND hwnd);
  86. STDMETHODIMP SendDriverMessage(int iDialog, int uMsg, long dw1, long dw2);
  87. // pin enumerator calls this
  88. //
  89. int GetPinCount();
  90. CBasePin * GetPin(int ix);
  91. // override RUN so that we can pass it on to the streams
  92. // (the base class just calls Active/Inactive for each stream)
  93. //
  94. STDMETHODIMP Run(REFERENCE_TIME tStart);
  95. // override PAUSE so that we can know when we transition from RUN->PAUSE
  96. //
  97. STDMETHODIMP Pause();
  98. // override STOP because the base class is broken
  99. //
  100. STDMETHODIMP Stop();
  101. // override GetState to return VFW_S_CANT_CUE when pausing
  102. //
  103. STDMETHODIMP GetState(DWORD dwMSecs, FILTER_STATE *State);
  104. // for IAMStreamControl
  105. STDMETHODIMP SetSyncSource(IReferenceClock *pClock);
  106. STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
  107. // IPersistPropertyBag methods
  108. STDMETHOD(InitNew)(THIS);
  109. STDMETHOD(Load)(THIS_ LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog);
  110. STDMETHOD(Save)(THIS_ LPPROPERTYBAG pPropBag, BOOL fClearDirty,
  111. BOOL fSaveAllProperties);
  112. STDMETHODIMP GetClassID(CLSID *pClsid);
  113. // CPersistStream
  114. HRESULT WriteToStream(IStream *pStream);
  115. HRESULT ReadFromStream(IStream *pStream);
  116. int SizeMax();
  117. // STDMETHODIMP GetClassID(CLSID *pClsid);
  118. // IAMFilterMiscFlags to indicate that we're a source (really a push source)
  119. ULONG STDMETHODCALLTYPE GetMiscFlags(void) { return AM_FILTER_MISC_FLAGS_IS_SOURCE; }
  120. // --------- Nested implementation classes ----------
  121. class CSpecifyProp : public CUnknown, public ISpecifyPropertyPages
  122. {
  123. CVfwCapture * m_pCap; // parent CVfwCapture class
  124. public:
  125. // constructor
  126. //
  127. CSpecifyProp (CVfwCapture * pCap, HRESULT *phr) :
  128. CUnknown(NAME("SpecifyPropertyPages"), pCap->GetOwner(), phr),
  129. m_pCap(pCap)
  130. {
  131. };
  132. DECLARE_IUNKNOWN
  133. // ISpecifyPropertyPages methods
  134. //
  135. STDMETHODIMP GetPages(CAUUID *pPages);
  136. };
  137. class COptions : public CUnknown, public IVfwCaptureOptions
  138. {
  139. CVfwCapture * m_pCap; // parent CVfwCapture class
  140. public:
  141. // constructor
  142. //
  143. COptions (CVfwCapture * pCap, HRESULT *phr) :
  144. CUnknown(NAME("Options"), pCap->GetOwner(), phr),
  145. m_pCap(pCap)
  146. {
  147. };
  148. DECLARE_IUNKNOWN
  149. // these interfaces allow property pages to get
  150. // and set the user editable settings for us
  151. //
  152. STDMETHODIMP VfwCapSetOptions(const VFWCAPTUREOPTIONS * pOpt);
  153. STDMETHODIMP VfwCapGetOptions(VFWCAPTUREOPTIONS * pOpt);
  154. STDMETHODIMP VfwCapGetCaptureStats(CAPTURESTATS * pcs);
  155. STDMETHODIMP VfwCapDriverDialog(HWND hwnd, UINT uType, UINT uQuery);
  156. };
  157. // -------- End of nested interfaces -------------
  158. private:
  159. // Let the nested interfaces access our private state
  160. //
  161. friend class CCapStream;
  162. friend class CCapOverlay;
  163. friend class CCapPreview;
  164. friend class CCapOverlayNotify;
  165. friend class CPropPage;
  166. friend class CSpecifyProp;
  167. friend class COptions;
  168. // MikeCl - a way to avoid using overlay
  169. BOOL m_fAvoidOverlay;
  170. // device # of device to open
  171. int m_iVideoId;
  172. // persist stream saved from IPersistPropertyBag::Load
  173. IPersistStream *m_pPersistStreamDevice;
  174. void CreatePins(HRESULT *phr);
  175. // property page stuff
  176. //
  177. CSpecifyProp m_Specify;
  178. COptions m_Options;
  179. BOOL m_fDialogUp;
  180. CCritSec m_lock;
  181. CCapStream * m_pStream; // video data output pin
  182. CCapOverlay * m_pOverlayPin; // overlay preview pin
  183. CCapPreview * m_pPreviewPin; // non-overlay preview pin
  184. //CTimeStream * m_pTimeA; // SMPTE timecode stream
  185. };
  186. #define ALIGNUP(dw,align) ((LONG_PTR)(((LONG_PTR)(dw)+(align)-1) / (align)) * (align))
  187. class CFrameSample : public CMediaSample
  188. {
  189. public:
  190. CFrameSample(
  191. IMemAllocator *pAllocator,
  192. HRESULT *phr,
  193. LPTHKVIDEOHDR ptvh)
  194. :
  195. m_ptvh(ptvh),
  196. CMediaSample(NAME("Video Frame"),
  197. (CBaseAllocator *)pAllocator,
  198. phr,
  199. ptvh->vh.lpData,
  200. (long)ptvh->vh.dwBufferLength)
  201. {
  202. };
  203. LPTHKVIDEOHDR GetFrameHeader() {return m_ptvh;};
  204. private:
  205. const LPTHKVIDEOHDR m_ptvh;
  206. };
  207. // CCapStream
  208. // represents one stream of data within the file
  209. // responsible for delivering data to connected components
  210. //
  211. // supports IPin
  212. //
  213. // never created by COM, so no CreateInstance or entry in global
  214. // FactoryTemplate table. Only ever created by a CVfwCapture object and
  215. // returned via the EnumPins interface.
  216. //
  217. class CCapStream : public CBaseOutputPin, public IAMStreamConfig,
  218. public IAMVideoCompression, public IAMDroppedFrames,
  219. public IAMBufferNegotiation, public CBaseStreamControl,
  220. public IKsPropertySet, public IAMPushSource
  221. {
  222. public:
  223. CCapStream(
  224. TCHAR *pObjectName,
  225. CVfwCapture *pCapture,
  226. UINT iVideoId,
  227. HRESULT * phr,
  228. LPCWSTR pName);
  229. // ddraw stuff just so we can take the win16 lock
  230. LPDIRECTDRAWSURFACE m_pDrawPrimary; // DirectDraw primary surface
  231. IDirectDraw *m_pdd; // ddraw object
  232. virtual ~CCapStream();
  233. DECLARE_IUNKNOWN
  234. // IAMStreamConfig stuff
  235. STDMETHODIMP SetFormat(AM_MEDIA_TYPE *pmt);
  236. STDMETHODIMP GetFormat(AM_MEDIA_TYPE **ppmt);
  237. STDMETHODIMP GetNumberOfCapabilities(int *piCount, int *piSize);
  238. STDMETHODIMP GetStreamCaps(int i, AM_MEDIA_TYPE **ppmt,
  239. LPBYTE pSCC);
  240. /* IAMVideoCompression methods */
  241. STDMETHODIMP put_KeyFrameRate(long KeyFrameRate) {return E_NOTIMPL;};
  242. STDMETHODIMP get_KeyFrameRate(long FAR* pKeyFrameRate) {return E_NOTIMPL;};
  243. STDMETHODIMP put_PFramesPerKeyFrame(long PFramesPerKeyFrame)
  244. {return E_NOTIMPL;};
  245. STDMETHODIMP get_PFramesPerKeyFrame(long FAR* pPFramesPerKeyFrame)
  246. {return E_NOTIMPL;};
  247. STDMETHODIMP put_Quality(double Quality) {return E_NOTIMPL;};
  248. STDMETHODIMP get_Quality(double FAR* pQuality) {return E_NOTIMPL;};
  249. STDMETHODIMP put_WindowSize(DWORDLONG WindowSize) {return E_NOTIMPL;};
  250. STDMETHODIMP get_WindowSize(DWORDLONG FAR* pWindowSize) {return E_NOTIMPL;};
  251. STDMETHODIMP OverrideKeyFrame(long FrameNumber) {return E_NOTIMPL;};
  252. STDMETHODIMP OverrideFrameSize(long FrameNumber, long Size)
  253. {return E_NOTIMPL;};
  254. STDMETHODIMP GetInfo(LPWSTR pstrVersion,
  255. int *pcbVersion,
  256. LPWSTR pstrDescription,
  257. int *pcbDescription,
  258. long FAR* pDefaultKeyFrameRate,
  259. long FAR* pDefaultPFramesPerKey,
  260. double FAR* pDefaultQuality,
  261. long FAR* pCapabilities);
  262. /* IAMBufferNegotiation methods */
  263. STDMETHODIMP SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop);
  264. STDMETHODIMP GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop);
  265. /* IAMDroppedFrames methods */
  266. STDMETHODIMP GetNumDropped(long FAR* plDropped);
  267. STDMETHODIMP GetNumNotDropped(long FAR* plNotDropped);
  268. STDMETHODIMP GetDroppedInfo(long lSize, long FAR* plArray,
  269. long FAR* plNumCopied);
  270. STDMETHODIMP GetAverageFrameSize(long FAR* plAverageSize);
  271. // IAMPushSource
  272. STDMETHODIMP GetPushSourceFlags( ULONG *pFlags );
  273. STDMETHODIMP SetPushSourceFlags( ULONG Flags );
  274. STDMETHODIMP GetLatency( REFERENCE_TIME *prtLatency );
  275. STDMETHODIMP SetStreamOffset( REFERENCE_TIME rtOffset );
  276. STDMETHODIMP GetStreamOffset( REFERENCE_TIME *prtOffset );
  277. STDMETHODIMP GetMaxStreamOffset( REFERENCE_TIME *prtOffset );
  278. STDMETHODIMP SetMaxStreamOffset( REFERENCE_TIME rtOffset );
  279. /* IKsPropertySet stuff */
  280. STDMETHODIMP Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData,
  281. DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
  282. STDMETHODIMP Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData,
  283. DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData,
  284. DWORD *pcbReturned);
  285. STDMETHODIMP QuerySupported(REFGUID guidPropSet, DWORD dwPropID,
  286. DWORD *pTypeSupport);
  287. // expose our extra interfaces
  288. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** pv);
  289. HRESULT GetMediaType(int iPosition, CMediaType* pt);
  290. // check if the pin can support this specific proposed type&format
  291. HRESULT CheckMediaType(const CMediaType*);
  292. // set the new mediatype to use
  293. HRESULT SetMediaType(const CMediaType*);
  294. // say how big our buffers should be and how many we want
  295. HRESULT DecideBufferSize(IMemAllocator * pAllocator,
  296. ALLOCATOR_PROPERTIES *pProperties);
  297. // override this to force our own allocator
  298. HRESULT DecideAllocator(IMemInputPin *pPin,
  299. IMemAllocator **ppAlloc);
  300. // Override to start & stop streaming
  301. HRESULT Active(); // Stop-->Pause
  302. HRESULT Inactive(); // Pause-->Stop
  303. HRESULT ActiveRun(REFERENCE_TIME tStart); // Pause-->Run
  304. HRESULT ActivePause(); // Run-->Pause
  305. // override to receive Notification messages
  306. STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
  307. class CAlloc : public CUnknown,
  308. public IMemAllocator
  309. {
  310. private:
  311. CCapStream * m_pStream; // parent stream
  312. protected:
  313. friend class CCapStream;
  314. ALLOCATOR_PROPERTIES parms;
  315. public:
  316. CAlloc(TCHAR *, CCapStream *, HRESULT *);
  317. ~CAlloc();
  318. DECLARE_IUNKNOWN
  319. STDMETHODIMP SetProperties(
  320. ALLOCATOR_PROPERTIES* pRequest,
  321. ALLOCATOR_PROPERTIES* pActual);
  322. // return the properties actually being used on this allocator
  323. STDMETHODIMP GetProperties(
  324. ALLOCATOR_PROPERTIES* pProps);
  325. // override Commit to allocate memory. We handle the GetBuffer
  326. //state changes
  327. STDMETHODIMP Commit();
  328. // override this to handle the memory freeing. We handle any outstanding
  329. // GetBuffer calls
  330. STDMETHODIMP Decommit();
  331. // get container for a sample. Blocking, synchronous call to get the
  332. // next free buffer (as represented by an IMediaSample interface).
  333. // on return, the time etc properties will be invalid, but the buffer
  334. // pointer and size will be correct. The two time parameters are
  335. // optional and either may be NULL, they may alternatively be set to
  336. // the start and end times the sample will have attached to it
  337. STDMETHODIMP GetBuffer(IMediaSample **ppBuffer,
  338. REFERENCE_TIME * pStartTime,
  339. REFERENCE_TIME * pEndTime,
  340. DWORD dwFlags);
  341. // final release of a CMediaSample will call this
  342. STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
  343. };
  344. private:
  345. // methods for the helper thread
  346. //
  347. BOOL Create();
  348. BOOL Pause();
  349. BOOL Run();
  350. BOOL Stop();
  351. BOOL Destroy();
  352. static DWORD WINAPI ThreadProcInit(void *pv);
  353. DWORD ThreadProc();
  354. enum ThdState {TS_Not, TS_Create, TS_Init, TS_Pause, TS_Run, TS_Stop, TS_Destroy, TS_Exit};
  355. HANDLE m_hThread;
  356. DWORD m_tid;
  357. ThdState m_state; // used to communicate state changes between worker thread and main
  358. // Worker thread can make
  359. // Init->Pause, Stop->Destroy, Destroy->Exit transitions
  360. // main thread(s) can make
  361. // Pause->Run, Pause->Stop, Run->Pause, Run->Stop transitions
  362. // other transitions are invalid
  363. #ifdef DEBUG
  364. LPSTR StateName(ThdState state) {
  365. static char szState[] = "Not \0Create \0Init \0Pause \0"
  366. "Run \0Stop \0Destroy\0Exit \0";
  367. if (state <= TS_Exit && state >= TS_Not)
  368. return szState + (int)state * 8;
  369. return "<Invalid>";
  370. };
  371. #endif
  372. void DumpState (ThdState state) ;
  373. ThdState ChangeState(ThdState state)
  374. {
  375. DumpState (state) ;
  376. return (ThdState) InterlockedExchange ((LONG *)&m_state, (LONG)state);
  377. } ;
  378. UINT *m_pBufferQueue; // what order we sent the buffers to the driver in
  379. UINT m_uiQueueHead; // next buffer going to driver goes here
  380. UINT m_uiQueueTail; // next buffer coming from driver is here
  381. HANDLE m_hEvtPause; // Signalled when the worker is in the pause state
  382. HANDLE m_hEvtRun; // Signalled when the worker is in the run state
  383. BOOL ThreadExists() {return (m_hThread != NULL);};
  384. BOOL IsRunning() {return m_state == TS_Run;};
  385. // for IAMBufferNegotiation
  386. ALLOCATOR_PROPERTIES m_propSuggested;
  387. REFERENCE_TIME m_rtLatency;
  388. REFERENCE_TIME m_rtStreamOffset;
  389. REFERENCE_TIME m_rtMaxStreamOffset;
  390. // deal with user controllable options
  391. //
  392. private:
  393. VFWCAPTUREOPTIONS m_user;
  394. HRESULT LoadOptions (void);
  395. protected:
  396. CAPTURESTATS m_capstats;
  397. public:
  398. HRESULT SetOptions(const VFWCAPTUREOPTIONS * pUser);
  399. HRESULT GetOptions(VFWCAPTUREOPTIONS * pUser);
  400. HRESULT DriverDialog(HWND hwnd, UINT uType, UINT uQuery);
  401. HRESULT Reconnect(BOOL fCapturePinToo);
  402. private:
  403. // return the time of a given tick
  404. //
  405. REFERENCE_TIME TickToRefTime (DWORD nTick) {
  406. const DWORD dw100ns = 10 * 1000 * 1000;
  407. REFERENCE_TIME time =
  408. UInt32x32To64(dw100ns, m_user.dwTickScale)
  409. * nTick
  410. / m_user.dwTickRate;
  411. return time;
  412. };
  413. void ReduceScaleAndRate ();
  414. int ProfileInt(LPSTR pszKey, int iDefault);
  415. HRESULT ConnectToDriver (void);
  416. HRESULT DisconnectFromDriver (void);
  417. HRESULT InitPalette (void);
  418. HRESULT SendFormatToDriver(VIDEOINFOHEADER *);
  419. HRESULT GetFormatFromDriver (void);
  420. struct _cap_parms {
  421. // video driver stuff
  422. //
  423. HVIDEO hVideoIn; // video input
  424. HVIDEO hVideoExtIn; // external in (source control)
  425. HVIDEO hVideoExtOut; // external out (overlay; not required)
  426. MMRESULT mmr; // open fail/success code
  427. BOOL bHasOverlay; // TRUE if ExtOut has overlay support
  428. // the preview buffer. once created it persists until
  429. // the stream destructor because the renderer assumes
  430. // that it can keep a pointer to this and not crash
  431. // if it uses it after stopping the stream.
  432. // (no longer a problem)
  433. // !!! can we remove all this Preview still frame stuff?
  434. //
  435. UINT cbVidHdr; // size of a videohdr (or videohdrex)
  436. THKVIDEOHDR tvhPreview; // preview video header
  437. CFrameSample * pSamplePreview; // CMediaSample for preview buffer
  438. // video header & buffer stuff
  439. //
  440. UINT cbBuffer; // max size of video frame data
  441. UINT nHeaders; // number of video headers
  442. struct _cap_hdr {
  443. THKVIDEOHDR tvh;
  444. } * paHdr;
  445. BOOL fBuffersOnHardware; // TRUE if all video buffers are in hardware
  446. HANDLE hEvtBufferDone; // this event signalled when a buffer is ready
  447. DWORD_PTR h0EvtBufferDone; // on Win95 this is a Ring0 alias of the above event
  448. LONGLONG tTick; // duration of a single tick
  449. LONGLONG llLastTick; // the last frame sent downstream
  450. DWORDLONG dwlLastTimeCaptured;// the last driver time stamp
  451. DWORDLONG dwlTimeCapturedOffset;// wraparound compensation
  452. UINT uiLastAdded; // the last buffer AddBuffer'd
  453. DWORD dwFirstFrameOffset; // when 1st frame was captured
  454. LONGLONG llFrameCountOffset; // add this to frame number
  455. BOOL fReRun; // went from Run->Pause->Run
  456. BOOL fLastSampleDiscarded; // due to IAMStreamControl
  457. CRefTime rtThisFrameTime; // clock time when frame was captured
  458. CRefTime rtLastStamp; // last frame delivered had this stamp
  459. CRefTime rtDriverStarted; // when videoStreamStart was called
  460. CRefTime rtDriverLatency; // how long it takes captured frame to
  461. // get noticed by ring 3
  462. } m_cs;
  463. // methods for capture loop
  464. //
  465. HRESULT Prepare(); // allocate resources in preparation for capture loop
  466. HRESULT FakePreview(BOOL); // fake a preview stream
  467. HRESULT Capture(); // capture loop. executes while in the run state
  468. HRESULT StillFrame(); // send still frame while in pause mode
  469. HRESULT Flush(); // flush any data in the pipe (while stopping).
  470. HRESULT Unprepare(); // free resources used by capture loop
  471. HRESULT SendFrame(LPTHKVIDEOHDR ptvh, BOOL bDiscon, BOOL bPreroll);
  472. BOOL Committed() {return m_cs.paHdr != NULL;};
  473. HRESULT ReleaseFrame(LPTHKVIDEOHDR ptvh);
  474. private:
  475. friend class CAlloc;
  476. friend class CVfwCapture::COptions;
  477. friend class CVfwCapture;
  478. friend class CCapOverlay;
  479. friend class CCapPreview;
  480. friend class CCapOverlayNotify;
  481. CAlloc m_Alloc; // allocator
  482. CVfwCapture * m_pCap; // parent
  483. CMediaType * m_pmt; // media type for this pin
  484. #ifdef PERF
  485. int m_perfWhyDropped;
  486. #endif // PERF
  487. CCritSec m_ReleaseLock;
  488. };
  489. // CCapOverlayNotify
  490. // where the video renderer informs us of window moves/clips so we can fix
  491. // the overlay
  492. //
  493. class CCapOverlayNotify : public CUnknown, public IOverlayNotify
  494. {
  495. public:
  496. /* Constructor and destructor */
  497. CCapOverlayNotify(TCHAR *pName,
  498. CVfwCapture *pFilter,
  499. LPUNKNOWN pUnk,
  500. HRESULT *phr);
  501. ~CCapOverlayNotify();
  502. /* Unknown methods */
  503. DECLARE_IUNKNOWN
  504. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  505. STDMETHODIMP_(ULONG) NonDelegatingRelease();
  506. STDMETHODIMP_(ULONG) NonDelegatingAddRef();
  507. /* IOverlayNotify methods */
  508. STDMETHODIMP OnColorKeyChange(
  509. const COLORKEY *pColorKey); // Defines new colour key
  510. STDMETHODIMP OnClipChange(
  511. const RECT *pSourceRect, // Area of video to play
  512. const RECT *pDestinationRect, // Area of video to play
  513. const RGNDATA *pRegionData); // Header describing clipping
  514. STDMETHODIMP OnPaletteChange(
  515. DWORD dwColors, // Number of colours present
  516. const PALETTEENTRY *pPalette); // Array of palette colours
  517. STDMETHODIMP OnPositionChange(
  518. const RECT *pSourceRect, // Area of video to play with
  519. const RECT *pDestinationRect); // Area video goes
  520. private:
  521. CVfwCapture *m_pFilter;
  522. } ;
  523. // CCapOverlay
  524. // represents the overlay output pin that connects to the renderer
  525. //
  526. // supports IPin
  527. //
  528. // never created by COM, so no CreateInstance or entry in global
  529. // FactoryTemplate table. Only ever created by a CVfwCapture object and
  530. // returned via the EnumPins interface.
  531. //
  532. class CCapOverlay : public CBaseOutputPin, public IKsPropertySet
  533. #ifdef OVERLAY_SC
  534. , public CBaseStreamControl
  535. #endif
  536. {
  537. public:
  538. CCapOverlay(
  539. TCHAR *pObjectName,
  540. CVfwCapture *pCapture,
  541. HRESULT * phr,
  542. LPCWSTR pName);
  543. virtual ~CCapOverlay();
  544. /* IKsPropertySet stuff */
  545. STDMETHODIMP Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData,
  546. DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
  547. STDMETHODIMP Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData,
  548. DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData,
  549. DWORD *pcbReturned);
  550. STDMETHODIMP QuerySupported(REFGUID guidPropSet, DWORD dwPropID,
  551. DWORD *pTypeSupport);
  552. HRESULT GetMediaType(int iPosition, CMediaType* pt);
  553. // check if the pin can support this specific proposed type&format
  554. HRESULT CheckMediaType(const CMediaType*);
  555. // override this to not do anything with allocators
  556. HRESULT DecideAllocator(IMemInputPin *pPin,
  557. IMemAllocator **ppAlloc);
  558. // override these to use IOverlay, not IMemInputPin
  559. STDMETHODIMP Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
  560. HRESULT BreakConnect();
  561. HRESULT CheckConnect(IPin *pPin);
  562. DECLARE_IUNKNOWN
  563. // expose our extra interfaces
  564. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** pv);
  565. #ifdef OVERLAY_SC
  566. STDMETHODIMP StopAt(const REFERENCE_TIME * ptStop, BOOL bBlockData, BOOL bSendExtra, DWORD dwCookie);
  567. STDMETHODIMP StartAt(const REFERENCE_TIME * ptStart, DWORD dwCookie);
  568. #endif
  569. HRESULT Active(); // Stop-->Pause
  570. HRESULT Inactive(); // Pause-->Stop
  571. HRESULT ActiveRun(REFERENCE_TIME tStart); // Pause-->Run
  572. HRESULT ActivePause(); // Run-->Pause
  573. // say how big our buffers should be and how many we want
  574. HRESULT DecideBufferSize(IMemAllocator * pAllocator,
  575. ALLOCATOR_PROPERTIES *pProperties)
  576. {
  577. return NOERROR;
  578. };
  579. private:
  580. CVfwCapture * m_pCap; // parent
  581. IOverlay * m_pOverlay; // Overlay window on output pin
  582. CCapOverlayNotify m_OverlayNotify; // Notify object
  583. BOOL m_bAdvise; // Advise id
  584. BOOL m_fRunning; // am I running?
  585. #ifdef OVERLAY_SC
  586. HANDLE m_hThread; // thread for IAMStreamControl
  587. DWORD m_tid;
  588. CAMEvent m_EventAdvise;
  589. DWORD_PTR m_dwAdvise;
  590. REFERENCE_TIME m_rtStart, m_rtEnd; // for IAMStreamControl
  591. BOOL m_fHaveThread;
  592. DWORD m_dwCookieStart, m_dwCookieStop;
  593. static DWORD WINAPI ThreadProcInit(void *pv);
  594. DWORD ThreadProc();
  595. #endif
  596. friend class CVfwCapture;
  597. friend class CCapOverlayNotify;
  598. };
  599. // CCapPreview
  600. // represents the non-overlay preview pin that connects to the renderer
  601. //
  602. // supports IPin
  603. //
  604. // never created by COM, so no CreateInstance or entry in global
  605. // FactoryTemplate table. Only ever created by a CVfwCapture object and
  606. // returned via the EnumPins interface.
  607. //
  608. class CCapPreview : public CBaseOutputPin, public CBaseStreamControl,
  609. public IKsPropertySet, public IAMPushSource
  610. {
  611. public:
  612. CCapPreview(
  613. TCHAR *pObjectName,
  614. CVfwCapture *pCapture,
  615. HRESULT * phr,
  616. LPCWSTR pName);
  617. virtual ~CCapPreview();
  618. DECLARE_IUNKNOWN
  619. /* IKsPropertySet stuff */
  620. STDMETHODIMP Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData,
  621. DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
  622. STDMETHODIMP Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData,
  623. DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData,
  624. DWORD *pcbReturned);
  625. STDMETHODIMP QuerySupported(REFGUID guidPropSet, DWORD dwPropID,
  626. DWORD *pTypeSupport);
  627. // override this to say what interfaces we support where
  628. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
  629. HRESULT GetMediaType(int iPosition, CMediaType* pt);
  630. // check if the pin can support this specific proposed type&format
  631. HRESULT CheckMediaType(const CMediaType*);
  632. HRESULT ActiveRun(REFERENCE_TIME tStart); // Pause-->Run
  633. HRESULT ActivePause(); // Run-->Pause
  634. HRESULT Active(); // Stop-->Pause
  635. HRESULT Inactive(); // Pause-->Stop
  636. STDMETHODIMP Notify(IBaseFilter *pFilter, Quality q);
  637. // say how big our buffers should be and how many we want
  638. HRESULT DecideBufferSize(IMemAllocator * pAllocator,
  639. ALLOCATOR_PROPERTIES *pProperties);
  640. // IAMPushSource
  641. STDMETHODIMP GetPushSourceFlags( ULONG *pFlags );
  642. STDMETHODIMP SetPushSourceFlags( ULONG Flags );
  643. STDMETHODIMP GetLatency( REFERENCE_TIME *prtLatency );
  644. STDMETHODIMP SetStreamOffset( REFERENCE_TIME rtOffset );
  645. STDMETHODIMP GetStreamOffset( REFERENCE_TIME *prtOffset );
  646. STDMETHODIMP GetMaxStreamOffset( REFERENCE_TIME *prtMaxOffset );
  647. STDMETHODIMP SetMaxStreamOffset( REFERENCE_TIME rtOffset );
  648. private:
  649. static DWORD WINAPI ThreadProcInit(void *pv);
  650. DWORD ThreadProc();
  651. HRESULT CapturePinActive(BOOL fActive);
  652. HRESULT ReceivePreviewFrame(IMediaSample * lpPrevSample, int iSize);
  653. HRESULT CopyPreviewFrame(LPVOID lpOutputBuffer);
  654. CVfwCapture * m_pCap; // parent
  655. BOOL m_fActuallyRunning; // is this filter is running state?
  656. BOOL m_fThinkImRunning; // does the preview thread realize that?
  657. REFERENCE_TIME m_rtRun;
  658. HANDLE m_hThread;
  659. DWORD m_tid;
  660. HANDLE m_hEventRun;
  661. HANDLE m_hEventStop;
  662. HANDLE m_hEventFrameValid;
  663. HANDLE m_hEventActiveChanged;
  664. CAMEvent m_EventAdvise;
  665. DWORD_PTR m_dwAdvise;
  666. BOOL m_fCapturing; // is the streaming pin active?
  667. IMediaSample* m_pPreviewSample;
  668. int m_iFrameSize;
  669. BOOL m_fFrameValid;
  670. BOOL m_fLastSampleDiscarded; // for IAMStreamControl
  671. COutputQueue *m_pOutputQueue;
  672. REFERENCE_TIME m_rtLatency;
  673. REFERENCE_TIME m_rtStreamOffset;
  674. REFERENCE_TIME m_rtMaxStreamOffset;
  675. LONG m_cPreviewBuffers;
  676. friend class CVfwCapture;
  677. friend class CCapStream;
  678. };
  679. // this helper function creates an output pin for streaming video.
  680. //
  681. CCapStream * CreateStreamPin (
  682. CVfwCapture * pCapture,
  683. UINT iVideoId,
  684. HRESULT * phr);
  685. // this helper function creates an output pin for overlay
  686. //
  687. CCapOverlay * CreateOverlayPin (
  688. CVfwCapture * pCapture,
  689. HRESULT * phr);
  690. // this helper function creates an output pin for non-overlay preview
  691. //
  692. CCapPreview * CreatePreviewPin (
  693. CVfwCapture * pCapture,
  694. HRESULT * phr);
  695. // property page class to show properties of
  696. // and object that exposes IVfwCaptureOptions
  697. //
  698. class CPropPage : public CBasePropertyPage
  699. {
  700. IVfwCaptureOptions * m_pOpt; // object that we are showing options from
  701. IPin *m_pPin;
  702. public:
  703. CPropPage(TCHAR *, LPUNKNOWN, HRESULT *);
  704. // create a new instance of this class
  705. //
  706. static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *);
  707. HRESULT OnConnect(IUnknown *pUnknown);
  708. HRESULT OnDisconnect();
  709. INT_PTR OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  710. };