Project

General

Profile

Support Request #7982 » DSInput.cpp

adtf-device-toolbox 2.7.0 - hidden, 2019-08-01 11:10

 
1
/**
2
 *
3
 * Direct show input.
4
 *
5
 * @file
6
 * Copyright © Audi Electronics Venture GmbH. All rights reserved
7
 *
8
 * $Author: WNEROLF $
9
 * $Date: 2012-06-11 18:13:02 +0200 (Mo, 11 Jun 2012) $
10
 * $Revision: 32109 $
11
 *
12
 * @remarks
13
 *
14
 */
15
#include "./dsvideo.h"
16
//#include <atlconv.h>
17

    
18
#define RELEASE_IF_NOT_NULL(pIObj) if ((pIObj)!=NULL) { (pIObj)->Release(); (pIObj)=NULL; }
19

    
20
//*****************************************************************************
21
#define SET_STREAM_CONFIGURATION 1
22

    
23
tInt cDSInput::m_nCOMIntances = 0;
24

    
25
//*****************************************************************************
26
cString cDSInput::GetDSError(HRESULT hResult)
27
{
28
    tChar szMsg[1024];
29
    AMGetErrorText(hResult, szMsg, sizeof(szMsg));
30

    
31
    return cString(szMsg);
32
}
33

    
34
//*****************************************************************************
35
cDSInput::cDSInput()
36
{
37
   // ::CoInitialize(NULL);
38

    
39
    m_hWnd                       = NULL;
40
    m_pGraph                     = NULL;
41
    m_pMediaControl              = NULL;
42
    m_pEvent                     = NULL;
43
    m_pRenderer                  = NULL;
44
    m_psStreamEventSink          = NULL;
45
    m_pCaptureGraphBuilder       = NULL;
46
    m_sBitmapFormat.nPaletteSize = 0;
47
    m_pPalette                   = NULL;
48
    m_pGreyscalePalette          = NULL;
49
    m_nAvgTimePerFrame           = 0;
50
    m_bFormatChanged             = tTrue;
51
    m_bFlipVertical              = tFalse;
52
    m_bConfigureBitsPerPixel     = tTrue; // if false, always use default depth
53
}
54

    
55
//*****************************************************************************
56
cDSInput::~cDSInput()
57
{
58
    Stop();
59

    
60
    Release();
61

    
62
    //::CoUninitialize();
63
}
64

    
65
//*****************************************************************************
66
bool cDSInput::Release()
67
{
68
    CleanUp();
69

    
70
    if (m_nCOMIntances > 0)
71
    {
72
        m_nCOMIntances--;
73
        if (m_nCOMIntances == 0)
74
        {
75
            ::CoUninitialize();
76
            m_nCOMIntances = 0;
77
        }
78
    }
79

    
80
    return true;
81
}
82

    
83
//*****************************************************************************
84
bool cDSInput::Open(const char* strDeviceName,
85
                    HWND hWnd,
86
                    IDSStreamEventSink* psEventSink,
87
                    tDeviceConfig* pDeviceConfig,
88
                    int nGraphEventMsg,
89
                    HRESULT* phr)
90
{
91

    
92
    if (m_nCOMIntances <= 0)
93
    {
94
        ::CoInitialize(NULL);
95
        m_nCOMIntances++;
96
    }
97

    
98
    HRESULT hr = S_OK;
99

    
100
    m_nRequestedSubFormat = pDeviceConfig->nSubFormat;
101
    m_nSubFormatIdx = 0;
102
    memcpy(&m_sRequestedFormat, &pDeviceConfig->sBitmapFormat, sizeof(m_sRequestedFormat));
103

    
104
    if (m_bConfigureBitsPerPixel)
105
    {
106
        switch (pDeviceConfig->sBitmapFormat.nBitsPerPixel)
107
        {
108
            case 8:
109
                m_RequestedSubtype = MEDIASUBTYPE_RGB8;
110
                break;
111
            case 16:
112
                m_RequestedSubtype = MEDIASUBTYPE_RGB555;
113
                break;
114
            case 24:
115
                m_RequestedSubtype = MEDIASUBTYPE_RGB24;
116
                break;
117
            case 32:
118
                m_RequestedSubtype = MEDIASUBTYPE_RGB32;
119
                break;
120
            default:
121
                // bits per pixel not specified - use any available
122
                memset(&m_RequestedSubtype, 0, sizeof(m_RequestedSubtype));
123
                break;
124
        }
125
    }
126

    
127
    m_bFormatChanged = tTrue;
128

    
129
    if (nGraphEventMsg == 0)
130
    {
131
        nGraphEventMsg = WM_USER + 0x123;
132
    }
133

    
134
    m_psStreamEventSink = psEventSink;
135

    
136
    m_hWnd = hWnd;
137

    
138
    if (m_hWnd == NULL)
139
    {
140
        if (!m_oBlindWnd.Create(this, nGraphEventMsg))
141
        {
142
            return false;
143
        }
144

    
145
        m_hWnd = m_oBlindWnd.GetHandle();
146
    }
147

    
148
    IBaseFilter* pSourceFilter = NULL;
149

    
150
    ::IPin* pPinSource_Output = NULL;
151
    ::IPin* pPinRenderer_Input = NULL;
152

    
153
    bool l_bFailure = false;
154

    
155
    // filter graph / graph builder
156
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IFilterGraph2, (void **)&m_pGraph);
157
    if (FAILED(hr))
158
    {
159
        LOG_ERROR(GetDSError(hr));
160
        l_bFailure = true;
161
    }
162

    
163
    if (!l_bFailure)
164
    {
165
        hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
166
                              NULL, CLSCTX_INPROC,
167
                              IID_ICaptureGraphBuilder2,
168
                              (void **) &m_pCaptureGraphBuilder);
169
    }
170

    
171
    if (FAILED(hr))
172
    {
173
        LOG_ERROR(GetDSError(hr));
174
        l_bFailure = true;
175
    }
176

    
177
    if (!l_bFailure)
178
    {
179
        hr = m_pCaptureGraphBuilder->SetFiltergraph(m_pGraph);
180
        if (FAILED(hr))
181
        {
182
            LOG_ERROR(GetDSError(hr));
183
            l_bFailure = true;
184
        }
185
    }
186

    
187
    m_bMonikerSetToGraph = tFalse;
188
    if (!l_bFailure)
189
    {
190
        hr = FindCaptureDevice(strDeviceName, &pSourceFilter);
191
        if (hr != S_OK)
192
        {
193
            // Don't display a message because FindCaptureDevice will handle it
194
            l_bFailure = true;
195
        }
196
    }
197

    
198
    if (!l_bFailure && !m_bMonikerSetToGraph)
199
    {
200
        hr = m_pGraph->AddFilter(pSourceFilter, L"VideoCapture");
201
        if (FAILED(hr))
202
        {
203
            /*
204
            DisplayText(TEXT("Couldn't add the capture filter to the graph!  hr=0x%x\r\n\r\n") 
205
                TEXT("If you have a working video capture device, please make sure\r\n")
206
                TEXT("that it is connected and is not being used by another application.\r\n\r\n")
207
                TEXT("The sample will now close."), hr);
208
            */
209
            LOG_ERROR(GetDSError(hr));
210
            l_bFailure = true;
211
        }
212
    }
213
    else if (m_bMonikerSetToGraph)
214
    {
215
        //to to set name to filter
216
    }
217

    
218
    if (!l_bFailure)
219
    {
220
        #if (SET_STREAM_CONFIGURATION)
221
            hr = S_OK;
222
            tResult nErr = ConfigureCaptureDevice(pSourceFilter, pDeviceConfig, &hr);
223
            if (IS_FAILED(nErr))
224
            {
225
                LOG_ERROR(GetDSError(hr));
226
                l_bFailure = true;
227
            }
228
        #endif
229
    }
230

    
231
    // renderer
232
    if (!l_bFailure)
233
    {
234
        m_pRenderer = new cDSRenderer(this);
235
        if (m_pRenderer == NULL)
236
        {
237
            l_bFailure = true;
238
        }
239
    }
240

    
241
    if (!l_bFailure)
242
    {
243
        hr = m_pGraph->AddFilter(m_pRenderer, L"ADTFDefaultRenderer");
244
        if (FAILED(hr))
245
        {
246
            LOG_ERROR(GetDSError(hr));
247
            l_bFailure = true;
248
        }
249
        else
250
        {
251
            pPinRenderer_Input = GetPin(m_pRenderer, PINDIR_INPUT);
252
            if (pPinRenderer_Input == NULL)
253
            {
254
                l_bFailure = true;
255
            }
256
        }
257
    }
258

    
259
    if (!l_bFailure)
260
    {
261
        // Render the capture or preview  pin on the video capture filter
262
        hr = m_pCaptureGraphBuilder->RenderStream (&PIN_CATEGORY_CAPTURE,
263
                                                   &MEDIATYPE_Video,
264
                                                   pSourceFilter,
265
                                                   NULL,
266
                                                   m_pRenderer);
267
        if (FAILED(hr))
268
        {
269
            hr = m_pCaptureGraphBuilder->RenderStream (&PIN_CATEGORY_PREVIEW,
270
                                                       &MEDIATYPE_Video,
271
                                                       pSourceFilter,
272
                                                       NULL,
273
                                                       m_pRenderer);
274
            if (FAILED(hr))
275
            {
276
                // device may already be in use by another application
277
                LOG_ERROR(GetDSError(hr));
278
                l_bFailure = true;
279
            }
280
        }
281
    }
282

    
283
    if (!l_bFailure)
284
    {
285
        // get controller interfaces
286
        m_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&m_pEvent);
287
        if (m_pEvent != NULL)
288
        {
289
            m_pEvent->SetNotifyWindow((OAHWND)m_hWnd, nGraphEventMsg, 0);
290
        }
291

    
292
        /*
293
        AM_MEDIA_TYPE mediaType;
294
        hr = pPinRenderer_Input->ConnectionMediaType(&mediaType);
295
        if (IS_FAILED(UpdateFormat(&mediaType)))
296
        {
297
            memset(&m_sBitmapFormat, 0, sizeof(m_sBitmapFormat));
298
        }
299
        FreeMediaType(mediaType);
300
        */
301
    }
302

    
303
    RELEASE_IF_NOT_NULL(pPinSource_Output);
304
    RELEASE_IF_NOT_NULL(pPinRenderer_Input);
305
    RELEASE_IF_NOT_NULL(pSourceFilter);
306

    
307
    // get media control interface
308
    if (!l_bFailure)
309
    {
310
        hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pMediaControl);
311
        if (FAILED(hr))
312
        {
313
            LOG_ERROR(GetDSError(hr));
314
            l_bFailure = true;
315
        }
316
    }
317

    
318
    if (phr != NULL)
319
    {
320
        *phr = hr;
321
    }
322

    
323
    if (l_bFailure)
324
    {
325
        Release();
326
        
327
        return false;
328
    }
329

    
330
    return true;
331
}
332

    
333
::IPin* cDSInput::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
334
{
335
    BOOL bFound = FALSE;
336
    IEnumPins *pEnum;
337
    ::IPin *pPin;
338

    
339
    HRESULT hr = pFilter->EnumPins(&pEnum);
340
    if (FAILED(hr))
341
    {
342
        return NULL;
343
    }
344

    
345
    while(pEnum->Next(1, &pPin, 0) == S_OK)
346
    {
347
        PIN_DIRECTION PinDirThis;
348
        pPin->QueryDirection(&PinDirThis);
349
        if (bFound = (PinDir == PinDirThis))
350
            break;
351
        pPin->Release();
352
    }
353

    
354
    pEnum->Release();
355
    return (bFound ? pPin : NULL);
356
}
357

    
358
//*****************************************************************************
359
HRESULT cDSInput::FindCaptureDevice(const char* strDeviceName, IBaseFilter ** ppSrcFilter)
360
{
361
    IBaseFilter* pSrc = NULL;
362
    IMoniker* pMoniker = NULL;
363
    IEnumMoniker* pClassEnum = NULL;
364
    ICreateDevEnum* pDevEnum = NULL;
365
    bool l_bFailure = false;
366
    char strDeviceDisplayName[512];
367

    
368
    if (ppSrcFilter == NULL || strDeviceName == NULL)
369
    {
370
        return E_POINTER;
371
    }
372

    
373
    *ppSrcFilter = NULL;
374

    
375
    cString strDeviceSpec(strDeviceName);
376
    strDeviceSpec.Trim();
377
    strDeviceSpec.ToLower();
378
    tUInt32 nNameSeparator = (tUInt32)strDeviceSpec.Find(':');
379
    if (nNameSeparator != UINT32_MAX)
380
    {
381
        strDeviceSpec.Delete(0, nNameSeparator + 1);
382
    }
383

    
384
    tInt nDeviceNum = -1;
385
    if (strDeviceSpec.Compare("default") == 0)
386
    {
387
        nDeviceNum = 1;
388
        strDeviceSpec = "";
389
    }
390
    else
391
    {
392
        nDeviceNum = atoi(strDeviceSpec.GetPtr());
393
        if (nDeviceNum == 0 && strDeviceSpec.Compare("0") != 0)
394
        {
395
            nDeviceNum = -1;
396
        }
397
        else
398
        {
399
            strDeviceSpec = "";
400
        }
401
    }
402

    
403
    // Create the system device enumerator
404
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
405
                          NULL,
406
                          CLSCTX_INPROC,
407
                          IID_ICreateDevEnum,
408
                          (void **) &pDevEnum);
409
    if (FAILED(hr))
410
    {
411
        LOG_ERROR(GetDSError(hr));
412
        l_bFailure = true;
413
    }
414

    
415
    if (!l_bFailure)
416
    {
417
        // Create an enumerator for the video capture devices
418
        hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory,
419
                                              &pClassEnum,
420
                                              0);
421
        if (FAILED(hr))
422
        {
423
            LOG_ERROR(GetDSError(hr));
424
            l_bFailure = true;
425
        }
426
    }
427

    
428
    if (!l_bFailure)
429
    {
430
        // If there are no enumerators for the requested type, then 
431
        // CreateClassEnumerator will succeed, but pClassEnum will be NULL.
432
        if (pClassEnum == NULL)
433
        {
434
            LOG_ERROR("No video capture device was detected.");
435
            l_bFailure = true;
436
            hr = ERROR_NOT_READY;
437
        }
438
    }
439

    
440
    bool bDeviceFound = false;
441

    
442
    if (!l_bFailure)
443
    {
444
        // Process the device list.
445
        // Note that if the Next() call succeeds but there are no monikers,
446
        // it will return S_FALSE (which is not a failure).  Therefore, we
447
        // check that the return code is S_OK instead of using SUCCEEDED() macro.
448
       
449
        ULONG cFetched;
450
        pClassEnum->Reset();
451

    
452
        tInt nDeviceIdx = 1;
453
        LPOLESTR wstrMonikerName = NULL;
454
        
455
        while (!bDeviceFound  &&  (S_OK == pClassEnum->Next (1, &pMoniker, &cFetched)))
456
        {
457
            // get a human-readable string for evaluation during debugging
458
            strcpy_s(strDeviceDisplayName, 512, "Failed to read friendly name!");
459

    
460
            IPropertyBag *pBag = NULL;
461
            hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
462
            if (SUCCEEDED(hr))
463
            {
464
                VARIANT var;
465
                VariantInit(&var);
466
                hr = pBag->Read(L"FriendlyName", &var, NULL);
467
                if (SUCCEEDED(hr))
468
                {
469
                    WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1,
470
                                        strDeviceDisplayName, sizeof(strDeviceDisplayName),
471
                                        NULL, NULL);
472
                }
473

    
474
                VariantClear(&var);
475
                pBag->Release();
476
            }
477

    
478
            LOG_INFO(cString::Format("Found device #%d: \"%s\"", nDeviceIdx, strDeviceDisplayName));
479
 
480
            if (!strDeviceSpec.IsEmpty())
481
            {
482
                cString strFoundDeviceNameLowerCase(strDeviceDisplayName);
483
                strFoundDeviceNameLowerCase.ToLower();
484
                if (strFoundDeviceNameLowerCase.Find(strDeviceSpec) != -1)
485
                {
486
                    // found device specified by name
487
                    bDeviceFound = tTrue;
488
                }
489
            }
490
            else if (nDeviceNum == nDeviceIdx)
491
            {
492
                // found device specified by number
493
                bDeviceFound = tTrue;
494
            }
495

    
496
            if (bDeviceFound)
497
            {
498
                hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**) &pSrc);
499
                if (FAILED(hr))
500
                {
501
                    //try to add with moniker to graph
502
                    hr = m_pGraph->AddSourceFilterForMoniker(pMoniker, 0, L"VideoCapture", &pSrc);
503
                    if (FAILED(hr))
504
                    {
505
                        LOG_ERROR("Device not ready");
506
                        l_bFailure = tTrue;
507
                    }
508
                }
509
                if (!l_bFailure)
510
                {
511
                    LOG_INFO(cString::Format("Using device #%d: \"%s\"", 
512
                                             nDeviceIdx, strDeviceDisplayName));
513
                }
514
            }
515

    
516
            nDeviceIdx++;
517
            RELEASE_IF_NOT_NULL(pMoniker);
518
        }
519
    }
520

    
521
    if (!l_bFailure && !bDeviceFound)
522
    {
523
        LOG_ERROR("Device not found \"" + cString(strDeviceName) + "\"");
524
        l_bFailure = true;
525
        hr = ERROR_BAD_UNIT;
526
    }
527

    
528
    RELEASE_IF_NOT_NULL(pMoniker);
529
    RELEASE_IF_NOT_NULL(pClassEnum);
530
    RELEASE_IF_NOT_NULL(pDevEnum);
531

    
532
    // Copy the found filter pointer to the output parameter.
533
    // Do NOT Release() the reference, since it will still be used
534
    // by the calling function.
535
    if (!l_bFailure)
536
    {
537
        *ppSrcFilter = pSrc;
538
    }
539

    
540
    return hr;
541
}
542

    
543
//*****************************************************************************
544
bool cDSInput::Play()
545
{
546
    m_bFormatChanged = tTrue;
547
    
548
    // Run the graph
549
    IVideoWindow *pVidWin = NULL;
550

    
551
    if (m_pMediaControl != NULL)
552
    {
553
        OAFilterState eFilterState ;
554
        HRESULT hr = m_pMediaControl->GetState(INFINITE, &eFilterState );
555
        if (FAILED(hr))
556
        {
557
            return false;
558
        }
559

    
560
        if (eFilterState == State_Running)
561
        {
562
            hr = m_pMediaControl->Stop();
563
        }
564

    
565
        if (m_pEvent != NULL)
566
        {
567
            long levCode = 0;
568
            m_pEvent->WaitForCompletion(INFINITE, &levCode);
569
        }
570

    
571
        m_pMediaControl->Run();
572

    
573
        return true;
574
    }
575

    
576
    return false;
577
}
578

    
579
//*****************************************************************************
580
bool cDSInput::Pause()
581
{
582
    if (m_pMediaControl != NULL)
583
    {
584
        m_pMediaControl->Pause();
585

    
586
        return true;
587
    }
588

    
589
    return false;
590
}
591

    
592
//*****************************************************************************
593
bool cDSInput::Stop()
594
{
595
    if (m_pMediaControl != NULL)
596
    {
597
        LONGLONG pos = 0;
598
        HRESULT hr = m_pMediaControl->Stop();
599
 
600
        if (m_pEvent != NULL)
601
        {
602
            long levCode = 0;
603
            m_pEvent->WaitForCompletion(INFINITE, &levCode);
604
        }
605

    
606
        return true;
607
    }
608

    
609
    return false;
610
}
611

    
612
//*****************************************************************************
613
void cDSInput::CleanUp()
614
{
615
    long levCode = 0;
616

    
617
    Stop();
618

    
619
    if (m_pEvent != NULL)
620
    {
621
        m_pEvent->WaitForCompletion(INFINITE, &levCode);
622
    }
623

    
624
    if (m_pMediaControl != NULL)
625
    {
626
        m_pMediaControl->Release();
627
        m_pMediaControl = NULL;
628
    }
629

    
630
    if (m_pEvent != NULL)
631
    {
632
        m_pEvent->Release();
633
        m_pEvent = NULL;
634
    }
635

    
636
    if (m_pRenderer != NULL)
637
    {
638
        // delete m_pRenderer; --> don't delete: Graph->Release() will do that!
639
        m_pRenderer = NULL;
640
    }
641

    
642
    if (m_pCaptureGraphBuilder != NULL)
643
    {
644
        m_pCaptureGraphBuilder->Release();
645
        m_pCaptureGraphBuilder = NULL;
646
    }
647
    if (m_pGraph != NULL)
648
    {
649
        m_pGraph->Release();
650
        m_pGraph = NULL;
651
    }
652

    
653
    m_oBlindWnd.Release();
654

    
655
    FreePalette();
656
}
657

    
658
//*****************************************************************************
659
bool cDSInput::UpdateStatus()
660
{
661
    if (m_pEvent == NULL)
662
    {
663
        return FALSE;
664
    }
665

    
666
    long lEventCode = 0;
667
    LONG_PTR lParam1 = 0;
668
    LONG_PTR lParam2 = 0;
669

    
670
    HRESULT hr = m_pEvent->GetEvent(&lEventCode, &lParam1, &lParam2, INFINITE);
671
    if (FAILED(hr))
672
    {
673
        return false;
674
    }
675

    
676
    if (lEventCode == EC_COMPLETE)
677
    {
678
        Stop();
679
    }
680
    else if (lEventCode == EC_USERABORT)
681
    {
682
        Stop();
683
    }
684

    
685
    if (m_psStreamEventSink != NULL)
686
    {
687
        m_psStreamEventSink->OnStreamEvent(lEventCode, (tInt)lParam1, (tInt)lParam2);
688
    }
689

    
690
    m_pEvent->FreeEventParams(lEventCode, lParam1, lParam2);
691

    
692
    return true;
693
}
694

    
695
//*****************************************************************************
696
HRESULT cDSInput::GetEvent(long *lEventCode, long *lParam1, long *lParam2, long msTimeout)
697
{
698
    if (m_pEvent == NULL)
699
    {
700
        return E_NOTIMPL;
701
    }
702

    
703
    LONG_PTR* lpParam1 = (LONG_PTR*)&lParam1;
704
    LONG_PTR* lpParam2 = (LONG_PTR*)&lParam2;
705

    
706
    HRESULT hr = m_pEvent->GetEvent(lEventCode, lpParam1, lpParam2, msTimeout);
707
    if (SUCCEEDED(hr))
708
    {
709
        m_pEvent->FreeEventParams(*lEventCode, *lParam1, *lParam2);
710
    }
711

    
712
    return hr;
713
}
714

    
715
//*****************************************************************************
716
void cDSInput::OnGraphEvent()
717
{
718
    UpdateStatus();
719
}
720

    
721
//*****************************************************************************
722
HWND cDSInput::GetHWnd()
723
{
724
    return m_hWnd;
725
}
726

    
727
//*****************************************************************************
728
bool cDSInput::DoModal()
729
{
730
    return m_oBlindWnd.DoModal();
731
}
732

    
733
//*****************************************************************************
734
bool cDSInput::ProcessMessages(int nWait)
735
{
736
    return m_oBlindWnd.ProcessMessages(nWait);
737
}
738

    
739
//*****************************************************************************
740
HRESULT cDSInput::OnQueryMediaType(const CMediaType* pMediaType)
741
{
742
    if (pMediaType == NULL)
743
    {
744
        return E_POINTER;
745
    }
746

    
747
    if (pMediaType->majortype != MEDIATYPE_Video)
748
    {
749
        return S_FALSE;
750
    }
751

    
752
    if (m_bConfigureBitsPerPixel &&
753
        m_sRequestedFormat.nBitsPerPixel != 0)
754
    {
755
        // check if specified subtype is available
756
        if (m_RequestedSubtype != pMediaType->subtype)
757
        {
758
            return S_FALSE;
759
        }
760
    }
761
    else if (pMediaType->subtype != MEDIASUBTYPE_RGB8   &&
762
             pMediaType->subtype != MEDIASUBTYPE_RGB555 &&
763
             pMediaType->subtype != MEDIASUBTYPE_RGB565 &&
764
             pMediaType->subtype != MEDIASUBTYPE_RGB24  &&
765
             pMediaType->subtype != MEDIASUBTYPE_RGB32)
766
    {
767
        // none of the supported formats is available
768
        return S_FALSE;
769
    }
770

    
771
    const BITMAPINFOHEADER* pBitmapInfoHeader = NULL;
772
    const VIDEOINFOHEADER*  pInfo             = NULL;
773
    const VIDEOINFOHEADER2* pInfo2            = NULL;
774

    
775
    if (pMediaType->formattype == FORMAT_VideoInfo2)
776
    {
777
        pInfo2 = (VIDEOINFOHEADER2*) pMediaType->pbFormat;
778
        pBitmapInfoHeader = &pInfo2->bmiHeader;
779
    }
780
    else if (pMediaType->formattype == FORMAT_VideoInfo)
781
    {
782
        pInfo = (VIDEOINFOHEADER*) pMediaType->pbFormat;
783
        pBitmapInfoHeader = &pInfo->bmiHeader;
784
    }
785
    else
786
    {
787
        return S_FALSE;
788
    }
789

    
790
    if (m_bConfigureBitsPerPixel)
791
    {
792
        // check specified attributes
793
        if (m_sRequestedFormat.nBitsPerPixel != 0 &&
794
            m_sRequestedFormat.nBitsPerPixel != pBitmapInfoHeader->biBitCount )
795
        {
796
            return S_FALSE;
797
        }
798

    
799
        if (m_sRequestedFormat.nBitsPerPixel == 8 &&
800
            m_sRequestedFormat.nPixelFormat == cImage::PF_GREYSCALE_8 &&
801
            pBitmapInfoHeader->biClrUsed != 0)
802
        {
803
            // don't accept palette for greyscale images
804
            return S_FALSE;
805
        }
806
    }
807

    
808
    // check sub-format idx if specified
809
    m_nSubFormatIdx++;
810
    if (m_nRequestedSubFormat != 0 &&
811
        m_nSubFormatIdx != m_nRequestedSubFormat)
812
    {
813
        return S_FALSE;
814
    }
815

    
816
    return S_OK;
817
}
818

    
819
//*****************************************************************************
820
HRESULT cDSInput::OnSetMediaType(const CMediaType* pMediaType)
821
{
822
    if (pMediaType == NULL)
823
    {
824
        return E_POINTER;
825
    }
826

    
827
    if (IS_FAILED(UpdateFormat(pMediaType)))
828
    {
829
        return S_FALSE;
830
    }
831

    
832
    return S_OK;
833
}
834

    
835
tResult cDSInput::ConfigureCaptureDevice(IBaseFilter* pObject, 
836
                                         tDeviceConfig* pDeviceConfig,
837
                                         HRESULT* phr)
838
{
839
    LOG_INFO("ConfigureCaptureDevice start");
840

    
841
    RETURN_IF_POINTER_NULL(pDeviceConfig);
842

    
843
    IAMStreamConfig* pStreamConfig = NULL;
844
    HRESULT hr = m_pCaptureGraphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
845
                                                       NULL,
846
                                                       pObject,
847
                                                       IID_IAMStreamConfig,
848
                                                       (tVoid**) &pStreamConfig);
849
    if (IS_FAILED(hr))
850
    {
851
        if (phr != NULL)
852
        {
853
            *phr = hr;
854
        }
855
        LOG_ERROR(GetDSError(hr));
856
        LOG_ERROR("FindInterface failed");
857
        RETURN_ERROR(ERR_NOT_SUPPORTED);
858
    }
859

    
860
    VIDEO_STREAM_CONFIG_CAPS sConfigCaps;
861
    memset(&sConfigCaps, 0, sizeof(sConfigCaps));
862

    
863
    int iCount = 0;
864
    int iSize = 0;
865
    hr = pStreamConfig->GetNumberOfCapabilities(&iCount, &iSize);
866
    if (sizeof(sConfigCaps) != iSize)
867
    {
868
        pStreamConfig->Release();
869
        if (phr != NULL)
870
        {
871
            *phr = hr;
872
        }
873
        LOG_ERROR(GetDSError(hr));
874
        LOG_ERROR("The video stream capture config that will be returned has not the right size! "
875
                  "Can not ask for VIDEO_STREAM_CONFIG_CAPS in DirectShow (capabilities)");
876
        RETURN_ERROR(ERR_FAILED);
877
    }
878

    
879
    AM_MEDIA_TYPE*    pMediaType        = NULL;
880
    VIDEOINFOHEADER*  pInfo             = NULL;
881
    VIDEOINFOHEADER2* pInfo2            = NULL;
882
    BITMAPINFOHEADER* pBitmapInfoHeader = NULL;
883

    
884
    LOG_INFO(cString::Format("Iterate capabilities. Count == %d", iCount));
885
    for (tInt nIdx = 0;  nIdx < iCount;  nIdx++)
886
    {
887
        hr = pStreamConfig->GetStreamCaps(nIdx, &pMediaType, reinterpret_cast<BYTE*>(&sConfigCaps));
888
        if (IS_FAILED(hr))
889
        {
890
            LOG_ERROR(GetDSError(hr));
891
            LOG_ERROR("Could not find valid stream type");
892
            pStreamConfig->Release();
893
            if (phr != NULL)
894
            {
895
                *phr = hr;
896
            }
897
            RETURN_ERROR(ERR_NOT_SUPPORTED);
898
        }
899

    
900
        if ((pMediaType->formattype == FORMAT_VideoInfo2 ||
901
             pMediaType->formattype == FORMAT_VideoInfo) &&
902
            (pMediaType->subtype == MEDIASUBTYPE_RGB8    ||
903
             pMediaType->subtype == MEDIASUBTYPE_RGB555  ||
904
             pMediaType->subtype == MEDIASUBTYPE_RGB565  ||
905
             pMediaType->subtype == MEDIASUBTYPE_RGB24   ||
906
             pMediaType->subtype == MEDIASUBTYPE_RGB32   ||
907
             pMediaType->subtype == MEDIASUBTYPE_MJPG    ))
908
        {
909
            LOG_INFO("MediaType found!");
910
            break;
911
        }
912
    }
913

    
914
    if (pMediaType->formattype == FORMAT_VideoInfo2)
915
    {
916
        pInfo2 = (VIDEOINFOHEADER2*) pMediaType->pbFormat;
917
        pInfo2->AvgTimePerFrame = (10000000) / (tInt64) pDeviceConfig->nFrameRate;
918
        pBitmapInfoHeader = &pInfo2->bmiHeader;
919
        LOG_INFO("FORMAT_VideoInfo2");
920
    }
921
    else if (pMediaType->formattype == FORMAT_VideoInfo)
922
    {
923
        pInfo = (VIDEOINFOHEADER*) pMediaType->pbFormat;
924
        pInfo->AvgTimePerFrame = (10000000) / (tInt64) pDeviceConfig->nFrameRate;
925
        pBitmapInfoHeader = &pInfo->bmiHeader;
926
        LOG_INFO("FORMAT_VideoInfo");
927
    }
928
    else if (pMediaType->formattype == FORMAT_MPEG2Video)
929
    {
930
        LOG_ERROR("unhandled formattype: FORMAT_MPEG2Video");
931
        RETURN_ERROR(ERR_NOT_SUPPORTED);
932
    }
933
    else if (pMediaType->formattype == FORMAT_None)
934
    {
935
        LOG_ERROR("unhandled formattype: FORMAT_None");
936
        RETURN_ERROR(ERR_NOT_SUPPORTED);
937
    }
938
    else if (pMediaType->formattype == FORMAT_DolbyAC3)
939
    {
940
        LOG_ERROR("unhandled formattype: FORMAT_DolbyAC3");
941
        RETURN_ERROR(ERR_NOT_SUPPORTED);
942
    }
943
    else if (pMediaType->formattype == FORMAT_MPEG2Audio)
944
    {
945
        LOG_ERROR("unhandled formattype: FORMAT_MPEG2Audio");
946
        RETURN_ERROR(ERR_NOT_SUPPORTED);
947
    }
948
    else if (pMediaType->formattype == FORMAT_DVD_LPCMAudio)
949
    {
950
        LOG_ERROR("unhandled formattype: FORMAT_DVD_LPCMAudio");
951
        RETURN_ERROR(ERR_NOT_SUPPORTED);
952
    }
953
    else
954
    {
955

    
956
        RETURN_ERROR(ERR_UNKNOWN_FORMAT);
957
    }
958

    
959
    LOG_INFO(cString::Format("BitmapFormat.Width = %d", pDeviceConfig->sBitmapFormat.nWidth));
960
    if (pDeviceConfig->sBitmapFormat.nWidth != 0)
961
    {
962
        pBitmapInfoHeader->biWidth = pDeviceConfig->sBitmapFormat.nWidth;
963
    }
964

    
965
    LOG_INFO(cString::Format("BitmapFormat.Height = %d", pDeviceConfig->sBitmapFormat.nHeight));
966
    if (pDeviceConfig->sBitmapFormat.nHeight != 0)
967
    {
968
        pBitmapInfoHeader->biHeight = pDeviceConfig->sBitmapFormat.nHeight;
969
    }
970

    
971
    LOG_INFO(cString::Format("BitmapFormat.BitsPerPixel = %d", pDeviceConfig->sBitmapFormat.nBitsPerPixel));
972
    if (m_bConfigureBitsPerPixel &&
973
        pDeviceConfig->sBitmapFormat.nBitsPerPixel != 0)
974
    {
975
        //pMediaType->subtype = m_RequestedSubtype;
976
        pBitmapInfoHeader->biBitCount = (WORD) pDeviceConfig->sBitmapFormat.nBitsPerPixel;
977
        if (pBitmapInfoHeader->biBitCount <= 8)
978
        {
979
            pBitmapInfoHeader->biClrUsed      = 0;
980
            pBitmapInfoHeader->biClrImportant = 0;
981
        }
982
    }
983

    
984
    // set the sample size and image size. round the image width up to a DWORD boundary.
985
    pBitmapInfoHeader->biSizeImage = (((pBitmapInfoHeader->biWidth + 3) & ~3) *
986
                                        abs(pBitmapInfoHeader->biHeight) *
987
                                        pBitmapInfoHeader->biBitCount) / 8;
988

    
989
    pStreamConfig->SetFormat(pMediaType);
990

    
991
    DeleteMediaType(pMediaType);
992
    pStreamConfig->Release();
993

    
994
    LOG_INFO("ConfigureCaptureDevice end");
995
    RETURN_NOERROR;
996
}
997

    
998
//*****************************************************************************
999
tResult cDSInput::UpdateFormat(const AM_MEDIA_TYPE* pMediaType)
1000
{
1001
    RETURN_IF_POINTER_NULL(pMediaType);
1002

    
1003
    if (pMediaType->majortype != MEDIATYPE_Video)
1004
    {
1005
        RETURN_ERROR(ERR_INVALID_ARG);
1006
    }
1007

    
1008
    if (pMediaType->subtype != MEDIASUBTYPE_RGB8  &&
1009
        pMediaType->subtype != MEDIASUBTYPE_RGB555 &&
1010
        pMediaType->subtype != MEDIASUBTYPE_RGB565 &&
1011
        pMediaType->subtype != MEDIASUBTYPE_RGB24 &&
1012
        pMediaType->subtype != MEDIASUBTYPE_RGB32)
1013
    {
1014
        RETURN_ERROR(ERR_NOT_SUPPORTED);
1015
    }
1016

    
1017
    BITMAPINFOHEADER* pBitmapInfoHeader = NULL;
1018
    RGBQUAD* pPalette                   = NULL;
1019
    long nPaletteSize                   = 0;
1020
    tInt16 nPixelFormat                 = cImage::PF_BGR_888;
1021

    
1022
    if (pMediaType->subtype == MEDIASUBTYPE_RGB8)
1023
    {
1024
        nPixelFormat = cImage::PF_RGB_8;
1025
    }
1026
    else if (pMediaType->subtype == MEDIASUBTYPE_RGB555)
1027
    {
1028
        nPixelFormat = cImage::PF_BGR_555;
1029
    }
1030
    else if (pMediaType->subtype == MEDIASUBTYPE_RGB565)
1031
    {
1032
        nPixelFormat = cImage::PF_BGR_565;
1033
    }
1034
    else if (pMediaType->subtype == MEDIASUBTYPE_RGB24)
1035
    {
1036
        nPixelFormat = cImage::PF_RGB_888;
1037
    }
1038
    else if (pMediaType->subtype == MEDIASUBTYPE_RGB32)
1039
    {
1040
        nPixelFormat = cImage::PF_RGBA_8888;
1041
    }
1042

    
1043
    if (pMediaType->formattype == FORMAT_VideoInfo2 &&
1044
        pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER2)) 
1045
    {
1046
        VIDEOINFOHEADER2* pInfo = (VIDEOINFOHEADER2*) pMediaType->pbFormat;
1047
        
1048
        m_nAvgTimePerFrame = pInfo->AvgTimePerFrame;
1049

    
1050
        pBitmapInfoHeader = &pInfo->bmiHeader;
1051

    
1052
        if (pBitmapInfoHeader->biBitCount <= 8 && pMediaType->cbFormat > sizeof(VIDEOINFOHEADER2))
1053
        {
1054
            pPalette     = (RGBQUAD*) (((BYTE*) pMediaType->pbFormat) + sizeof(VIDEOINFOHEADER2));
1055
            nPaletteSize = (pMediaType->cbFormat - sizeof(VIDEOINFOHEADER2)) / sizeof(RGBQUAD);
1056
        }
1057

    
1058
        if (pBitmapInfoHeader->biSizeImage == 0)
1059
        {
1060
            pBitmapInfoHeader->biSizeImage = pMediaType->lSampleSize;
1061
        }
1062

    
1063
        RETURN_IF_FAILED(UpdateFormat(pBitmapInfoHeader, pPalette, nPaletteSize, nPixelFormat));
1064
    }
1065
    else if (pMediaType->formattype == FORMAT_VideoInfo &&
1066
             pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER)) 
1067
    {
1068
        VIDEOINFOHEADER* pInfo = (VIDEOINFOHEADER*) pMediaType->pbFormat;
1069

    
1070
        m_nAvgTimePerFrame = pInfo->AvgTimePerFrame;
1071

    
1072
        pBitmapInfoHeader = &pInfo->bmiHeader;
1073

    
1074
        if (pBitmapInfoHeader->biBitCount <= 8 &&
1075
            pMediaType->cbFormat > sizeof(VIDEOINFOHEADER))
1076
        {
1077
            pPalette     = (RGBQUAD*) (((BYTE*) pMediaType->pbFormat) + sizeof(VIDEOINFOHEADER));
1078
            nPaletteSize = (pMediaType->cbFormat - sizeof(VIDEOINFOHEADER)) / sizeof(RGBQUAD);
1079
        }
1080

    
1081
        if (pBitmapInfoHeader->biSizeImage == 0)
1082
        {
1083
            pBitmapInfoHeader->biSizeImage = pMediaType->lSampleSize;
1084
        }
1085

    
1086
        RETURN_IF_FAILED(UpdateFormat(pBitmapInfoHeader, pPalette, nPaletteSize, nPixelFormat));
1087
    }
1088
    else
1089
    {
1090
        m_nAvgTimePerFrame = 25;
1091
        RETURN_IF_FAILED(UpdateFormat(pBitmapInfoHeader, pPalette, nPaletteSize, nPixelFormat));
1092
    }
1093

    
1094
    RETURN_NOERROR;
1095
}
1096

    
1097
//*****************************************************************************
1098
tResult cDSInput::UpdateFormat(BITMAPINFOHEADER* pBitmapInfoHeader,
1099
                               RGBQUAD* pPalette,
1100
                               long nPaletteSize, 
1101
                               tInt16 nPixelFormat)
1102
{
1103
    memset(&m_sBitmapFormat, 0, sizeof(m_sBitmapFormat));
1104

    
1105
    m_sBitmapFormat.nWidth  = pBitmapInfoHeader->biWidth;
1106
    m_sBitmapFormat.nHeight = pBitmapInfoHeader->biHeight;
1107
    if (m_sBitmapFormat.nHeight < 0)
1108
    {
1109
        m_sBitmapFormat.nHeight = -m_sBitmapFormat.nHeight;
1110
        m_bFlipVertical = tFalse;
1111
    }
1112
    else
1113
    {
1114
        m_bFlipVertical = tTrue;
1115
    }
1116

    
1117
    m_sBitmapFormat.nBitsPerPixel = pBitmapInfoHeader->biBitCount;
1118
    m_sBitmapFormat.nBytesPerLine = (pBitmapInfoHeader->biWidth * m_sBitmapFormat.nBitsPerPixel) / 8;
1119

    
1120
    m_sBitmapFormat.nSize         = pBitmapInfoHeader->biSizeImage;
1121
    if (m_sBitmapFormat.nSize < 0 && m_bFlipVertical)
1122
    {
1123
        m_sBitmapFormat.nSize = - m_sBitmapFormat.nSize;
1124
    }
1125

    
1126
    m_sBitmapFormat.nPixelFormat = nPixelFormat;
1127
    if (m_sBitmapFormat.nBitsPerPixel <= 8 && nPaletteSize == 0)
1128
    {
1129
        m_sBitmapFormat.nPixelFormat = cImage::PF_GREYSCALE_8;
1130
    }
1131

    
1132
    RETURN_IF_FAILED(AllocPalette(nPaletteSize, tFalse));
1133

    
1134
    if (m_pPalette != NULL)
1135
    {
1136
        memcpy(m_pPalette, pPalette, nPaletteSize * sizeof(RGBQUAD));
1137
        for (tInt nIdx=0; nIdx<nPaletteSize; nIdx++)
1138
        {
1139
            m_pGreyscalePalette[nIdx] = cImage::Brightness(m_pPalette[nIdx].nRed, m_pPalette[nIdx].nGreen, m_pPalette[nIdx].nBlue);
1140
        }
1141
    }
1142

    
1143
    RETURN_NOERROR;
1144
}
1145

    
1146

    
1147
//*****************************************************************************
1148
tResult cDSInput::AllocPalette(tInt nPaletteSize, tBool bForce)
1149
{
1150
    if (nPaletteSize == m_sBitmapFormat.nPaletteSize &&
1151
        m_pPalette != NULL &&
1152
        !bForce)
1153
    {
1154
        RETURN_NOERROR;
1155
    }
1156

    
1157
    FreePalette();
1158

    
1159
    if (nPaletteSize > 0)
1160
    {
1161
        m_pPalette = new tColor[nPaletteSize];
1162
        if (m_pPalette == NULL)
1163
        {
1164
            RETURN_ERROR(ERR_MEMORY);
1165
        }
1166

    
1167
        m_pGreyscalePalette = new tUInt8[nPaletteSize];
1168
        if (m_pGreyscalePalette == NULL)
1169
        {
1170
            RETURN_ERROR(ERR_MEMORY);
1171
        }
1172

    
1173
        m_sBitmapFormat.nPaletteSize = nPaletteSize;
1174
    }
1175

    
1176
    RETURN_NOERROR;
1177
}
1178

    
1179
//*****************************************************************************
1180
tResult cDSInput::FreePalette()
1181
{
1182
    if (m_pPalette != NULL)
1183
    {
1184
        delete [] m_pPalette;
1185
        m_pPalette = NULL;
1186
    }
1187

    
1188
    if (m_pGreyscalePalette != NULL)
1189
    {
1190
        delete [] m_pGreyscalePalette;
1191
        m_pGreyscalePalette = NULL;
1192
    }
1193

    
1194
    m_sBitmapFormat.nPaletteSize = 0;
1195

    
1196
    RETURN_NOERROR;
1197
}
1198

    
1199
//*****************************************************************************
1200
tBitmapFormat* cDSInput::GetBitmapFormat()
1201
{
1202
    return &m_sBitmapFormat;
1203
}
1204

    
1205
//*****************************************************************************
1206
tInt64 cDSInput::GetAvgTimePerFrame()
1207
{
1208
    return m_nAvgTimePerFrame / 10;
1209
}
1210

    
1211
//*****************************************************************************
1212
HRESULT cDSInput::OnNewFrame(::IMediaSample* pMediaSample)
1213
{
1214
    tTimeStamp tmCurrent = cHighResTimer::GetTime();
1215

    
1216
    HRESULT hr = S_OK;
1217

    
1218
    AM_MEDIA_TYPE* pMediaType;
1219
    hr = pMediaSample->GetMediaType(&pMediaType);
1220
    if (hr == S_OK && pMediaType != NULL)
1221
    {
1222
        if (IS_OK(UpdateFormat(pMediaType)))
1223
        {
1224
            m_bFormatChanged = tTrue;
1225
        }
1226

    
1227
        DeleteMediaType(pMediaType);
1228
    }
1229

    
1230
    long nSampleSize = pMediaSample->GetSize();
1231

    
1232
    BYTE* pData = NULL;
1233
    hr = pMediaSample->GetPointer(&pData);
1234

    
1235
    if (m_psStreamEventSink != NULL)
1236
    {
1237
        REFERENCE_TIME  nStartTime, nEndTime;
1238
        hr = pMediaSample->GetTime(&nStartTime, &nEndTime);
1239

    
1240
        tTimeStamp nTime;
1241

    
1242
        if (FAILED(hr))
1243
        {
1244
            if (VFW_S_NO_STOP_TIME == hr)
1245
            {
1246
                nTime = (nStartTime + m_nAvgTimePerFrame / 2) / 10;
1247
            }
1248
            else if (VFW_E_SAMPLE_TIME_NOT_SET == hr)
1249
            {
1250
                nTime = tmCurrent - m_nAvgTimePerFrame / 20;
1251
            }
1252
            else 
1253
            {
1254
                return hr;
1255
            }
1256
        }
1257
        else
1258
        {
1259
            nTime = ((tInt64) nStartTime + (tInt64) nEndTime) / 20;
1260
        }
1261

    
1262
        if (m_bFormatChanged)
1263
        {
1264
            m_psStreamEventSink->OnNewFrame(nTime,
1265
                                            pData,
1266
                                            nSampleSize,
1267
                                            &m_sBitmapFormat,
1268
                                            m_pPalette,
1269
                                            m_bFlipVertical);
1270
            m_bFormatChanged = tFalse;
1271
        }
1272
        else
1273
        {
1274
            m_psStreamEventSink->OnNewFrame(nTime,
1275
                                            pData,
1276
                                            nSampleSize,
1277
                                            NULL,
1278
                                            NULL,
1279
                                            m_bFlipVertical);
1280
        }
1281
    }
1282

    
1283
    return S_OK;
1284
}
(2-2/2)