source: mediastreamer2/linphone/mediastreamer2/plugins/msdscap/mdscap.cc @ 393:33c4f6d6a293

Last change on this file since 393:33c4f6d6a293 was 393:33c4f6d6a293, checked in by smorlat <smorlat@…>, 4 years ago

new directshow/mingw filter works

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@396 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

  • Property exe set to *
File size: 37.9 KB
Line 
1// This is a DirectShow interface. But maybe you'll find that it's easier to
2// access the camera directly ;)
3
4// http://www.codeguru.com/cpp/g-m/multimedia/video/article.php/c9551/
5// http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-April/027965.html
6// http://msdn2.microsoft.com/en-us/library/ms787594.aspx
7// http://msdn2.microsoft.com/en-us/library/ms787867.aspx
8// NullRenderer wih reference clock set to NULL
9// http://www.videolan.org/
10// http://git.videolan.org/gitweb.cgi?p=vlc.git;f=modules/access/dshow;hb=0.8.6
11
12// #include <wtypes.h>
13// #include <unknwn.h>
14// #include <ole2.h>
15// #include <limits.h>
16// #include <dshow.h>
17
18#include <iostream>
19#include <iomanip>
20#include <fstream>
21#include <windows.h>
22#include <winnls.h>
23#include <errors.h>
24#include <initguid.h>
25#include <ocidl.h>
26#include <malloc.h>
27#include "comptr.hh"
28#include "error.hh"
29
30#include <mediastreamer2/mswebcam.h>
31#include <mediastreamer2/msfilter.h>
32#include <mediastreamer2/msticker.h>
33#include <mediastreamer2/msvideo.h>
34
35#define FILTER_NAME L"HornetsEye Capture Filter"
36#define PIN_NAME L"Capture"
37
38using namespace Hornetseye;
39
40DEFINE_GUID( CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01,
41             0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
42DEFINE_GUID( CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0,
43             0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 );
44DEFINE_GUID( CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce,
45             0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
46DEFINE_GUID( CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3,
47             0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
48DEFINE_GUID( CLSID_NullRenderer,0xc1f400a4, 0x3f08, 0x11d3,
49             0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
50DEFINE_GUID( CLSID_VfwCapture, 0x1b544c22, 0xfd0b, 0x11ce,
51             0x8c, 0x63, 0x0, 0xaa, 0x00, 0x44, 0xb5, 0x1e);
52DEFINE_GUID( IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce,
53             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
54DEFINE_GUID( IID_IBaseFilter, 0x56a86895, 0x0ad4, 0x11ce,
55             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
56DEFINE_GUID( IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0,
57             0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 );
58DEFINE_GUID( IID_IEnumFilters, 0x56a86893, 0xad4, 0x11ce,
59             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
60DEFINE_GUID( IID_IEnumPins, 0x56a86892, 0x0ad4, 0x11ce,
61             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
62DEFINE_GUID( IID_IMediaSample, 0x56a8689a, 0x0ad4, 0x11ce,
63             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
64DEFINE_GUID( IID_IMediaFilter, 0x56a86899, 0x0ad4, 0x11ce,
65             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
66DEFINE_GUID( IID_IPin, 0x56a86891, 0x0ad4, 0x11ce,
67             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
68DEFINE_GUID( IID_ISampleGrabber, 0x6b652fff, 0x11fe, 0x4fce,
69             0x92, 0xad, 0x02, 0x66, 0xb5, 0xd7, 0xc7, 0x8f );
70DEFINE_GUID( IID_ISampleGrabberCB, 0x0579154a, 0x2b53, 0x4994,
71             0xb0, 0xd0, 0xe7, 0x73, 0x14, 0x8e, 0xff, 0x85 );
72DEFINE_GUID( IID_IMediaEvent, 0x56a868b6, 0x0ad4, 0x11ce,
73             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
74DEFINE_GUID( IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce,
75             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
76DEFINE_GUID( IID_IMemInputPin, 0x56a8689d, 0x0ad4, 0x11ce,
77             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
78DEFINE_GUID( IID_IAMStreamConfig, 0xc6e13340, 0x30ac, 0x11d0,
79             0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 );
80DEFINE_GUID( IID_IVideoProcAmp, 0x4050560e, 0x42a7, 0x413a,
81             0x85, 0xc2, 0x09, 0x26, 0x9a, 0x2d, 0x0f, 0x44 );
82DEFINE_GUID( MEDIATYPE_Video, 0x73646976, 0x0000, 0x0010,
83             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
84DEFINE_GUID( MEDIASUBTYPE_I420, 0x30323449, 0x0000, 0x0010,
85             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
86DEFINE_GUID( MEDIASUBTYPE_YV12, 0x32315659, 0x0000, 0x0010,
87             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
88DEFINE_GUID( MEDIASUBTYPE_IYUV, 0x56555949, 0x0000, 0x0010,
89             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
90DEFINE_GUID( MEDIASUBTYPE_YUYV, 0x56595559, 0x0000, 0x0010,
91             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
92DEFINE_GUID( MEDIASUBTYPE_YUY2, 0x32595559, 0x0000, 0x0010,
93             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
94DEFINE_GUID( MEDIASUBTYPE_UYVY, 0x59565955, 0x0000, 0x0010,
95             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
96DEFINE_GUID( MEDIASUBTYPE_RGB24, 0xe436eb7d, 0x524f, 0x11ce,
97             0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
98
99using namespace std;
100
101typedef LONGLONG REFERENCE_TIME;
102
103typedef struct tagVIDEOINFOHEADER {
104  RECT rcSource;
105  RECT rcTarget;
106  DWORD dwBitRate;
107  DWORD dwBitErrorRate;
108  REFERENCE_TIME AvgTimePerFrame;
109  BITMAPINFOHEADER bmiHeader;
110} VIDEOINFOHEADER;
111
112typedef struct _AMMediaType {
113  GUID majortype;
114  GUID subtype;
115  BOOL bFixedSizeSamples;
116  BOOL bTemporalCompression;
117  ULONG lSampleSize;
118  GUID formattype;
119  IUnknown *pUnk;
120  ULONG cbFormat;
121  BYTE *pbFormat;
122} AM_MEDIA_TYPE;
123
124DECLARE_ENUMERATOR_(IEnumMediaTypes,AM_MEDIA_TYPE*);
125
126typedef struct _VIDEO_STREAM_CONFIG_CAPS
127{
128  GUID guid;
129  ULONG VideoStandard;
130  SIZE InputSize;
131  SIZE MinCroppingSize;
132  SIZE MaxCroppingSize;
133  int CropGranularityX;
134  int CropGranularityY;
135  int CropAlignX;
136  int CropAlignY;
137  SIZE MinOutputSize;
138  SIZE MaxOutputSize;
139  int OutputGranularityX;
140  int OutputGranularityY;
141  int StretchTapsX;
142  int StretchTapsY;
143  int ShrinkTapsX;
144  int ShrinkTapsY;
145  LONGLONG MinFrameInterval;
146  LONGLONG MaxFrameInterval;
147  LONG MinBitsPerSecond;
148  LONG MaxBitsPerSecond;
149} VIDEO_STREAM_CONFIG_CAPS;
150
151typedef LONGLONG REFERENCE_TIME;
152
153typedef interface IBaseFilter IBaseFilter;
154typedef interface IReferenceClock IReferenceClock;
155typedef interface IFilterGraph IFilterGraph;
156
157typedef enum _FilterState {
158  State_Stopped,
159  State_Paused,
160  State_Running
161} FILTER_STATE;
162
163#define MAX_FILTER_NAME 128
164typedef struct _FilterInfo {
165  WCHAR achName[MAX_FILTER_NAME]; 
166  IFilterGraph *pGraph;
167} FILTER_INFO;
168
169typedef enum _PinDirection {
170  PINDIR_INPUT,
171  PINDIR_OUTPUT
172} PIN_DIRECTION;
173
174#define MAX_PIN_NAME 128
175typedef struct _PinInfo {
176  IBaseFilter *pFilter;
177  PIN_DIRECTION dir;
178  WCHAR achName[MAX_PIN_NAME];
179} PIN_INFO;
180
181#define INTERFACE IPin
182DECLARE_INTERFACE_(IPin,IUnknown)
183{
184  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
185  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
186  STDMETHOD_(ULONG,Release)(THIS) PURE;
187  STDMETHOD(Connect)(THIS_ IPin*,const AM_MEDIA_TYPE*) PURE;
188  STDMETHOD(ReceiveConnection)(THIS_ IPin*,const AM_MEDIA_TYPE*) PURE;
189  STDMETHOD(Disconnect)(THIS) PURE;
190  STDMETHOD(ConnectedTo)(THIS_ IPin**) PURE;
191  STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
192  STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO*) PURE;
193  STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION*) PURE;
194};
195#undef INTERFACE
196
197DECLARE_ENUMERATOR_(IEnumPins,IPin*);
198
199typedef struct _AllocatorProperties {
200  long cBuffers;
201  long cbBuffer;
202  long cbAlign;
203  long cbPrefix;
204} ALLOCATOR_PROPERTIES;
205
206typedef LONG_PTR OAEVENT;
207
208#define INTERFACE IMediaEvent
209DECLARE_INTERFACE_(IMediaEvent,IDispatch)
210{
211  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
212  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
213  STDMETHOD_(ULONG,Release)(THIS) PURE;
214  STDMETHOD(GetEventHandle)(THIS_ OAEVENT*) PURE;
215  STDMETHOD(GetEvent)(THIS_ long*,LONG_PTR,LONG_PTR,long) PURE;
216  STDMETHOD(WaitForCompletion)(THIS_ long,long*) PURE;
217  STDMETHOD(CancelDefaultHandling)(THIS_ long) PURE;
218  STDMETHOD(RestoreDefaultHandling)(THIS_ long) PURE;
219  STDMETHOD(FreeEventParams)(THIS_ long,LONG_PTR,LONG_PTR) PURE;
220};
221#undef INTERFACE
222
223typedef long OAFilterState;
224
225#define INTERFACE IMediaControl
226DECLARE_INTERFACE_(IMediaControl,IDispatch)
227{
228  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
229  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
230  STDMETHOD_(ULONG,Release)(THIS) PURE;
231  STDMETHOD(Run)(THIS) PURE;
232  STDMETHOD(Pause)(THIS) PURE;
233  STDMETHOD(Stop)(THIS) PURE;
234  STDMETHOD(GetState)(THIS_ LONG,OAFilterState*) PURE;
235  STDMETHOD(RenderFile)(THIS_ BSTR) PURE;
236  STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**) PURE;
237  STDMETHOD(get_FilterCollection)(THIS_ IDispatch**) PURE;
238  STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**) PURE;
239  STDMETHOD(StopWhenReady)(THIS) PURE;
240};
241#undef INTERFACE
242
243#define INTERFACE IVideoProcAmp
244DECLARE_INTERFACE_(IVideoProcAmp,IUnknown)
245{
246  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
247  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
248  STDMETHOD_(ULONG,Release)(THIS) PURE;
249};
250#undef INTERFACE
251
252#define INTERFACE IAMStreamConfig
253DECLARE_INTERFACE_(IAMStreamConfig,IUnknown)
254{
255  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
256  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
257  STDMETHOD_(ULONG,Release)(THIS) PURE;
258  STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE;
259  STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE;
260  STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE;
261  STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE;
262};
263#undef INTERFACE
264
265#define INTERFACE IMediaFilter
266DECLARE_INTERFACE_(IMediaFilter,IPersist)
267{
268  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
269  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
270  STDMETHOD_(ULONG,Release)(THIS) PURE;
271  STDMETHOD(Stop)(THIS) PURE;
272  STDMETHOD(Pause)(THIS) PURE;
273  STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
274  STDMETHOD(GetState)(THIS_ DWORD,FILTER_STATE*) PURE;
275  STDMETHOD(SetSyncSource)(THIS_ IReferenceClock*) PURE;
276  STDMETHOD(GetSyncSource)(THIS_ IReferenceClock**) PURE;
277};
278#undef INTERFACE
279
280#define INTERFACE IBaseFilter
281DECLARE_INTERFACE_(IBaseFilter,IMediaFilter)
282{
283  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
284  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
285  STDMETHOD_(ULONG,Release)(THIS) PURE;
286  STDMETHOD(EnumPins)(THIS_ IEnumPins**) PURE;
287  STDMETHOD(FindPin)(THIS_ LPCWSTR,IPin**) PURE;
288  STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO*) PURE;
289  STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph*,LPCWSTR) PURE;
290  STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR*) PURE;
291};
292#undef INTERFACE
293
294DECLARE_ENUMERATOR_(IEnumFilters,IBaseFilter*);
295
296// #define INTERFACE IEnumFilters
297// DECLARE_INTERFACE_(IEnumFilters,IUnknown)
298// {
299//   STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
300//   STDMETHOD_(ULONG,AddRef)(THIS) PURE;
301//   STDMETHOD_(ULONG,Release)(THIS) PURE;
302//   STDMETHOD(Next)(THIS_ ULONG,IBaseFilter**,ULONG*) PURE;
303//   STDMETHOD(Skip)(THIS_ ULONG) PURE;
304//   STDMETHOD(Reset)(THIS) PURE;
305//   STDMETHOD(Clone)(THIS_ IEnumFilters**) PURE;
306// };
307// #undef INTERFACE
308
309#define INTERFACE IFilterGraph
310DECLARE_INTERFACE_(IFilterGraph,IUnknown)
311{
312  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
313  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
314  STDMETHOD_(ULONG,Release)(THIS) PURE;
315  STDMETHOD(AddFilter)(THIS_ IBaseFilter*,LPCWSTR) PURE;
316  STDMETHOD(RemoveFilter)(THIS_ IBaseFilter*) PURE;
317  STDMETHOD(EnumFilters)(THIS_ IEnumFilters**) PURE;
318  STDMETHOD(FindFilterByName)(THIS_ LPCWSTR,IBaseFilter**) PURE;
319  STDMETHOD(ConnectDirect)(THIS_ IPin*,IPin*,const AM_MEDIA_TYPE*) PURE;
320  STDMETHOD(Reconnect)(THIS_ IPin*) PURE;
321  STDMETHOD(Disconnect)(THIS_ IPin*) PURE;
322  STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
323};
324#undef INTERFACE
325
326#define INTERFACE IGraphBuilder
327DECLARE_INTERFACE_(IGraphBuilder,IFilterGraph)
328{
329  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
330  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
331  STDMETHOD_(ULONG,Release)(THIS) PURE;
332  STDMETHOD(Connect)(THIS_ IPin*,IPin*) PURE;
333  STDMETHOD(Render)(THIS_ IPin*) PURE;
334  STDMETHOD(RenderFile)(THIS_ LPCWSTR,LPCWSTR) PURE;
335  STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR,LPCWSTR,IBaseFilter**) PURE;
336  STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE;
337  STDMETHOD(Abort)(THIS) PURE;
338  STDMETHOD(ShouldOperationContinue)(THIS) PURE;
339};
340#undef INTERFACE
341
342#define INTERFACE ICreateDevEnum
343DECLARE_INTERFACE_(ICreateDevEnum,IUnknown)
344{
345  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
346  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
347  STDMETHOD_(ULONG,Release)(THIS) PURE;
348  STDMETHOD(CreateClassEnumerator)(THIS_ REFIID,IEnumMoniker**,DWORD) PURE;
349};
350#undef INTERFACE
351
352#define INTERFACE IMediaSample
353DECLARE_INTERFACE_(IMediaSample,IUnknown)
354{
355  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
356  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
357  STDMETHOD_(ULONG,Release)(THIS) PURE;
358  STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;
359  STDMETHOD_(long, GetSize)(THIS) PURE;
360};
361/*
362#define INTERFACE IMediaSample
363DECLARE_INTERFACE_(IMediaSample, IUnknown)
364{
365    STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;
366    STDMETHOD_(long, GetSize)(THIS) PURE;
367    STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
368    STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
369    STDMETHOD(IsSyncPoint)(THIS) PURE;
370    STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE;
371    STDMETHOD(IsPreroll)(THIS) PURE;
372    STDMETHOD(SetPreroll)(THIS_ BOOL) PURE;
373    STDMETHOD_(long, GetActualDataLength)(THIS) PURE;
374    STDMETHOD(SetActualDataLength)(THIS_ long) PURE;
375    STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE;
376    STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;
377    STDMETHOD(IsDiscontinuity)(THIS) PURE;
378    STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE;
379    STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
380    STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
381};
382*/
383
384
385#undef INTERFACE
386
387#define INTERFACE IMemAllocator
388DECLARE_INTERFACE_(IMemAllocator,IUnknown)
389{
390  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
391  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
392  STDMETHOD_(ULONG,Release)(THIS) PURE;
393  STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES*,ALLOCATOR_PROPERTIES*) PURE;
394  STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES*) PURE;
395  STDMETHOD(Commit)(THIS) PURE;
396  STDMETHOD(Decommit)(THIS) PURE;
397  STDMETHOD(GetBuffer)(THIS_ IMediaSample **,REFERENCE_TIME*,REFERENCE_TIME*,DWORD) PURE;
398  STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample*) PURE;
399};
400#undef INTERFACE
401
402#define INTERFACE IMemInputPin
403DECLARE_INTERFACE_(IMemInputPin,IUnknown)
404{
405  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
406  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
407  STDMETHOD_(ULONG,Release)(THIS) PURE;
408  STDMETHOD(GetAllocator)(THIS_ IMemAllocator**) PURE;
409  STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator*,BOOL) PURE;
410  STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES*) PURE;
411  STDMETHOD(Receive)(THIS_ IMediaSample*) PURE;
412  STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample**,LONG,LONG*) PURE;
413  STDMETHOD(ReceiveCanBlock)(THIS) PURE;
414};
415#undef INTERFACE
416
417#define INTERFACE ISampleGrabberCB
418DECLARE_INTERFACE_(ISampleGrabberCB,IUnknown)
419{
420  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
421  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
422  STDMETHOD_(ULONG,Release)(THIS) PURE;
423  STDMETHOD(SampleCB)(THIS_ double,IMediaSample*) PURE;
424  STDMETHOD(BufferCB)(THIS_ double,BYTE*,long) PURE;
425};
426#undef INTERFACE
427
428#define INTERFACE ISampleGrabber
429DECLARE_INTERFACE_(ISampleGrabber,IUnknown)
430{
431  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
432  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
433  STDMETHOD_(ULONG,Release)(THIS) PURE;
434  STDMETHOD(SetOneShot)(THIS_ BOOL) PURE;
435  STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE;
436  STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
437  STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE;
438  STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE;
439  STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE;
440  STDMETHOD(SetCallBack)(THIS_ ISampleGrabberCB *,long) PURE;
441};
442#undef INTERFACE
443
444ComPtr< IPin > getPin( IBaseFilter *filter, PIN_DIRECTION direction, int num )
445{
446  ComPtr< IPin > retVal;
447  ComPtr< IEnumPins > enumPins;
448  COERRORMACRO( filter->EnumPins( &enumPins ), Error, ,
449                "Error getting pin enumerator" );
450  ULONG found;
451  ComPtr< IPin > pin;
452  while ( enumPins->Next( 1, &pin, &found ) == S_OK ) {
453    PIN_DIRECTION pinDirection = (PIN_DIRECTION)( -1 );
454    pin->QueryDirection( &pinDirection );
455    if ( pinDirection == direction ) {
456      if ( num == 0 ) {
457        retVal = pin;
458        break;
459      };
460      num--;
461    };
462  };
463  return retVal;
464}
465
466struct DscapState;
467
468class MSCallback: public ISampleGrabberCB
469{
470public:
471  MSCallback(DscapState *s);
472  virtual ~MSCallback(void);
473  STDMETHODIMP QueryInterface( REFIID riid, void **ppv );
474  STDMETHODIMP_(ULONG) AddRef(void);
475  STDMETHODIMP_(ULONG) Release(void);
476  STDMETHODIMP SampleCB(double,IMediaSample*);
477  STDMETHODIMP BufferCB(double,BYTE*,long);
478protected:
479  long m_refCount;
480  DscapState *mState;
481};
482
483#if 1
484using namespace std;
485
486int toto(void)
487{
488  int retVal = 0;
489  bool initialized = false;
490  MSCallback *callback = NULL;
491  try {
492    COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
493    initialized = true;
494    ComPtr< IGraphBuilder > graphBuilder;
495    graphBuilder.coCreateInstance( CLSID_FilterGraph, IID_IGraphBuilder,
496                                   "Could not create graph builder "
497                                   "interface" );
498    cerr << "graphBuilder is " << graphBuilder.get() << endl;
499    ComPtr< ICreateDevEnum > createDevEnum;
500    createDevEnum.coCreateInstance( CLSID_SystemDeviceEnum,
501                                    IID_ICreateDevEnum, "Could not create "
502                                    "device enumerator" );
503    ComPtr< IEnumMoniker > enumMoniker;
504    COERRORMACRO( createDevEnum->CreateClassEnumerator
505                  ( CLSID_VideoInputDeviceCategory, &enumMoniker, 0 ), Error, ,
506                  "Error requesting moniker enumerator" );
507    createDevEnum.reset();
508    COERRORMACRO( enumMoniker->Reset(), Error, ,
509                  "Error resetting moniker enumerator" );
510    int index = 0;
511    ComPtr< IMoniker > moniker;
512    for ( int i=0; i<=index; i++ ) {
513      ULONG fetched = 0;
514      COERRORMACRO( enumMoniker->Next( 1, &moniker, &fetched ), Error, ,
515                    "Error fetching next moniker" );
516    };
517    enumMoniker.reset();
518    ComPtr< IBaseFilter > source;
519    COERRORMACRO( moniker->BindToObject( 0, 0, IID_IBaseFilter,
520                                         (void **)&source ), Error, ,
521                  "Error binding moniker to base filter" );
522    moniker.reset();
523    COERRORMACRO( graphBuilder->AddFilter( source.get(), L"Source" ),
524                  Error, , "Error adding camera source to filter graph" );
525    ComPtr< IPin > sourceOut = getPin( source.get(), PINDIR_OUTPUT, 0 );
526    ERRORMACRO( sourceOut.get() != NULL, Error, ,
527                "Error getting output pin of camera source" );
528    ComPtr< IAMStreamConfig > streamConfig;
529    COERRORMACRO( sourceOut->
530                  QueryInterface( IID_IAMStreamConfig,
531                                  (void **)&streamConfig ),
532                  Error, , "Error requesting stream configuration API" );
533    int count, size;
534    COERRORMACRO( streamConfig->GetNumberOfCapabilities( &count, &size ),
535                  Error, , "Error getting number of capabilities" );
536    bool ok = false;
537    for ( int i=0; i<count; i++ ) {
538      VIDEO_STREAM_CONFIG_CAPS videoConfig;
539      AM_MEDIA_TYPE *mediaType;
540      COERRORMACRO( streamConfig->GetStreamCaps( i, &mediaType,
541                                                 (BYTE *)&videoConfig ),
542                    Error, , "Error getting stream capabilities" );
543      if ( mediaType->majortype == MEDIATYPE_Video &&
544           mediaType->cbFormat != 0 ) {
545        VIDEOINFOHEADER *infoHeader = (VIDEOINFOHEADER*)mediaType->pbFormat;
546        // TODO: choose format here !!!
547        ms_message("Setting format %ix%i",infoHeader->bmiHeader.biWidth,infoHeader->bmiHeader.biHeight);
548        streamConfig->SetFormat( mediaType );
549        ok = true;
550      };
551      if ( mediaType->cbFormat != 0 )
552        CoTaskMemFree( (PVOID)mediaType->pbFormat );
553      if ( mediaType->pUnk != NULL ) mediaType->pUnk->Release();
554      CoTaskMemFree( (PVOID)mediaType );
555      if ( ok )
556        break;
557    };
558    streamConfig.reset();
559    ERRORMACRO( ok, Error, , "Could not find any video format" );
560
561    ComPtr< IBaseFilter > grabberBase;
562    COERRORMACRO( CoCreateInstance( CLSID_SampleGrabber, NULL,
563                                    CLSCTX_INPROC, IID_IBaseFilter,
564                                    (void **)&grabberBase ),
565                  Error, , "Error creating sample grabber" );
566    COERRORMACRO( graphBuilder->AddFilter( grabberBase.get(), L"Grabber" ),
567                  Error, , "Error adding sample grabber to filter graph" );
568    ComPtr< ISampleGrabber > sampleGrabber;
569    COERRORMACRO( grabberBase->QueryInterface( IID_ISampleGrabber,
570                                               (void **)&sampleGrabber ),
571                  Error, , "Error requesting sample grabber interface" );
572    COERRORMACRO( sampleGrabber->SetOneShot( FALSE ), Error, ,
573                  "Error disabling one-shot mode" );
574    COERRORMACRO( sampleGrabber->SetBufferSamples( TRUE ), Error, ,
575                  "Error enabling buffer sampling" );
576    callback = new MSCallback(NULL);
577    COERRORMACRO( sampleGrabber->SetCallBack( callback, 0 ), Error, ,
578                  "Error setting callback interface for grabbing" );
579    ComPtr< IPin > grabberIn = getPin( grabberBase.get(), PINDIR_INPUT, 0 );
580    ERRORMACRO( grabberIn.get() != NULL, Error, ,
581                "Error getting input of sample grabber" );
582    ComPtr< IPin > grabberOut = getPin( grabberBase.get(), PINDIR_OUTPUT, 0 );
583    ERRORMACRO( grabberOut.get() != NULL, Error, ,
584                "Error getting output of sample grabber" );
585
586    ComPtr< IBaseFilter > nullRenderer;
587    COERRORMACRO( CoCreateInstance( CLSID_NullRenderer, NULL,
588                                    CLSCTX_INPROC, IID_IBaseFilter,
589                                    (void **)&nullRenderer ),
590                  Error, , "Error creating Null Renderer" );
591    COERRORMACRO( graphBuilder->AddFilter( nullRenderer.get(), L"Sink" ),
592                  Error, , "Error adding null renderer to filter graph" );
593    ComPtr< IPin > nullIn = getPin( nullRenderer.get(), PINDIR_INPUT, 0 );
594
595    cerr << endl << "Attempting to connect" << endl;
596    COERRORMACRO( graphBuilder->Connect( sourceOut.get(), grabberIn.get() ),
597                  Error, , "Error connecting source to sample grabber" );
598    COERRORMACRO( graphBuilder->Connect( grabberOut.get(), nullIn.get() ),
599                  Error, , "Error connecting sample grabber to sink" );
600
601    cerr << "Success!!!!!!!!!!!!!!!!!!!!!" << endl;
602
603    ComPtr< IMediaControl > mediaControl;
604    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaControl,
605                                                (void **)&mediaControl ),
606                  Error, , "Error requesting media control interface" );
607    COERRORMACRO( mediaControl->Run(), Error, , "Error running graph" );
608
609    ComPtr< IMediaEvent > mediaEvent;
610    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaEvent,
611                                                (void **)&mediaEvent ),
612                  Error, , "Error requesting event interface" );
613
614    cin.get();
615
616    mediaControl->Stop();
617
618    long evCode = 0;
619    mediaEvent->WaitForCompletion( INFINITE, &evCode );
620
621    // sourceOut.reset();
622    // sinkIn.reset();
623    // source.reset();
624  } catch ( Error &e ) {
625    cerr << e.what() << endl;
626    retVal = 1;
627  };
628  if ( callback != NULL ) callback->Release();
629  if ( initialized ) CoUninitialize();
630  return retVal;
631}
632
633#endif
634
635struct DscapState{
636        DscapState(){
637                callback=0;
638        }
639        ~DscapState(){
640                if (callback) callback->Release();
641        }
642        int devid;
643        MSVideoSize vsize;
644        queue_t rq;
645        ms_mutex_t mutex;
646        int frame_ind;
647        int frame_max;
648        float fps;
649        float start_time;
650        int frame_count;
651        MSPixFmt fmt;
652        ComPtr< IBaseFilter > source;
653        ComPtr< IBaseFilter > nullRenderer;
654        ComPtr< IBaseFilter > grabberBase;
655        ComPtr< IMediaControl > mediaControl;
656        ComPtr< IMediaEvent > mediaEvent;
657        MSCallback * callback;
658};
659
660
661
662MSCallback::MSCallback(DscapState *s): m_refCount(1), mState(s)
663{
664}
665
666MSCallback::~MSCallback(void)
667{
668  ms_message("MSCallback::~MSCallback");
669}
670
671STDMETHODIMP MSCallback::QueryInterface(REFIID riid, void **ppv)
672{
673#ifndef NDEBUG
674        ms_message("MSCallback::QueryInterface");
675#endif
676  HRESULT retval;
677  if ( ppv == NULL ) return E_POINTER;
678  /*
679  if ( riid == IID_IUnknown ) {
680    *ppv = static_cast< IUnknown * >( this );
681    AddRef();
682    retval = S_OK;
683  } else if ( riid == IID_ISampleGrabberCB ) {
684    *ppv = static_cast< ISampleGrabberCB * >( this );
685    AddRef();
686    retval = S_OK;
687    } else */ {
688#ifndef NDEBUG
689    cerr << setbase( 16 ) << setfill('0')
690         << "DEFINE_GUID( ..., 0x" << setw(8) << (int)riid.Data1 << ", 0x"
691         << setw(4) << (int)riid.Data2 << "," << endl
692         << "             0x"
693         << setw(4) << (int)riid.Data3 << ", 0x" << setw(2)
694         << (int)riid.Data4[0] << ", 0x"
695         << (int)riid.Data4[1] << ", 0x"
696         << (int)riid.Data4[2] << ", 0x"
697         << (int)riid.Data4[3] << ", 0x"
698         << (int)riid.Data4[4] << ", 0x"
699         << (int)riid.Data4[5] << ", 0x"
700         << (int)riid.Data4[6] << ", 0x"
701         << (int)riid.Data4[7] << " ) ?" << endl
702         << setfill( ' ' ) << setw( 0 ) << setbase( 10 );
703#endif
704    retval = E_NOINTERFACE;
705  };
706  return retval;
707};
708
709STDMETHODIMP_(ULONG) MSCallback::AddRef(void)
710{
711        ms_message("MSCallback::AddRef");
712  m_refCount++;
713  return m_refCount;
714}
715
716STDMETHODIMP_(ULONG) MSCallback::Release(void)
717{
718  ms_message("MSCallback::Release");
719
720  if ( !InterlockedDecrement( &m_refCount ) ) {
721                int refcnt=m_refCount;
722                delete this;
723                return refcnt;
724        }
725  return m_refCount;
726}
727
728static void dummy(void*p){
729}
730
731STDMETHODIMP MSCallback::SampleCB( double par1 , IMediaSample * sample)
732{
733        uint8_t *p;
734        unsigned int size;
735        if (sample->GetPointer(&p)!=S_OK){
736                ms_error("error in GetPointer()");
737                return S_OK;
738        }
739        size=sample->GetSize();
740        ms_message( "MSCallback::SampleCB pointer=%p, size=%i",p,size);
741        mblk_t *m=esballoc(p,size,0,dummy);
742        m->b_wptr+=size;
743        ms_mutex_lock(&mState->mutex);
744        putq(&mState->rq,m);
745        ms_mutex_unlock(&mState->mutex);
746        return S_OK;
747}
748
749
750
751STDMETHODIMP MSCallback::BufferCB( double, BYTE *b, long len)
752{
753        ms_message("MSCallback::BufferCB");
754
755        return S_OK;
756}
757
758static void dscap_init(MSFilter *f){
759        DscapState *s=new DscapState;
760        s->vsize.width=MS_VIDEO_SIZE_CIF_W;
761        s->vsize.height=MS_VIDEO_SIZE_CIF_H;
762        qinit(&s->rq);
763        ms_mutex_init(&s->mutex,NULL);
764        s->start_time=0;
765        s->frame_count=-1;
766        s->fps=15;
767        s->fmt=MS_YUV420P;
768        f->data=s;
769}
770
771
772
773static void dscap_uninit(MSFilter *f){
774        DscapState *s=(DscapState*)f->data;
775        flushq(&s->rq,0);
776        ms_mutex_destroy(&s->mutex);
777        delete s;
778}
779
780static char * fourcc_to_char(char *str, uint32_t fcc){
781        memcpy(str,&fcc,4);
782        str[4]='\0';
783        return str;
784}
785
786static int find_best_format(ComPtr<IAMStreamConfig> streamConfig, int count, MSVideoSize *requested_size, MSPixFmt requested_fmt ){
787        int i;
788        MSVideoSize best_found=(MSVideoSize){32768,32768};
789        int best_index=-1;
790        char fccstr[5];
791        char selected_fcc[5];
792        for (i=0; i<count; i++ ) {
793                VIDEO_STREAM_CONFIG_CAPS videoConfig;
794                AM_MEDIA_TYPE *mediaType;
795                COERRORMACRO( streamConfig->GetStreamCaps( i, &mediaType,
796                                                 (BYTE *)&videoConfig ),
797                    Error, , "Error getting stream capabilities" );
798                if ( mediaType->majortype == MEDIATYPE_Video &&
799           mediaType->cbFormat != 0 ) {
800                        VIDEOINFOHEADER *infoHeader = (VIDEOINFOHEADER*)mediaType->pbFormat;
801                        ms_message("Seeing format %ix%i %s",infoHeader->bmiHeader.biWidth,infoHeader->bmiHeader.biHeight,
802                                        fourcc_to_char(fccstr,infoHeader->bmiHeader.biCompression));
803                        if (ms_fourcc_to_pix_fmt(infoHeader->bmiHeader.biCompression)==requested_fmt){
804                                MSVideoSize cur;
805                                cur.width=infoHeader->bmiHeader.biWidth;
806                                cur.height=infoHeader->bmiHeader.biHeight;
807                                if (ms_video_size_greater_than(cur,*requested_size)){
808                                        if (ms_video_size_greater_than(best_found,cur)){
809                                                best_found=cur;
810                                                best_index=i;
811                                                fourcc_to_char(selected_fcc,infoHeader->bmiHeader.biCompression);
812                                        }
813                                }
814                        }
815                };
816                if ( mediaType->cbFormat != 0 )
817                        CoTaskMemFree( (PVOID)mediaType->pbFormat );
818                if ( mediaType->pUnk != NULL ) mediaType->pUnk->Release();
819                        CoTaskMemFree( (PVOID)mediaType );
820        }
821        if (best_index!=-1) {
822                *requested_size=best_found;
823                ms_message("Best camera format is %s %ix%i",selected_fcc,best_found.width,best_found.height);
824        }
825        return best_index;
826}
827
828static int select_best_format(DscapState *s, ComPtr<IAMStreamConfig> streamConfig, int count){
829        int index;
830        s->fmt=MS_YUV420P;
831        index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
832        if (index!=-1) goto success;
833        s->fmt=MS_YUY2;
834        index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
835        if (index!=-1) goto success;
836        s->fmt=MS_YUYV;
837        index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
838        if (index!=-1) goto success;
839        s->fmt=MS_RGB24;
840        index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
841        if (index!=-1) {
842                s->fmt=MS_RGB24_REV;
843                goto success;
844        }
845        ms_error("This camera does not support any of our pixel formats.");
846        return -1;
847       
848        success:
849        VIDEO_STREAM_CONFIG_CAPS videoConfig;
850        AM_MEDIA_TYPE *mediaType;
851        COERRORMACRO( streamConfig->GetStreamCaps( index, &mediaType,
852                                                 (BYTE *)&videoConfig ),
853                                Error, , "Error getting stream capabilities" );
854    streamConfig->SetFormat( mediaType );
855    return 0;
856}
857
858static void create_dshow_graph(DscapState *s){
859        ComPtr< ICreateDevEnum > createDevEnum;
860        COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
861    createDevEnum.coCreateInstance( CLSID_SystemDeviceEnum,
862                                    IID_ICreateDevEnum, "Could not create "
863                                    "device enumerator" );
864    ComPtr< IEnumMoniker > enumMoniker;
865    if (createDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &enumMoniker, 0 )!=S_OK){
866                ms_error("Fail to create class enumerator.");
867                return;
868        }
869    createDevEnum.reset();
870    enumMoniker->Reset();
871
872    int index = 0;
873    ULONG fetched = 0;
874        ComPtr< IGraphBuilder > graphBuilder;
875        graphBuilder.coCreateInstance( CLSID_FilterGraph, IID_IGraphBuilder,
876                                   "Could not create graph builder "
877                                   "interface" );
878    ComPtr< IMoniker > moniker;
879    for ( int i=0;enumMoniker->Next( 1, &moniker, &fetched )==S_OK;++i ) {
880                if (i==s->devid){
881                        if (moniker->BindToObject( 0, 0, IID_IBaseFilter, (void **)&s->source )!=S_OK){
882                                ms_error("Error binding moniker to base filter" );
883                                return;
884                        }
885                }
886        }
887        if (s->source.get()==0){
888                ms_error("Could not interface with webcam devid=%i",s->devid);
889                return;
890        }
891        moniker.reset();
892    enumMoniker.reset();
893    s->callback = new MSCallback(s);
894    ms_message("Callback created");
895    fflush(NULL);
896    try{
897    COERRORMACRO( graphBuilder->AddFilter( s->source.get(), L"Source" ),
898                  Error, , "Error adding camera source to filter graph" );
899    ComPtr< IPin > sourceOut = getPin( s->source.get(), PINDIR_OUTPUT, 0 );
900    ERRORMACRO( sourceOut.get() != NULL, Error, ,
901                "Error getting output pin of camera source" );
902    ComPtr< IAMStreamConfig > streamConfig;
903    COERRORMACRO( sourceOut->
904                  QueryInterface( IID_IAMStreamConfig,
905                                  (void **)&streamConfig ),
906                  Error, , "Error requesting stream configuration API" );
907    int count, size;
908    COERRORMACRO( streamConfig->GetNumberOfCapabilities( &count, &size ),
909                  Error, , "Error getting number of capabilities" );
910    select_best_format(s,streamConfig,count);
911   
912    streamConfig.reset();
913
914    COERRORMACRO( CoCreateInstance( CLSID_SampleGrabber, NULL,
915                                    CLSCTX_INPROC, IID_IBaseFilter,
916                                    (void **)&s->grabberBase ),
917                  Error, , "Error creating sample grabber" );
918    COERRORMACRO( graphBuilder->AddFilter( s->grabberBase.get(), L"Grabber" ),
919                  Error, , "Error adding sample grabber to filter graph" );
920    ComPtr< ISampleGrabber > sampleGrabber;
921    COERRORMACRO( s->grabberBase->QueryInterface( IID_ISampleGrabber,
922                                               (void **)&sampleGrabber ),
923                  Error, , "Error requesting sample grabber interface" );
924    COERRORMACRO( sampleGrabber->SetOneShot( FALSE ), Error, ,
925                  "Error disabling one-shot mode" );
926    COERRORMACRO( sampleGrabber->SetBufferSamples( TRUE ), Error, ,
927                  "Error enabling buffer sampling" );
928
929    COERRORMACRO( sampleGrabber->SetCallBack( s->callback, 0 ), Error, ,
930                  "Error setting callback interface for grabbing" );
931    ComPtr< IPin > grabberIn = getPin( s->grabberBase.get(), PINDIR_INPUT, 0 );
932    ERRORMACRO( grabberIn.get() != NULL, Error, ,
933                "Error getting input of sample grabber" );
934    ComPtr< IPin > grabberOut = getPin( s->grabberBase.get(), PINDIR_OUTPUT, 0 );
935    ERRORMACRO( grabberOut.get() != NULL, Error, ,
936                "Error getting output of sample grabber" );
937
938   
939    COERRORMACRO( CoCreateInstance( CLSID_NullRenderer, NULL,
940                                    CLSCTX_INPROC, IID_IBaseFilter,
941                                    (void **)&s->nullRenderer ),
942                  Error, , "Error creating Null Renderer" );
943    COERRORMACRO( graphBuilder->AddFilter( s->nullRenderer.get(), L"Sink" ),
944                  Error, , "Error adding null renderer to filter graph" );
945    ComPtr< IPin > nullIn = getPin( s->nullRenderer.get(), PINDIR_INPUT, 0 );
946
947    ms_message("Attempting to connect");
948    COERRORMACRO( graphBuilder->Connect( sourceOut.get(), grabberIn.get() ),
949                  Error, , "Error connecting source to sample grabber" );
950    COERRORMACRO( graphBuilder->Connect( grabberOut.get(), nullIn.get() ),
951                  Error, , "Error connecting sample grabber to sink" );
952
953    ms_message("Success!!!!!!!!!!!!!!!!!!!!!");
954
955
956        ms_message("Querying control interface");
957    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaControl,
958                                                (void **)&s->mediaControl ),
959                  Error, , "Error requesting media control interface" );
960        ms_message("Got the control interface (%p).",s->mediaControl.get());
961    ms_message("Going to start the graph");
962    HRESULT r;
963        if ((r=s->mediaControl->Run())!=S_OK){
964                ms_error("Error starting graph (%i)",r);
965        }
966    ms_message("Graph started");
967    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaEvent,
968                                                (void **)&s->mediaEvent ),
969                  Error, , "Error requesting event interface" );
970    ms_message("Graph created");
971        } catch ( Error &e ) {
972        ms_error(e.what());
973        };
974}
975
976static void dscap_preprocess(MSFilter * obj){
977        DscapState *s=(DscapState*)obj->data;
978        create_dshow_graph(s);
979        //toto();
980    ms_message("preprocess done.");
981}
982
983static void dscap_postprocess(MSFilter * obj){
984        DscapState *s=(DscapState*)obj->data;
985        if (s->mediaControl.get()!=NULL){
986                s->mediaControl->Stop();
987        long evCode = 0;
988        s->mediaEvent->WaitForCompletion( INFINITE, &evCode );
989        }
990        flushq(&s->rq,0);
991}
992
993static void dscap_process(MSFilter * obj){
994        DscapState *s=(DscapState*)obj->data;
995        mblk_t *m;
996        uint32_t timestamp;
997        int cur_frame;
998
999        if (s->frame_count==-1){
1000                s->start_time=(float)obj->ticker->time;
1001                s->frame_count=0;
1002        }
1003
1004        cur_frame=(int)((obj->ticker->time-s->start_time)*s->fps/1000.0);
1005        if (cur_frame>s->frame_count){
1006                mblk_t *om=NULL;
1007                /*keep the most recent frame if several frames have been captured */
1008               
1009                ms_mutex_lock(&s->mutex);
1010                while((m=getq(&s->rq))!=NULL){
1011                        ms_mutex_unlock(&s->mutex);
1012                        if (om!=NULL) freemsg(om);
1013                        om=m;
1014                        ms_mutex_lock(&s->mutex);
1015                }
1016                ms_mutex_unlock(&s->mutex);
1017                if (om!=NULL){
1018                        timestamp=(uint32_t)(obj->ticker->time*90);/* rtp uses a 90000 Hz clockrate for video*/
1019                        mblk_set_timestamp_info(om,timestamp);
1020                        ms_queue_put(obj->outputs[0],om);
1021                }
1022                s->frame_count++;
1023        }
1024}
1025
1026static int dscap_set_fps(MSFilter *f, void *arg){
1027        DscapState *s=(DscapState*)f->data;
1028        s->fps=*((float*)arg);
1029        return 0;
1030}
1031
1032static int dscap_get_pix_fmt(MSFilter *f,void *arg){
1033        DscapState *s=(DscapState*)f->data;
1034        *((MSPixFmt*)arg)=s->fmt;
1035        return 0;
1036}
1037
1038static int dscap_set_vsize(MSFilter *f, void *arg){
1039        DscapState *s=(DscapState*)f->data;
1040        s->vsize=*((MSVideoSize*)arg);
1041        return 0;
1042}
1043
1044static int dscap_get_vsize(MSFilter *f, void *arg){
1045        DscapState *s=(DscapState*)f->data;
1046        MSVideoSize *vs=(MSVideoSize*)arg;
1047        *vs=s->vsize;
1048        return 0;
1049}
1050
1051static MSFilterMethod methods[]={
1052        {       MS_FILTER_SET_FPS       ,       dscap_set_fps   },
1053        {       MS_FILTER_GET_PIX_FMT   ,       dscap_get_pix_fmt       },
1054        {       MS_FILTER_SET_VIDEO_SIZE, dscap_set_vsize       },
1055        {       MS_FILTER_GET_VIDEO_SIZE, dscap_get_vsize       },
1056        {       0                                                               ,       NULL                    }
1057};
1058
1059MSFilterDesc ms_dscap_desc={
1060        MS_FILTER_PLUGIN_ID,
1061        "MSDsCap",
1062        N_("A webcam grabber based on directshow."),
1063        MS_FILTER_OTHER,
1064        NULL,
1065        0,
1066        1,
1067        dscap_init,
1068        dscap_preprocess,
1069        dscap_process,
1070        dscap_postprocess,
1071        dscap_uninit,
1072        methods
1073};
1074
1075
1076static void ms_dshow_detect(MSWebCamManager *obj);
1077static MSFilter * ms_dshow_create_reader(MSWebCam *obj){
1078        MSFilter *f=ms_filter_new_from_desc(&ms_dscap_desc);
1079        DscapState *s=(DscapState*)f->data;
1080        s->devid=(int)obj->data;
1081        return f;
1082}
1083
1084static MSWebCamDesc ms_dshow_cam_desc={
1085        "Directshow capture",
1086        &ms_dshow_detect,
1087        NULL,
1088        &ms_dshow_create_reader,
1089        NULL
1090};
1091
1092static void ms_dshow_detect(MSWebCamManager *obj){
1093        int i;
1094        MSWebCam *cam;
1095        ComPtr<IPropertyBag> pBag;
1096       
1097        COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
1098 
1099    ComPtr< ICreateDevEnum > createDevEnum;
1100    createDevEnum.coCreateInstance( CLSID_SystemDeviceEnum,
1101                                    IID_ICreateDevEnum, "Could not create "
1102                                    "device enumerator" );
1103    ComPtr< IEnumMoniker > enumMoniker;
1104    if (createDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &enumMoniker, 0 )!=S_OK){
1105                ms_error("Fail to create class enumerator.");
1106                return;
1107        }
1108    createDevEnum.reset();
1109    enumMoniker->Reset();
1110   
1111    int index = 0;
1112    ULONG fetched = 0;
1113    ComPtr< IMoniker > moniker;
1114    for ( int i=0;enumMoniker->Next( 1, &moniker, &fetched )==S_OK;++i ) {
1115                VARIANT var;
1116                if (moniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag )!=S_OK)
1117                        continue;
1118                VariantInit(&var);
1119                if (pBag->Read( L"FriendlyName", &var, NULL )!=S_OK)
1120                        continue;
1121        char szName[256];
1122                WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0);
1123                MSWebCam *cam=ms_web_cam_new(&ms_dshow_cam_desc);
1124        cam->name=ms_strdup(szName);
1125        cam->data=(void*)i;
1126                ms_web_cam_manager_prepend_cam(obj,cam);
1127        VariantClear(&var);
1128        }
1129    enumMoniker.reset();
1130}
1131
1132extern "C" void libmsdscap_init(void){
1133                ms_web_cam_manager_register_desc(ms_web_cam_manager_get(),&ms_dshow_cam_desc);
1134}
Note: See TracBrowser for help on using the repository browser.