source: mediastreamer2/linphone/mediastreamer2/src/winvideods.c @ 313:592ddc97785f

Last change on this file since 313:592ddc97785f was 313:592ddc97785f, checked in by aymeric <aymeric@…>, 4 years ago

fix unix file mode

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

File size: 36.5 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#define UNICODE
21#define AYMERIC_TEST
22#define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA
23
24#include "mediastreamer2/msvideo.h"
25#include "mediastreamer2/msticker.h"
26#include "mediastreamer2/msv4l.h"
27#include "mediastreamer2/mswebcam.h"
28
29#include "nowebcam.h"
30#include <ffmpeg/avcodec.h>
31
32#include <dshow.h>
33#include <dmodshow.h>
34#include <dmoreg.h>
35
36#include <streams.h>
37#include <initguid.h>
38#include "dxfilter.h"
39EXTERN_C const CLSID CLSID_NullRenderer;
40
41HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);
42void RemoveGraphFromRot(DWORD pdwRegister);
43
44typedef struct V4wState{
45
46        char dev[512];
47        int devidx;
48
49        IGraphBuilder *m_pGraph;
50        ICaptureGraphBuilder2 *m_pBuilder;
51        IMediaControl *m_pControl;
52        CDXFilter *m_pDXFilter;
53        IBaseFilter *m_pIDXFilter;     
54        IBaseFilter *m_pNullRenderer;
55        IBaseFilter *m_pDeviceFilter;
56        DWORD rotregvalue;
57
58        MSVideoSize vsize;
59        int pix_fmt;
60        mblk_t *mire[10];
61        char nowebcamimage[256];
62        queue_t rq;
63        ms_mutex_t mutex;
64        int frame_ind;
65        int frame_max;
66        float fps;
67        float start_time;
68        int frame_count;
69}V4wState;
70
71static V4wState *s_callback=NULL;
72
73static void dummy(void*p){
74}
75
76HRESULT ( Callback)(IMediaSample* pSample, REFERENCE_TIME* sTime, REFERENCE_TIME* eTime, BOOL changed)
77{
78        BYTE *byte_buf=NULL;
79        mblk_t *buf;
80
81        V4wState *s = s_callback;
82        if (s==NULL)
83                return S_OK;
84
85        HRESULT hr = pSample->GetPointer(&byte_buf);
86        if (FAILED(hr))
87        {
88                return S_OK;
89        }
90
91        int size = pSample->GetActualDataLength();
92        if (size>+1000)
93        {
94                buf=allocb(size,0);
95                memcpy(buf->b_wptr, byte_buf, size);
96                if (s->pix_fmt==MS_RGB24)
97                {
98                        /* Conversion from top down bottom up (BGR to RGB and flip) */
99                        unsigned long Index,nPixels;
100                        unsigned char *blue;
101                        unsigned char tmp;
102                        short iPixelSize;
103
104                        blue=buf->b_wptr;
105
106                        nPixels=s->vsize.width*s->vsize.height;
107                        iPixelSize=24/8;
108                 
109                        for(Index=0;Index!=nPixels;Index++)  // For each pixel
110                        {
111                                tmp=*blue;
112                                *blue=*(blue+2);
113                                *(blue+2)=tmp;
114                                blue+=iPixelSize;
115                        }
116 
117                        unsigned char *pLine1, *pLine2;
118                        int iLineLen,iIndex;
119
120                        iLineLen=s->vsize.width*iPixelSize;
121                        pLine1=buf->b_wptr;
122                        pLine2=&(buf->b_wptr)[iLineLen * (s->vsize.height - 1)];
123
124                        for( ;pLine1<pLine2;pLine2-=(iLineLen*2))
125                        {
126                                for(iIndex=0;iIndex!=iLineLen;pLine1++,pLine2++,iIndex++)
127                                {
128                                        tmp=*pLine1;
129                                        *pLine1=*pLine2;
130                                        *pLine2=tmp;       
131                                }
132                        }
133                }
134                buf->b_wptr+=size; 
135               
136                ms_mutex_lock(&s->mutex);
137                putq(&s->rq, buf);
138                ms_mutex_unlock(&s->mutex);
139
140        }
141        return S_OK;
142}
143
144HRESULT GetPinCategory(IPin *pPin, GUID *pPinCategory)
145{
146    HRESULT hr;
147    IKsPropertySet *pKs;
148    hr = pPin->QueryInterface(IID_IKsPropertySet, (void **)&pKs);
149    if (FAILED(hr))
150    {
151        // The pin does not support IKsPropertySet.
152        return hr;
153    }
154    // Try to retrieve the pin category.
155    DWORD cbReturned;
156    hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, 
157        pPinCategory, sizeof(GUID), &cbReturned);
158
159    // If this succeeded, pPinCategory now contains the category GUID.
160
161    pKs->Release();
162    return hr;
163}
164
165int try_format(V4wState *s, int format, GUID *pPinCategory)
166{
167    HRESULT hr=S_OK;
168    IEnumPins *pEnum=0;
169    ULONG ulFound;
170    IPin *pPin;
171
172        GUID guid_format;
173        DWORD biCompression;
174        DWORD biBitCount;
175
176        // Verify input
177    if (!s->m_pDeviceFilter)
178        return -1;
179
180        if (format == MS_YUV420P)
181                guid_format = (GUID)FOURCCMap(MAKEFOURCC('I','4','2','0'));
182        else if (format == MS_YUYV)
183                guid_format = MEDIASUBTYPE_YUYV;
184        else if (format == MS_UYVY)
185                guid_format = MEDIASUBTYPE_UYVY;
186        else if (format == MS_RGB24)
187                guid_format = MEDIASUBTYPE_RGB24;
188        else if (format == MS_YUY2)
189                guid_format = MEDIASUBTYPE_YUY2;
190
191        if (format == MS_YUV420P)
192                biCompression = MAKEFOURCC('I','4','2','0');
193        else if (format == MS_YUYV)
194                biCompression = MAKEFOURCC('Y','U','Y','V');
195        else if (format == MS_UYVY)
196                biCompression = MAKEFOURCC('U','Y','V','Y');
197        else if (format == MS_RGB24)
198                biCompression = BI_RGB;
199        else if (format == MS_YUY2)
200                biCompression = MAKEFOURCC('Y','U','Y','2');
201       
202        if (format == MS_YUV420P)
203                biBitCount = 12;
204        else if (format == MS_YUYV)
205                biBitCount = 16;
206        else if (format == MS_UYVY)
207                biBitCount = 16;
208        else if (format == MS_RGB24)
209                biBitCount = 24;
210        else if (format == MS_YUY2)
211                biBitCount = 16;
212       
213    // Get pin enumerator
214        hr = s->m_pDeviceFilter->EnumPins(&pEnum);
215    if(FAILED(hr)) 
216        return -1;
217
218    pEnum->Reset();
219
220    // Count every pin on the filter
221    while(S_OK == pEnum->Next(1, &pPin, &ulFound))
222    {
223        PIN_DIRECTION pindir = (PIN_DIRECTION) 3;
224
225        hr = pPin->QueryDirection(&pindir);
226
227        if(pindir != PINDIR_INPUT)
228                {
229                        IEnumMediaTypes *ppEnum;
230            ULONG ulFound2;
231
232      GetPinCategory(pPin, pPinCategory);
233      if (*pPinCategory!=PIN_CATEGORY_CAPTURE
234        && *pPinCategory!=PIN_CATEGORY_PREVIEW)
235        continue;
236
237      hr = pPin->EnumMediaTypes(&ppEnum);
238                        if(FAILED(hr)) 
239                                continue;
240
241                        AM_MEDIA_TYPE *ppMediaTypes;
242                        while(S_OK == ppEnum->Next(1, &ppMediaTypes, &ulFound2))
243                        {
244                                if (ppMediaTypes->formattype != FORMAT_VideoInfo)
245                                        continue;
246                                if (ppMediaTypes->majortype != MEDIATYPE_Video)
247                                        continue;
248                                if (ppMediaTypes->subtype != guid_format)
249                                        continue;
250                                VIDEOINFO *pvi = (VIDEOINFO *)ppMediaTypes->pbFormat;
251                                if (pvi->bmiHeader.biCompression!=biCompression)
252                                        continue;
253                                if (pvi->bmiHeader.biBitCount!=biBitCount)
254                                        continue;
255
256        pPin->Release();
257                          pEnum->Release();
258                                return 0;
259                        }
260                }
261
262        pPin->Release();
263    }
264
265    pEnum->Release();
266    return -1;
267}
268
269int try_format_size(V4wState *s, int format, int width, int height, GUID *pPinCategory)
270{
271    HRESULT hr=S_OK;
272    IEnumPins *pEnum=0;
273    ULONG ulFound;
274    IPin *pPin;
275
276        GUID guid_format;
277        DWORD biCompression;
278        DWORD biBitCount;
279
280        // Verify input
281    if (!s->m_pDeviceFilter)
282        return -1;
283
284        if (format == MS_YUV420P)
285                guid_format = (GUID)FOURCCMap(MAKEFOURCC('I','4','2','0'));
286        else if (format == MS_YUYV)
287                guid_format = MEDIASUBTYPE_YUYV;
288        else if (format == MS_UYVY)
289                guid_format = MEDIASUBTYPE_UYVY;
290        else if (format == MS_RGB24)
291                guid_format = MEDIASUBTYPE_RGB24;
292        else if (format == MS_YUY2)
293                guid_format = MEDIASUBTYPE_YUY2;
294
295        if (format == MS_YUV420P)
296                biCompression = MAKEFOURCC('I','4','2','0');
297        else if (format == MS_YUYV)
298                biCompression = MAKEFOURCC('Y','U','Y','V');
299        else if (format == MS_UYVY)
300                biCompression = MAKEFOURCC('U','Y','V','Y');
301        else if (format == MS_RGB24)
302                biCompression = BI_RGB;
303        else if (format == MS_YUY2)
304                biCompression = MAKEFOURCC('Y','U','Y','2');
305       
306        if (format == MS_YUV420P)
307                biBitCount = 12;
308        else if (format == MS_YUYV)
309                biBitCount = 16;
310        else if (format == MS_UYVY)
311                biBitCount = 16;
312        else if (format == MS_RGB24)
313                biBitCount = 24;
314        else if (format == MS_YUY2)
315                biBitCount = 16;
316
317    // Get pin enumerator
318        hr = s->m_pDeviceFilter->EnumPins(&pEnum);
319    if(FAILED(hr)) 
320        return -1;
321
322    pEnum->Reset();
323
324    // Count every pin on the filter
325    while(S_OK == pEnum->Next(1, &pPin, &ulFound))
326    {
327        PIN_DIRECTION pindir = (PIN_DIRECTION) 3;
328
329        hr = pPin->QueryDirection(&pindir);
330
331        if(pindir != PINDIR_INPUT)
332                {
333                        IEnumMediaTypes *ppEnum;
334                    ULONG ulFound2;
335                        hr = pPin->EnumMediaTypes(&ppEnum);
336                        if(FAILED(hr)) 
337                                continue;
338
339      GUID pCurrentPinCategory;
340      GetPinCategory(pPin, &pCurrentPinCategory);
341      if (*pPinCategory!=pCurrentPinCategory)
342        continue;
343
344                        AM_MEDIA_TYPE *ppMediaTypes;
345                        while(S_OK == ppEnum->Next(1, &ppMediaTypes, &ulFound2))
346                        {
347                                if (ppMediaTypes->formattype != FORMAT_VideoInfo)
348                                        continue;
349                                if (ppMediaTypes->majortype != MEDIATYPE_Video)
350                                        continue;
351                                if (ppMediaTypes->subtype != guid_format)
352                                        continue;
353                                VIDEOINFO *pvi = (VIDEOINFO *)ppMediaTypes->pbFormat;
354                                if (pvi->bmiHeader.biCompression!=biCompression)
355                                        continue;
356                                if (pvi->bmiHeader.biBitCount!=biBitCount)
357                                        continue;
358                                if (pvi->bmiHeader.biHeight!=height)
359                                        continue;
360                                if (pvi->bmiHeader.biWidth!=width)
361                                        continue;
362
363                                s->vsize.width = width;
364                                s->vsize.height = height;
365
366                                pPin->Release();
367                            pEnum->Release();
368                                return 0;
369                        }
370                }
371
372        pPin->Release();
373    } 
374
375    pEnum->Release();
376    return -1;
377}
378
379static int v4w_configure_videodevice(V4wState *s)
380{
381        // Initialize COM
382        CoInitialize(NULL);
383
384        // get a Graph
385        HRESULT hr= CoCreateInstance (CLSID_FilterGraph,
386                          NULL,
387                          CLSCTX_INPROC_SERVER,
388                          IID_IGraphBuilder, //IID_IBaseFilter,
389                          (void **)&s->m_pGraph);
390        if(FAILED(hr))
391        {
392                return -1;
393        }
394
395        // get a CaptureGraphBuilder2
396        hr= CoCreateInstance (CLSID_CaptureGraphBuilder2,
397                          NULL,
398                          CLSCTX_INPROC_SERVER,
399                          IID_ICaptureGraphBuilder2, //IID_IBaseFilter,
400                          (void **)&s->m_pBuilder);
401        if(FAILED(hr))
402        {
403                return -2;
404        }
405
406        // connect capture graph builder with the graph
407        s->m_pBuilder->SetFiltergraph(s->m_pGraph);
408
409        // get mediacontrol so we can start and stop the filter graph
410        hr=s->m_pGraph->QueryInterface (IID_IMediaControl, (void **)&s->m_pControl);
411        if(FAILED(hr))
412        {
413                return -3;
414        }
415
416
417#ifdef _DEBUG
418        HANDLE m_hLogFile=CreateFile(L"DShowGraphLog.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
419        if(m_hLogFile!=INVALID_HANDLE_VALUE)
420        {
421                hr=s->m_pGraph->SetLogFile((DWORD_PTR)m_hLogFile);
422                /* ASSERT(SUCCEEDED(hr)); */
423        }
424       
425        //AddGraphToRot(s->m_pGraph, &s->rotregvalue);
426#endif
427
428        ICreateDevEnum *pCreateDevEnum = NULL;
429        IEnumMoniker *pEnumMoniker = NULL;
430        IMoniker *pMoniker = NULL;
431
432        ULONG nFetched = 0;
433
434        hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, 
435                IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum);
436        if(FAILED(hr))
437        {
438                return -4;
439        }
440
441        hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
442                &pEnumMoniker, 0);
443        if (FAILED(hr) || pEnumMoniker == NULL) {
444                //printf("no device\n");
445                return -5;
446        }
447
448        pEnumMoniker->Reset();
449
450        int pos=0;
451  while(S_OK == pEnumMoniker->Next(1, &pMoniker, &nFetched) )
452  {
453    IPropertyBag *pBag;
454    hr = pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag );
455    if( hr != S_OK )
456       continue; 
457
458    if (s->dev[0]=='\0')
459      break;
460
461    VARIANT var;
462    VariantInit(&var);
463    hr = pBag->Read( L"FriendlyName", &var, NULL ); 
464    if( hr != S_OK )
465    {
466      pMoniker->Release();
467      continue;
468    }
469    //USES_CONVERSION;
470    char szName[256];
471
472    WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0);
473    VariantClear(&var); 
474
475    if (strcmp(szName, s->dev)==0)
476      break;
477
478    pMoniker->Release();
479    pBag->Release();
480    pMoniker=NULL;
481    pBag=NULL;
482        }
483
484        if(pMoniker==NULL)
485  {
486          int pos=0;
487    while(S_OK == pEnumMoniker->Next(1, &pMoniker, &nFetched) )
488    {
489      IPropertyBag *pBag;
490      hr = pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag );
491      if( hr != S_OK )
492         continue; 
493    }
494
495        }
496
497        if(pMoniker==NULL)
498        {
499                return -6;
500        }
501
502        hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&s->m_pDeviceFilter );
503        if(FAILED(hr))
504        {
505                return -7;
506        }
507
508        s->m_pGraph->AddFilter(s->m_pDeviceFilter, L"Device Filter");
509
510        pMoniker->Release();
511        pEnumMoniker->Release();
512        pCreateDevEnum->Release();
513
514
515  GUID pPinCategory;
516
517        if (try_format(s, s->pix_fmt, &pPinCategory)==0)
518                s->pix_fmt = s->pix_fmt;
519        else if (try_format(s,MS_YUV420P, &pPinCategory)==0)
520                s->pix_fmt = MS_YUV420P;
521        else if (try_format(s,MS_YUY2, &pPinCategory)==0)
522                s->pix_fmt = MS_YUY2;
523        else if (try_format(s,MS_YUYV, &pPinCategory)==0)
524                s->pix_fmt = MS_YUYV;
525        else if (try_format(s,MS_UYVY, &pPinCategory)==0)
526                s->pix_fmt = MS_UYVY;
527        else if (try_format(s,MS_RGB24, &pPinCategory)==0)
528                s->pix_fmt = MS_RGB24;
529        else
530        {
531                ms_error("Unsupported video pixel format.");
532                return -8;
533        }
534       
535        if (s->pix_fmt == MS_YUV420P)
536                ms_message("Driver supports YUV420P, using that format.");
537        else if (s->pix_fmt == MS_YUY2)
538                ms_message("Driver supports YUY2 (UYVY), using that format.");
539        else if (s->pix_fmt == MS_YUYV)
540                ms_message("Driver supports YUV422, using that format.");
541        else if (s->pix_fmt == MS_UYVY)
542                ms_message("Driver supports UYVY, using that format.");
543        else if (s->pix_fmt == MS_RGB24)
544                ms_message("Driver supports RGB24, using that format.");
545
546        if (try_format_size(s, s->pix_fmt, s->vsize.width, s->vsize.height, &pPinCategory)==0)
547                ms_message("Selected Size: %ix%i.", s->vsize.width, s->vsize.height);
548        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H, &pPinCategory)==0)
549                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H);
550        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H, &pPinCategory)==0)
551                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H);
552        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H, &pPinCategory)==0)
553                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H);
554        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H, &pPinCategory)==0)
555                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H);
556        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H, &pPinCategory)==0)
557                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H);
558        else
559        {
560                ms_error("No supported size found for format.");
561                /* size not supported? */
562                return -9;
563        }
564
565        return 0;
566}
567
568static int v4w_open_videodevice(V4wState *s)
569{
570        // Initialize COM
571        CoInitialize(NULL);
572
573        // get a Graph
574        HRESULT hr= CoCreateInstance (CLSID_FilterGraph,
575                          NULL,
576                          CLSCTX_INPROC_SERVER,
577                          IID_IGraphBuilder, //IID_IBaseFilter,
578                          (void **)&s->m_pGraph);
579        if(FAILED(hr))
580        {
581                return -1;
582        }
583
584        // get a CaptureGraphBuilder2
585        hr= CoCreateInstance (CLSID_CaptureGraphBuilder2,
586                          NULL,
587                          CLSCTX_INPROC_SERVER,
588                          IID_ICaptureGraphBuilder2, //IID_IBaseFilter,
589                          (void **)&s->m_pBuilder);
590        if(FAILED(hr))
591        {
592                return -2;
593        }
594
595        // connect capture graph builder with the graph
596        s->m_pBuilder->SetFiltergraph(s->m_pGraph);
597
598        // get mediacontrol so we can start and stop the filter graph
599        hr=s->m_pGraph->QueryInterface (IID_IMediaControl, (void **)&s->m_pControl);
600        if(FAILED(hr))
601        {
602                return -3;
603        }
604
605
606#ifdef _DEBUG
607        HANDLE m_hLogFile=CreateFile(L"DShowGraphLog.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
608        if(m_hLogFile!=INVALID_HANDLE_VALUE)
609        {
610                hr=s->m_pGraph->SetLogFile((DWORD_PTR)m_hLogFile);
611                /* ASSERT(SUCCEEDED(hr)); */
612        }
613       
614        //AddGraphToRot(s->m_pGraph, &s->rotregvalue);
615#endif
616
617        ICreateDevEnum *pCreateDevEnum = NULL;
618        IEnumMoniker *pEnumMoniker = NULL;
619        IMoniker *pMoniker = NULL;
620
621        ULONG nFetched = 0;
622
623        hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, 
624                IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum);
625        if(FAILED(hr))
626        {
627                return -4;
628        }
629
630        hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
631                &pEnumMoniker, 0);
632        if (FAILED(hr) || pEnumMoniker == NULL) {
633                //printf("no device\n");
634                return -5;
635        }
636
637        pEnumMoniker->Reset();
638
639        int pos=0;
640  while(S_OK == pEnumMoniker->Next(1, &pMoniker, &nFetched) )
641  {
642    IPropertyBag *pBag;
643    hr = pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag );
644    if( hr != S_OK )
645       continue; 
646
647    if (s->dev[0]=='\0')
648      break;
649
650    VARIANT var;
651    VariantInit(&var);
652    hr = pBag->Read( L"FriendlyName", &var, NULL ); 
653    if( hr != S_OK )
654    {
655      pMoniker->Release();
656      continue;
657    }
658    //USES_CONVERSION;
659    char szName[256];
660
661    WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0);
662    VariantClear(&var); 
663
664    if (strcmp(szName, s->dev)==0)
665      break;
666
667    pMoniker->Release();
668    pBag->Release();
669    pMoniker=NULL;
670    pBag=NULL;
671        }
672
673        if(pMoniker==NULL)
674        {
675                return -6;
676        }
677
678        hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&s->m_pDeviceFilter );
679        if(FAILED(hr))
680        {
681                return -7;
682        }
683
684        s->m_pGraph->AddFilter(s->m_pDeviceFilter, L"Device Filter");
685
686        pMoniker->Release();
687        pEnumMoniker->Release();
688        pCreateDevEnum->Release();
689
690
691  GUID pPinCategory;
692
693        if (try_format(s, s->pix_fmt, &pPinCategory)==0)
694                s->pix_fmt = s->pix_fmt;
695        else if (try_format(s,MS_YUV420P, &pPinCategory)==0)
696                s->pix_fmt = MS_YUV420P;
697        else if (try_format(s,MS_YUY2, &pPinCategory)==0)
698                s->pix_fmt = MS_YUY2;
699        else if (try_format(s,MS_YUYV, &pPinCategory)==0)
700                s->pix_fmt = MS_YUYV;
701        else if (try_format(s,MS_UYVY, &pPinCategory)==0)
702                s->pix_fmt = MS_UYVY;
703        else if (try_format(s,MS_RGB24, &pPinCategory)==0)
704                s->pix_fmt = MS_RGB24;
705        else
706        {
707                ms_error("Unsupported video pixel format.");
708                return -8;
709        }
710       
711        if (s->pix_fmt == MS_YUV420P)
712                ms_message("Driver supports YUV420P, using that format.");
713        else if (s->pix_fmt == MS_YUY2)
714                ms_message("Driver supports YUY2 (UYVY), using that format.");
715        else if (s->pix_fmt == MS_YUYV)
716                ms_message("Driver supports YUV422, using that format.");
717        else if (s->pix_fmt == MS_UYVY)
718                ms_message("Driver supports UYVY, using that format.");
719        else if (s->pix_fmt == MS_RGB24)
720                ms_message("Driver supports RGB24, using that format.");
721
722        if (try_format_size(s, s->pix_fmt, s->vsize.width, s->vsize.height, &pPinCategory)==0)
723                ms_message("Selected Size: %ix%i.", s->vsize.width, s->vsize.height);
724        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H, &pPinCategory)==0)
725                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H);
726        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H, &pPinCategory)==0)
727                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H);
728        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H, &pPinCategory)==0)
729                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H);
730        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H, &pPinCategory)==0)
731                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H);
732        else if (try_format_size(s, s->pix_fmt, MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H, &pPinCategory)==0)
733                ms_message("Selected Size: %ix%i.", MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H);
734        else
735        {
736                ms_error("No supported size found for format.");
737                /* size not supported? */
738                return -9;
739        }
740
741        // get DXFilter
742        s->m_pDXFilter = new CDXFilter(NULL, &hr, FALSE);
743        if(s->m_pDXFilter==NULL)
744        {
745                return -10;
746        }
747        s->m_pDXFilter->AddRef();
748
749        CMediaType mt;
750        mt.SetType(&MEDIATYPE_Video);
751
752        GUID m = MEDIASUBTYPE_RGB24;
753        if (s->pix_fmt == MS_YUV420P)
754                m = (GUID)FOURCCMap(MAKEFOURCC('I','4','2','0'));
755        else if (s->pix_fmt == MS_YUY2)
756                m = MEDIASUBTYPE_YUY2;
757        else if (s->pix_fmt == MS_YUYV)
758                m = MEDIASUBTYPE_YUYV;
759        else if (s->pix_fmt == MS_UYVY)
760                m = MEDIASUBTYPE_UYVY;
761        else if (s->pix_fmt == MS_RGB24)
762                m = MEDIASUBTYPE_RGB24;
763        mt.SetSubtype(&m);
764       
765        mt.formattype = FORMAT_VideoInfo;
766        mt.SetTemporalCompression(FALSE);
767
768        VIDEOINFO *pvi = (VIDEOINFO *)
769        mt.AllocFormatBuffer(sizeof(VIDEOINFO));
770        if (NULL == pvi)
771                return -11;
772        ZeroMemory(pvi, sizeof(VIDEOINFO));
773
774        if (s->pix_fmt == MS_YUV420P)
775                pvi->bmiHeader.biCompression = MAKEFOURCC('I','4','2','0');
776        else if (s->pix_fmt == MS_YUY2)
777                pvi->bmiHeader.biCompression = MAKEFOURCC('Y','U','Y','2');
778        else if (s->pix_fmt == MS_YUYV)
779                pvi->bmiHeader.biCompression = MAKEFOURCC('Y','U','Y','V');
780        else if (s->pix_fmt == MS_UYVY)
781                pvi->bmiHeader.biCompression = MAKEFOURCC('U','Y','V','Y');
782        else if (s->pix_fmt == MS_RGB24)
783                pvi->bmiHeader.biCompression = BI_RGB;
784       
785        if (s->pix_fmt == MS_YUV420P)
786                pvi->bmiHeader.biBitCount = 12;
787        else if (s->pix_fmt == MS_YUY2)
788                pvi->bmiHeader.biBitCount = 16;
789        else if (s->pix_fmt == MS_YUYV)
790                pvi->bmiHeader.biBitCount = 16;
791        else if (s->pix_fmt == MS_UYVY)
792                pvi->bmiHeader.biBitCount = 16;
793        else if (s->pix_fmt == MS_RGB24)
794                pvi->bmiHeader.biBitCount = 24;
795
796        pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
797        pvi->bmiHeader.biWidth = s->vsize.width;
798        pvi->bmiHeader.biHeight = s->vsize.height;
799        pvi->bmiHeader.biPlanes = 1;
800        pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
801        pvi->bmiHeader.biClrImportant = 0;
802        mt.SetSampleSize(pvi->bmiHeader.biSizeImage);
803
804        mt.SetFormat((BYTE*)pvi, sizeof(VIDEOINFO));
805
806        hr = s->m_pDXFilter->SetAcceptedMediaType(&mt);
807        if(FAILED(hr))
808        {
809                return -12;
810        }
811
812        hr = s->m_pDXFilter->SetCallback(Callback); 
813        if(FAILED(hr))
814        {
815                return -13;
816        }
817
818        hr = s->m_pDXFilter->QueryInterface(IID_IBaseFilter,
819         (LPVOID *)&s->m_pIDXFilter);
820        if(FAILED(hr))
821        {
822                return -14;
823        }
824
825        hr = s->m_pGraph->AddFilter(s->m_pIDXFilter, L"DXFilter Filter");
826        if(FAILED(hr))
827        {
828                return -15;
829        }
830
831
832        // get null renderer
833        hr=CoCreateInstance (CLSID_NullRenderer,
834                          NULL,
835                          CLSCTX_INPROC_SERVER,
836                          IID_IBaseFilter,
837                          (void **)&s->m_pNullRenderer);
838        if(FAILED(hr))
839        {
840                return -16;
841        }
842        if (s->m_pNullRenderer!=NULL)
843        {
844                s->m_pGraph->AddFilter(s->m_pNullRenderer, L"Null Renderer");
845        }
846
847        hr = s->m_pBuilder->RenderStream(&pPinCategory,
848                &MEDIATYPE_Video, s->m_pDeviceFilter, s->m_pIDXFilter, s->m_pNullRenderer);
849        if (FAILED(hr))
850        {
851                return -17;
852        }
853       
854  IAMStreamConfig *pConfig = NULL;
855  hr = s->m_pBuilder->FindInterface(
856      &pPinCategory, // Preview pin.
857      &MEDIATYPE_Video,    // Any media type.
858      s->m_pDeviceFilter, // Pointer to the capture filter.
859      IID_IAMStreamConfig, (void**)&pConfig); 
860  if (pConfig!=NULL)
861  {
862    AM_MEDIA_TYPE *pType = NULL;
863    int iCount, iSize;
864    pConfig->GetNumberOfCapabilities(&iCount, &iSize);
865
866    for (int i = 0; i < iCount; i++) {
867        VIDEO_STREAM_CONFIG_CAPS scc;
868        pType = NULL;
869        pConfig->GetStreamCaps(i, &pType, (BYTE *)&scc);
870
871        if (!((pType->formattype == FORMAT_VideoInfo) &&
872              (pType->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
873              (pType->pbFormat != NULL)))
874          continue;
875
876        VIDEOINFOHEADER & videoInfo = *(VIDEOINFOHEADER *)pType->pbFormat;
877
878        if (m != pType->subtype)
879          continue;
880
881        if (videoInfo.bmiHeader.biWidth != s->vsize.width)
882          continue;
883
884        if (videoInfo.bmiHeader.biHeight != s->vsize.height)
885          continue;
886
887        if (videoInfo.bmiHeader.biBitCount != pvi->bmiHeader.biBitCount)
888          continue;
889
890        if (videoInfo.bmiHeader.biCompression != pvi->bmiHeader.biCompression)
891          continue;
892
893        videoInfo.AvgTimePerFrame = UNITS / (LONGLONG)s->fps;
894        pConfig->SetFormat(pType);   
895      }
896
897    pConfig->GetFormat(&pType);
898    if (pType!=NULL)
899    {
900      VIDEOINFO *pvi;
901      pvi = (VIDEOINFO *)pType->pbFormat;
902      ms_message("v4w: camera asked fps=%i // real fps=%i", (int)(UNITS / (LONGLONG)s->fps), pvi->AvgTimePerFrame);
903    }
904   
905    pConfig->Release();
906  }
907
908        //m_pDXFilter->SetBufferSamples(TRUE);
909
910        s_callback = s;
911        hr = s->m_pControl->Run();
912        if(FAILED(hr))
913        {
914                return -18;
915        }
916
917
918        s->rotregvalue=1;
919        return 0;
920}
921
922/****************************************************************************
923
924FUNCTION: AddGraphToRot.
925
926DESCRIPTION:
927     Adds a DirectShow filter graph to the Running Object Table,
928     allowing GraphEdit to "spy" on a remote filter graph.
929
930PARAMETERS:
931
932RETURNS:
933  . 0 for success, otherwise an error #.
934    . Standard COM/HRESULT error numbers are returned if a COM/HRESULT error
935        was encountered.
936
937****************************************************************************/
938HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
939{
940  IMoniker * pMoniker;
941  IRunningObjectTable *pROT;
942  WCHAR wsz[128];
943  HRESULT hr;
944
945  if (FAILED(GetRunningObjectTable(0, &pROT)))
946    return E_FAIL;
947
948  wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
949  wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
950
951  hr = CreateItemMoniker(L"!", wsz, &pMoniker);
952  if (SUCCEEDED(hr))
953  {
954    hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
955    pMoniker->Release();
956  }
957
958  pROT->Release();
959  return hr;
960}
961
962
963/****************************************************************************
964
965FUNCTION: RemoveGraphFromRot.
966
967DESCRIPTION:
968     Removes a filter graph from the Running Object Table.
969
970PARAMETERS:
971
972****************************************************************************/
973void RemoveGraphFromRot(DWORD pdwRegister)
974{
975  IRunningObjectTable *pROT;
976
977  if (SUCCEEDED(GetRunningObjectTable(0, &pROT)))
978  {
979    pROT->Revoke(pdwRegister);
980    pROT->Release();
981  }
982}
983
984static void v4w_init(MSFilter *f){
985        V4wState *s=(V4wState *)ms_new0(V4wState,1);
986        int idx;
987        s->devidx=0;
988        s->vsize.width=MS_VIDEO_SIZE_CIF_W;
989        s->vsize.height=MS_VIDEO_SIZE_CIF_H;
990        s->pix_fmt=MS_YUV420P;
991
992        s->rotregvalue = 0;
993        s->m_pGraph=NULL;
994        s->m_pBuilder=NULL;
995        s->m_pControl=NULL;
996        s->m_pDXFilter=NULL;
997        s->m_pIDXFilter=NULL;
998        s->m_pDeviceFilter=NULL;
999
1000        qinit(&s->rq);
1001        for (idx=0;idx<10;idx++)
1002        {
1003                s->mire[idx]=NULL;
1004        }
1005        memset(s->nowebcamimage, 0, sizeof(s->nowebcamimage));
1006        ms_mutex_init(&s->mutex,NULL);
1007        s->start_time=0;
1008        s->frame_count=-1;
1009        s->fps=15;
1010  memset(s->dev, 0, sizeof(s->dev));
1011
1012        f->data=s;
1013}
1014
1015static int _v4w_test(V4wState *s, void *arg)
1016{
1017        int i;
1018        i = v4w_configure_videodevice(s);
1019
1020  if (i!=0)
1021  {
1022        s->pix_fmt = MS_YUV420P;
1023    s->vsize.width = MS_VIDEO_SIZE_CIF_W;
1024    s->vsize.height = MS_VIDEO_SIZE_CIF_H;
1025  }
1026
1027        //RemoveGraphFromRot(s->rotregvalue);
1028        if (s->m_pGraph!=NULL)
1029        {
1030                if (s->m_pNullRenderer!=NULL)
1031                        s->m_pGraph->RemoveFilter(s->m_pNullRenderer);
1032                if (s->m_pIDXFilter!=NULL)
1033                        s->m_pGraph->RemoveFilter(s->m_pIDXFilter);
1034                if (s->m_pDeviceFilter!=NULL)
1035                        s->m_pGraph->RemoveFilter(s->m_pDeviceFilter);
1036        }
1037
1038        if (s->m_pNullRenderer)
1039                s->m_pNullRenderer->Release();
1040        if (s->m_pIDXFilter)
1041                s->m_pIDXFilter->Release();
1042        if (s->m_pDeviceFilter)
1043                s->m_pDeviceFilter->Release();
1044
1045        if (s->m_pBuilder)
1046                s->m_pBuilder->Release();
1047        if (s->m_pControl)
1048                s->m_pControl->Release();
1049        if (s->m_pGraph)
1050                s->m_pGraph->Release();
1051
1052        if (s->m_pDXFilter!=NULL)
1053                s->m_pDXFilter->Release();
1054
1055        s->m_pNullRenderer=NULL;
1056        s->m_pIDXFilter=NULL;
1057        s->m_pDeviceFilter=NULL;
1058        s->m_pBuilder=NULL;
1059        s->m_pControl=NULL;
1060        s->m_pGraph=NULL;
1061        s->m_pDXFilter=NULL;
1062
1063        CoUninitialize();
1064        s_callback = NULL;
1065        flushq(&s->rq,0);
1066  ms_message("v4w: checked device size=%ix%i format=%i (err=%i)", s->vsize.width, s->vsize.height, s->pix_fmt, i);
1067
1068        return i;
1069}
1070
1071static int _v4w_start(V4wState *s, void *arg)
1072{
1073        int i;
1074        s->frame_count=-1;
1075
1076        i = v4w_open_videodevice(s);
1077
1078        if (s->rotregvalue==0){
1079                //RemoveGraphFromRot(s->rotregvalue);
1080                if (s->m_pGraph!=NULL)
1081                {
1082                        if (s->m_pNullRenderer!=NULL)
1083                                s->m_pGraph->RemoveFilter(s->m_pNullRenderer);
1084                        if (s->m_pIDXFilter!=NULL)
1085                                s->m_pGraph->RemoveFilter(s->m_pIDXFilter);
1086                        if (s->m_pDeviceFilter!=NULL)
1087                                s->m_pGraph->RemoveFilter(s->m_pDeviceFilter);
1088                }
1089
1090                if (s->m_pNullRenderer)
1091                        s->m_pNullRenderer->Release();
1092                if (s->m_pIDXFilter)
1093                        s->m_pIDXFilter->Release();
1094                if (s->m_pDeviceFilter)
1095                        s->m_pDeviceFilter->Release();
1096
1097                if (s->m_pBuilder)
1098                        s->m_pBuilder->Release();
1099                if (s->m_pControl)
1100                        s->m_pControl->Release();
1101                if (s->m_pGraph)
1102                        s->m_pGraph->Release();
1103
1104                if (s->m_pDXFilter!=NULL)
1105                        s->m_pDXFilter->Release();
1106
1107                s->m_pNullRenderer=NULL;
1108                s->m_pIDXFilter=NULL;
1109                s->m_pDeviceFilter=NULL;
1110                s->m_pBuilder=NULL;
1111                s->m_pControl=NULL;
1112                s->m_pGraph=NULL;
1113                s->m_pDXFilter=NULL;
1114
1115                CoUninitialize();
1116                s_callback = NULL;
1117                flushq(&s->rq,0);
1118                ms_message("v4w: graph not started (err=%i)", i);
1119                s->rotregvalue=0;
1120                s->pix_fmt = MS_YUV420P;
1121        }
1122        return i;
1123}
1124
1125static int _v4w_stop(V4wState *s, void *arg){
1126        s->frame_count=-1;
1127        if (s->rotregvalue>0){
1128                HRESULT hr = s->m_pControl->Stop();
1129                if(FAILED(hr))
1130                {
1131                        ms_message("v4w: could not stop graph");
1132                }
1133
1134                if (s->m_pGraph!=NULL)
1135                {
1136                        if (s->m_pNullRenderer!=NULL)
1137                                s->m_pGraph->RemoveFilter(s->m_pNullRenderer);
1138                        if (s->m_pIDXFilter!=NULL)
1139                                s->m_pGraph->RemoveFilter(s->m_pIDXFilter);
1140                        if (s->m_pDeviceFilter!=NULL)
1141                                s->m_pGraph->RemoveFilter(s->m_pDeviceFilter);
1142                }
1143
1144                if (s->m_pNullRenderer)
1145                        s->m_pNullRenderer->Release();
1146                if (s->m_pIDXFilter)
1147                        s->m_pIDXFilter->Release();
1148                if (s->m_pDeviceFilter)
1149                        s->m_pDeviceFilter->Release();
1150
1151                if (s->m_pBuilder)
1152                        s->m_pBuilder->Release();
1153                if (s->m_pControl)
1154                        s->m_pControl->Release();
1155                if (s->m_pGraph)
1156                        s->m_pGraph->Release();
1157
1158                if (s->m_pDXFilter!=NULL)
1159                        s->m_pDXFilter->Release();
1160
1161                s->m_pNullRenderer=NULL;
1162                s->m_pIDXFilter=NULL;
1163                s->m_pDeviceFilter=NULL;
1164                s->m_pBuilder=NULL;
1165                s->m_pControl=NULL;
1166                s->m_pGraph=NULL;
1167                s->m_pDXFilter=NULL;
1168
1169                CoUninitialize();
1170                s_callback = NULL;
1171                flushq(&s->rq,0);
1172                ms_message("v4w: graph destroyed");
1173                s->rotregvalue=0;
1174        }
1175        return 0;
1176}
1177
1178static void v4w_uninit(MSFilter *f){
1179        V4wState *s=(V4wState*)f->data;
1180        int idx;
1181        flushq(&s->rq,0);
1182        ms_mutex_destroy(&s->mutex);
1183        for (idx=0;idx<10;idx++)
1184        {
1185                if (s->mire[idx]==NULL)
1186                        break;
1187                freemsg(s->mire[idx]);
1188        }
1189        if (s->rotregvalue>0){
1190                HRESULT hr = s->m_pControl->Stop();
1191                if(FAILED(hr))
1192                {
1193                        ms_message("v4w: could not stop graph");
1194                }
1195
1196                if (s->m_pGraph!=NULL)
1197                {
1198                        if (s->m_pNullRenderer!=NULL)
1199                                s->m_pGraph->RemoveFilter(s->m_pNullRenderer);
1200                        if (s->m_pIDXFilter!=NULL)
1201                                s->m_pGraph->RemoveFilter(s->m_pIDXFilter);
1202                        if (s->m_pDeviceFilter!=NULL)
1203                                s->m_pGraph->RemoveFilter(s->m_pDeviceFilter);
1204                }
1205
1206                if (s->m_pNullRenderer)
1207                        s->m_pNullRenderer->Release();
1208                if (s->m_pIDXFilter)
1209                        s->m_pIDXFilter->Release();
1210                if (s->m_pDeviceFilter)
1211                        s->m_pDeviceFilter->Release();
1212
1213                if (s->m_pBuilder)
1214                        s->m_pBuilder->Release();
1215                if (s->m_pControl)
1216                        s->m_pControl->Release();
1217                if (s->m_pGraph)
1218                        s->m_pGraph->Release();
1219
1220                if (s->m_pDXFilter!=NULL)
1221                        s->m_pDXFilter->Release();
1222
1223                s->m_pNullRenderer=NULL;
1224                s->m_pIDXFilter=NULL;
1225                s->m_pDeviceFilter=NULL;
1226                s->m_pBuilder=NULL;
1227                s->m_pControl=NULL;
1228                s->m_pGraph=NULL;
1229                s->m_pDXFilter=NULL;
1230
1231                CoUninitialize();
1232                s_callback = NULL;
1233                flushq(&s->rq,0);
1234                ms_message("v4w: graph destroyed");
1235                s->rotregvalue=0;
1236        }
1237        ms_free(s);
1238}
1239
1240static mblk_t * v4w_make_nowebcam(V4wState *s){
1241#if defined(_WIN32_WCE)
1242        return NULL;
1243#else
1244        int idx;
1245        int count;
1246        if(s->mire[0]==NULL &&  s->frame_ind==0 && s->nowebcamimage[0] != '\0')
1247          {
1248            s->mire[0] = ms_load_jpeg_as_yuv(s->nowebcamimage,&s->vsize);
1249          }
1250        if (s->mire[0]==NULL && s->frame_ind==0){
1251                /* load several images to fake a movie */
1252                for (idx=0;idx<10;idx++)
1253                {
1254                        s->mire[idx]=ms_load_nowebcam(&s->vsize, idx);
1255                        if (s->mire[idx]==NULL)
1256                                break;
1257                }
1258                if (idx==0)
1259                        s->mire[0]=ms_load_nowebcam(&s->vsize, -1);
1260        }
1261        for (count=0;count<10;count++)
1262        {
1263                if (s->mire[count]==NULL)
1264                        break;
1265        }
1266
1267        s->frame_ind++;
1268        if (count==0)
1269                return NULL;
1270
1271        idx = s->frame_ind%count;
1272        if (s->mire[idx]!=NULL)
1273                return s->mire[idx];
1274        return s->mire[0];
1275#endif
1276}
1277
1278static void v4w_preprocess(MSFilter * obj){
1279        V4wState *s=(V4wState*)obj->data;
1280        if (s->rotregvalue==0)
1281    _v4w_start(s, NULL);
1282        if (s->rotregvalue==0)
1283                s->fps=1;
1284}
1285
1286static void v4w_postprocess(MSFilter * obj){
1287        V4wState *s=(V4wState*)obj->data;
1288        s->start_time=0;
1289        s->frame_count=-1;
1290        flushq(&s->rq,0);
1291}
1292
1293static void v4w_process(MSFilter * obj){
1294        V4wState *s=(V4wState*)obj->data;
1295        mblk_t *m;
1296        uint32_t timestamp;
1297        int cur_frame;
1298
1299        if (s->frame_count==-1){
1300                s->start_time=obj->ticker->time;
1301                s->frame_count=0;
1302        }
1303
1304        cur_frame=((obj->ticker->time-s->start_time)*s->fps/1000.0);
1305        if (cur_frame>s->frame_count){
1306                mblk_t *om=NULL;
1307                ms_mutex_lock(&s->mutex);
1308                /*keep the most recent frame if several frames have been captured */
1309                if (s->rotregvalue!=0){
1310                        while((m=getq(&s->rq))!=NULL){
1311                                if (om!=NULL) freemsg(om);
1312                                om=m;
1313                        }
1314                }else {
1315                        mblk_t *nowebcam = v4w_make_nowebcam(s);
1316                        if (nowebcam!=NULL){
1317                                om=dupmsg(nowebcam);
1318                                mblk_set_precious_flag(om,1);
1319                        }
1320                }
1321                ms_mutex_unlock(&s->mutex);
1322                if (om!=NULL){
1323                        timestamp=obj->ticker->time*90;/* rtp uses a 90000 Hz clockrate for video*/
1324                        mblk_set_timestamp_info(om,timestamp);
1325                        ms_queue_put(obj->outputs[0],om);
1326                        /*ms_message("picture sent");*/
1327                }
1328                s->frame_count++;
1329        }
1330}
1331
1332
1333
1334static int v4w_set_fps(MSFilter *f, void *arg){
1335        V4wState *s=(V4wState*)f->data;
1336        s->fps=*((float*)arg);
1337        s->frame_count=-1; /* reset counter used for fps */
1338        return 0;
1339}
1340
1341
1342static int v4w_set_pix_fmt(MSFilter *f,void *arg){
1343        V4wState *s=(V4wState*)f->data;
1344  s->pix_fmt=*((MSPixFmt*)arg);
1345        return 0;
1346}
1347
1348static int v4w_get_pix_fmt(MSFilter *f,void *arg){
1349        V4wState *s=(V4wState*)f->data;
1350        if (s->rotregvalue==0){
1351                _v4w_test(s, NULL); /* check supported format */
1352                *((MSPixFmt*)arg) = (MSPixFmt)s->pix_fmt;
1353    return 0;
1354        }
1355        *((MSPixFmt*)arg) = (MSPixFmt)s->pix_fmt;
1356        return 0;
1357}
1358
1359static int v4w_set_vsize(MSFilter *f, void *arg){
1360        V4wState *s=(V4wState*)f->data;
1361        s->vsize=*((MSVideoSize*)arg);
1362        return 0;
1363}
1364
1365static int v4w_get_vsize(MSFilter *f, void *arg){
1366        V4wState *s=(V4wState*)f->data;
1367        MSVideoSize *vs=(MSVideoSize*)arg;
1368        vs->width=s->vsize.width;
1369        vs->height=s->vsize.height;
1370        return 0;
1371}
1372
1373static int v4w_set_device(MSFilter *f, void *arg){
1374        V4wState *s=(V4wState*)f->data;
1375        s->devidx=*((int*)arg);
1376        return 0;
1377}
1378
1379static int v4w_set_image(MSFilter *f, void *arg){
1380        int idx;
1381        V4wState *s=(V4wState*)f->data;
1382        char *image = (char *)arg;
1383        ms_mutex_lock(&s->mutex);
1384        if (image!=NULL && image[0]!='\0')
1385          snprintf(s->nowebcamimage, sizeof(s->nowebcamimage), "%s", image);
1386        else
1387          s->nowebcamimage[0] = '\0';
1388        for (idx=0;idx<10;idx++)
1389        {
1390                if (s->mire[idx]==NULL)
1391                        break;
1392                freemsg(s->mire[idx]);
1393                s->mire[idx]=NULL;
1394        }
1395        s->frame_ind=0;
1396        ms_mutex_unlock(&s->mutex);
1397        return 0;
1398}
1399
1400static int v4w_set_name(MSFilter *f, void *arg){
1401        V4wState *s=(V4wState*)f->data;
1402  snprintf(s->dev, sizeof(s->dev), (char*)arg);
1403        return 0;
1404}
1405
1406static MSFilterMethod methods[]={
1407        {       MS_FILTER_SET_FPS       ,       v4w_set_fps     },
1408        {       MS_FILTER_SET_PIX_FMT   ,       v4w_set_pix_fmt },
1409        {       MS_FILTER_GET_PIX_FMT   ,       v4w_get_pix_fmt },
1410        {       MS_FILTER_SET_VIDEO_SIZE, v4w_set_vsize },
1411        {       MS_FILTER_GET_VIDEO_SIZE, v4w_get_vsize },
1412        {       MS_V4L_SET_DEVICE,      v4w_set_device },
1413        { MS_FILTER_SET_IMAGE, v4w_set_image },
1414        {       0                                                               ,       NULL                    }
1415};
1416
1417#ifdef _MSC_VER
1418
1419MSFilterDesc ms_v4w_desc={
1420        MS_V4L_ID,
1421        "MSV4w",
1422        N_("A video4windows compatible source filter to stream pictures."),
1423        MS_FILTER_OTHER,
1424        NULL,
1425        0,
1426        1,
1427        v4w_init,
1428        v4w_preprocess,
1429        v4w_process,
1430        v4w_postprocess,
1431        v4w_uninit,
1432        methods
1433};
1434
1435#else
1436
1437MSFilterDesc ms_v4w_desc={
1438        .id=MS_V4L_ID,
1439        .name="MSV4w",
1440        .text=N_("A video4windows compatible source filter to stream pictures."),
1441        .ninputs=0,
1442        .noutputs=1,
1443        .category=MS_FILTER_OTHER,
1444        .init=v4w_init,
1445        .preprocess=v4w_preprocess,
1446        .process=v4w_process,
1447        .postprocess=v4w_postprocess,
1448        .uninit=v4w_uninit,
1449        .methods=methods
1450};
1451
1452#endif
1453
1454MS_FILTER_DESC_EXPORT(ms_v4w_desc)
1455
1456static MSFilter *vfw_create_reader(MSWebCam *obj){
1457        MSFilter *f=ms_filter_new_from_desc(&ms_v4w_desc);
1458        v4w_set_name(f,obj->name);
1459        return f;
1460}
1461
1462static void vfw_detect(MSWebCamManager *obj);
1463
1464static void vfw_cam_init(MSWebCam *cam){
1465}
1466
1467MSWebCamDesc ms_directx_cam_desc={
1468        "DirectX Video Grabber",
1469        &vfw_detect,
1470        &vfw_cam_init,
1471        &vfw_create_reader,
1472        NULL
1473};
1474
1475static void vfw_detect(MSWebCamManager *obj){
1476        ICreateDevEnum *pCreateDevEnum = NULL;
1477        IEnumMoniker *pEnumMoniker = NULL;
1478        IMoniker *pMoniker = NULL;
1479  HRESULT hr;
1480
1481        ULONG nFetched = 0;
1482
1483        hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, 
1484                IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum);
1485        if(FAILED(hr))
1486        {
1487                return ;
1488        }
1489
1490        hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
1491                &pEnumMoniker, 0);
1492        if (FAILED(hr) || pEnumMoniker == NULL) {
1493                //printf("no device\n");
1494                return ;
1495        }
1496
1497        pEnumMoniker->Reset();
1498
1499        int pos=0;
1500  while(S_OK == pEnumMoniker->Next(1, &pMoniker, &nFetched) )
1501  {
1502    IPropertyBag *pBag;
1503    hr = pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag );
1504    if( hr != S_OK )
1505       continue; 
1506
1507    VARIANT var;
1508    VariantInit(&var);
1509    hr = pBag->Read( L"FriendlyName", &var, NULL ); 
1510    if( hr != S_OK )
1511    {
1512      pMoniker->Release();
1513      continue;
1514    }
1515    //USES_CONVERSION;
1516    char szName[256];
1517
1518    WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0);
1519    VariantClear(&var); 
1520
1521          MSWebCam *cam=ms_web_cam_new(&ms_directx_cam_desc);
1522    cam->name=ms_strdup(szName);
1523          ms_web_cam_manager_add_cam(obj,cam);
1524
1525    pMoniker->Release();
1526    pBag->Release();
1527    pMoniker=NULL;
1528    pBag=NULL;
1529        }
1530
1531        pEnumMoniker->Release();
1532        pCreateDevEnum->Release();
1533}
Note: See TracBrowser for help on using the repository browser.