source: trunk/Utilities/RenderInterlacedVideo/MainPropertySheet.h @ 74

Last change on this file since 74 was 74, checked in by roman, 11 years ago

VMR-9 interlacing

  • Property svn:keywords set to Id
File size: 31.4 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2012
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: MainPropertySheet.h 74 2012-07-15 11:10:51Z roman $
6
7#pragma once
8
9#include "AboutDialog.h"
10#include <dshow.h>
11#include <d3d9.h>
12#include <vmr9.h>
13#include <evr.h>
14#include <evr9.h>
15#include <dxva.h>
16#include "rodshow.h"
17
18////////////////////////////////////////////////////////////
19// CVmr9Window
20
21class CVmr9Window :
22        public CControlWindowT<CVmr9Window>
23{
24public:
25
26BEGIN_MSG_MAP_EX(CVmr9Window)
27        //CHAIN_MSG_MAP(CControlWindowT<CVmr9Window>)
28        MSG_WM_ERASEBKGND(OnEraseBkgnd)
29        MSG_WM_PAINT(OnPaint)
30        MSG_WM_DISPLAYCHANGE(OnDisplayChange)
31        MSG_WM_SIZE(OnSize)
32        MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
33END_MSG_MAP()
34
35public:
36        CComPtr<IBaseFilter> m_pBaseFilter;
37        CComPtr<IVMRWindowlessControl9> m_pVmrWindowlessControl;
38
39public:
40// CVmr7Window
41        static CLSID GetRendererClassIdentifier() throw()
42        {
43                return CLSID_VideoMixingRenderer9;
44        }
45        static CComPtr<IBaseFilter> CoCreateBaseFilterInstance()
46        {
47                CComPtr<IBaseFilter> pBaseFilter;
48                __C(pBaseFilter.CoCreateInstance(GetRendererClassIdentifier()));
49                return pBaseFilter;
50        }
51        VOID Initialize(IBaseFilter* pBaseFilter)
52        {
53                _A(pBaseFilter);
54                _A(!m_pBaseFilter && !m_pVmrWindowlessControl);
55                m_pBaseFilter = pBaseFilter;
56                CComQIPtr<IVMRFilterConfig9> pVmrFilterConfig = pBaseFilter;
57                __D(pVmrFilterConfig, E_NOINTERFACE);
58                __C(pVmrFilterConfig->SetRenderingMode(VMR9Mode_Windowless));
59                m_pVmrWindowlessControl = CComQIPtr<IVMRWindowlessControl9>(m_pBaseFilter);
60                __D(m_pVmrWindowlessControl, E_NOINTERFACE);
61                __C(m_pVmrWindowlessControl->SetVideoClippingWindow(m_hWnd));
62                CRect VideoPosition = GetVideoPosition();
63                _Z4(atlTraceGeneral, 4, _T(".m_pVmrWindowlessControl 0x%p, VideoPosition at (%d, %d) size (%d, %d)\n"), m_pVmrWindowlessControl, VideoPosition.left, VideoPosition.top, VideoPosition.Width(), VideoPosition.Height());
64                __C(m_pVmrWindowlessControl->SetVideoPosition(NULL, VideoPosition));
65        }
66        VOID Terminate() throw()
67        {
68                m_pBaseFilter = NULL;
69                m_pVmrWindowlessControl = NULL;
70        }
71        CRect GetVideoPosition() const throw()
72        {
73                CRect Position;
74                _W(GetClientRect(Position));
75                return Position;
76        }
77
78// Window Message Handlers
79        LRESULT OnEraseBkgnd(CDCHandle Dc)
80        {
81                Dc;
82                if(m_pVmrWindowlessControl)
83                {
84                        return TRUE;
85                } else
86                        SetMsgHandled(FALSE);
87                return 0;
88        }
89        LRESULT OnPaint(CDCHandle)
90        {
91                if(m_pVmrWindowlessControl)
92                {
93                        CPaintDC Dc(m_hWnd);
94                        const HRESULT nRepaintVideoResult = m_pVmrWindowlessControl->RepaintVideo(m_hWnd, Dc);
95                        _Z4(atlTraceUI, SUCCEEDED(nRepaintVideoResult) ? 6 : 4, _T("nRepaintVideoResult 0x%08x\n"), nRepaintVideoResult);
96                } else
97                        SetMsgHandled(FALSE);
98                return 0;
99        }
100        LRESULT OnDisplayChange(UINT nDepth, CSize Extent)
101        {
102                if(m_pVmrWindowlessControl)
103                {
104                        const HRESULT nDisplayModeChangedResult = m_pVmrWindowlessControl->DisplayModeChanged();
105                        _Z4(atlTraceUI, 4, _T("nDisplayModeChangedResult 0x%08x\n"), nDisplayModeChangedResult);
106                }
107                return 0;
108        }
109        LRESULT OnSize(UINT nType, CSize)
110        {
111                if(nType != SIZE_MINIMIZED)
112                        if(m_pVmrWindowlessControl)
113                        {
114                                CRect VideoPosition = GetVideoPosition();
115                                const HRESULT nSetVideoPositionResult = m_pVmrWindowlessControl->SetVideoPosition(NULL, &VideoPosition);
116                                _Z4(atlTraceUI, SUCCEEDED(nSetVideoPositionResult) ? 6 : 4, _T("nSetVideoPositionResult 0x%08x\n"), nSetVideoPositionResult);
117                        }
118                return 0;
119        }
120        LRESULT OnLButtonDblClk(UINT, CPoint Position)
121        {
122                COlePropertyFrameDialog Dialog;
123                Dialog.SetObject(m_pBaseFilter);
124                Dialog.SetObjectPages();
125                Dialog.DoModal(m_hWnd);
126                return 0;
127        }
128};
129
130////////////////////////////////////////////////////////////
131// CEvrWindow
132
133class CEvrWindow :
134        public CControlWindowT<CEvrWindow>
135{
136public:
137
138BEGIN_MSG_MAP_EX(CEvrWindow)
139        //CHAIN_MSG_MAP(CControlWindowT<CEvrWindow>)
140        MSG_WM_ERASEBKGND(OnEraseBkgnd)
141        MSG_WM_PAINT(OnPaint)
142        MSG_WM_SIZE(OnSize)
143        MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
144END_MSG_MAP()
145
146public:
147        CComPtr<IBaseFilter> m_pBaseFilter;
148        CComPtr<IMFVideoDisplayControl> m_pMfVideoDisplayControl;
149
150public:
151// CEvrWindow
152        static CLSID GetRendererClassIdentifier() throw()
153        {
154                return CLSID_EnhancedVideoRenderer;
155        }
156        static CComPtr<IBaseFilter> CoCreateBaseFilterInstance()
157        {
158                CComPtr<IBaseFilter> pBaseFilter;
159                __C(pBaseFilter.CoCreateInstance(GetRendererClassIdentifier()));
160                return pBaseFilter;
161        }
162        VOID Initialize(IBaseFilter* pBaseFilter)
163        {
164                _A(pBaseFilter);
165                _A(!m_pBaseFilter && !m_pMfVideoDisplayControl);
166                m_pBaseFilter = pBaseFilter;
167                CComQIPtr<IMFGetService> pMfGetInterface = pBaseFilter;
168                CComPtr<IMFVideoDisplayControl> pMfVideoDisplayControl;
169                __C(pMfGetInterface->GetService(MR_VIDEO_RENDER_SERVICE, __uuidof(IMFVideoDisplayControl), (VOID**) &pMfVideoDisplayControl));
170                _A(pMfVideoDisplayControl);
171                m_pMfVideoDisplayControl = pMfVideoDisplayControl;
172                __C(pMfVideoDisplayControl->SetVideoWindow(m_hWnd));
173                CRect VideoPosition = GetVideoPosition();
174                _Z4(atlTraceGeneral, 4, _T("pMfVideoDisplayControl 0x%p, VideoPosition at (%d, %d) size (%d, %d)\n"), pMfVideoDisplayControl, VideoPosition.left, VideoPosition.top, VideoPosition.Width(), VideoPosition.Height());
175                __C(pMfVideoDisplayControl->SetVideoPosition(NULL, VideoPosition));
176                //__C(pMfVideoDisplayControl->SetAspectRatioMode(MFVideoARMode_None)); // As opposed to default MFVideoARMode_Picture - disable letterboxing
177        }
178        VOID Terminate() throw()
179        {
180                m_pBaseFilter = NULL;
181                m_pMfVideoDisplayControl = NULL;
182        }
183        CRect GetVideoPosition() const throw()
184        {
185                CRect Position;
186                _W(GetClientRect(Position));
187                return Position;
188        }
189
190// Window Message Handlers
191        LRESULT OnEraseBkgnd(CDCHandle Dc)
192        {
193                Dc;
194                if(m_pMfVideoDisplayControl)
195                {
196                        return TRUE;
197                } else
198                        SetMsgHandled(FALSE);
199                return 0;
200        }
201        LRESULT OnPaint(CDCHandle)
202        {
203                if(m_pMfVideoDisplayControl)
204                {
205                        CPaintDC Dc(m_hWnd);
206                        const HRESULT nRepaintVideoResult = m_pMfVideoDisplayControl->RepaintVideo();
207                        _Z4(atlTraceUI, SUCCEEDED(nRepaintVideoResult) ? 6 : 4, _T("nRepaintVideoResult 0x%08x\n"), nRepaintVideoResult);
208                } else
209                        SetMsgHandled(FALSE);
210                return 0;
211        }
212        LRESULT OnSize(UINT nType, CSize)
213        {
214                if(nType != SIZE_MINIMIZED)
215                        if(m_pMfVideoDisplayControl)
216                        {
217                                CRect VideoPosition = GetVideoPosition();
218                                const HRESULT nSetVideoPositionResult = m_pMfVideoDisplayControl->SetVideoPosition(NULL, &VideoPosition);
219                                _Z4(atlTraceUI, SUCCEEDED(nSetVideoPositionResult) ? 6 : 4, _T("nSetVideoPositionResult 0x%08x\n"), nSetVideoPositionResult);
220                        }
221                return 0;
222        }
223        LRESULT OnLButtonDblClk(UINT, CPoint Position)
224        {
225                COlePropertyFrameDialog Dialog;
226                Dialog.SetObject(m_pBaseFilter);
227                Dialog.SetObjectPages();
228                Dialog.DoModal(m_hWnd);
229                return 0;
230        }
231};
232
233////////////////////////////////////////////////////////////
234// CMainPropertySheet
235
236class CMainPropertySheet : 
237        public CSizablePropertySheetT<CMainPropertySheet>
238{
239public:
240
241BEGIN_MSG_MAP_EX(CMainPropertySheet)
242        CHAIN_MSG_MAP(CSizablePropertySheet)
243        MESSAGE_HANDLER_EX(WM_SETLARGERINITIALPOSITION, OnSetLargerInitialPosition)
244END_MSG_MAP()
245
246public:
247
248        ////////////////////////////////////////////////////////
249        // Window Message Identifiers
250
251        enum
252        {
253                MW_FIRST = WM_APP + 100,
254                WM_SETLARGERINITIALPOSITION,
255        };
256
257        ////////////////////////////////////////////////////////
258        // CSourceFilter
259
260        class ATL_NO_VTABLE CSourceFilter :
261                public CComObjectRootEx<CComMultiThreadModelNoCS>,
262                public CComCoClass<CSourceFilter>,
263                public CPushSourceFilterT<CSourceFilter>,
264                public CBasePersistT<CSourceFilter>,
265                public CAmFilterMiscFlagsT<CSourceFilter, AM_FILTER_MISC_FLAGS_IS_SOURCE>
266        {
267        public:
268
269        DECLARE_NO_REGISTRY()
270
271        DECLARE_PROTECT_FINAL_CONSTRUCT()
272
273        //DECLARE_QI_TRACE(CSourceFilter)
274
275        BEGIN_COM_MAP(CSourceFilter)
276                COM_INTERFACE_ENTRY(IBaseFilter)
277                COM_INTERFACE_ENTRY(IMediaFilter)
278                COM_INTERFACE_ENTRY_IID(__uuidof(IPersist), IBaseFilter)
279                COM_INTERFACE_ENTRY(IAMFilterMiscFlags)
280        END_COM_MAP()
281
282        public:
283
284                ////////////////////////////////////////////////////////
285                // CThreadContext
286
287                class CThreadContext :
288                        public CPushSourceFilter::CThreadContext
289                {
290                public:
291                        SIZE_T m_nMediaSampleIndex;
292
293                public:
294                // CThreadContext
295                        CThreadContext(CEvent& TerminationEvent) throw() :
296                                CPushSourceFilter::CThreadContext(TerminationEvent),
297                                m_nMediaSampleIndex(0)
298                        {
299                        }
300                };
301
302                ////////////////////////////////////////////////////////
303                // COutputPin
304
305                class ATL_NO_VTABLE COutputPin :
306                        public CComObjectRootEx<CComMultiThreadModelNoCS>,
307                        public CPushSourceFilterT<CSourceFilter>::COutputPinT<COutputPin, CSourceFilter, CThreadContext>,
308                        public CAmPushSourceT<COutputPin, 0>
309                {
310                public:
311
312                //DECLARE_QI_TRACE(CSourceFilter::COutputPin)
313
314                BEGIN_COM_MAP(COutputPin)
315                        COM_INTERFACE_ENTRY(IPin)
316                        COM_INTERFACE_ENTRY(IAMPushSource)
317                        COM_INTERFACE_ENTRY(IAMLatency)
318                END_COM_MAP()
319
320                private:
321
322                        VOID Paint(BYTE* pnData, SSIZE_T nNextRowOffset, BYTE nColor)
323                        {
324                                // 400 px high from 40, 60 px wide from current, line step 2
325                                for(LONG nY = (480 - 2 * 40) / 2; nY > 0; nY--)
326                                {
327                                        for(LONG nX = 0; nX < 60; nX++)
328                                                pnData[nX * 2] = nColor;
329                                        pnData += 2 * nNextRowOffset;
330                                }
331                        }
332
333                public:
334                // COutputPin
335                        COutputPin() throw()
336                        {
337                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
338                        }
339                        ~COutputPin() throw()
340                        {
341                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
342                        }
343                        VOID EnumerateMediaTypes(CAtlList<CMediaType>& MediaTypeList)
344                        {
345                                //CRoCriticalSectionLock DataLock(GetDataCriticalSection());
346                                _W(MediaTypeList.AddTail(GetFilter()->m_pRequestedMediaType));
347                        }
348                        BOOL CheckMediaType(const CMediaType& pMediaType) const throw()
349                        {
350                                _A(pMediaType);
351                                if(pMediaType->majortype != MEDIATYPE_Video)
352                                        return FALSE;
353                                //CRoCriticalSectionLock DataLock(GetDataCriticalSection());
354                                _A(GetFilter()->m_pRequestedMediaType);
355                                //if(GetFilter()->m_pRequestedMediaType.Compare(pMediaType))
356                                //      return TRUE;
357                                return CVideoInfoHeader::Compare(&GetFilter()->m_pRequestedMediaType.GetCompatibleVideoInfoHeader(), &pMediaType.GetCompatibleVideoInfoHeader(), FALSE);
358                        }
359                        BOOL DecideMemAllocatorProperties(IMemAllocator* pMemAllocator, ALLOCATOR_PROPERTIES Properties) throw()
360                        {
361                                static const SIZE_T g_nMiminalBufferCount = 8;
362                                Properties.cBuffers = max(Properties.cBuffers, (LONG) g_nMiminalBufferCount);
363                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
364                                const CMediaType& pMediaType = GetMediaTypeReference();
365                                const CVideoInfoHeader VideoInfoHeader = pMediaType.GetCompatibleVideoInfoHeader();
366                                const CSize Extent = VideoInfoHeader.GetExtent();
367                                SIZE_T nBufferSize;
368                                if(Extent.cx >= 1080)
369                                {
370                                        // NOTE: At higher resolutions we are good to go with much smaller buffers
371                                        static const UINT g_nPixelBitCount = 7;
372                                        nBufferSize = Extent.cy * Extent.cx * g_nPixelBitCount / 8;
373                                } else
374                                {
375                                        static const UINT g_nPixelBitCount = 14;
376                                        nBufferSize = Extent.cy * Extent.cx * g_nPixelBitCount / 8;
377                                }
378                                return SetMemAllocatorBufferSize(pMemAllocator, Properties, nBufferSize);
379                        }
380                        BOOL ComposeMediaSample(CThreadContext& ThreadContext, IMediaSample* pMediaSample)
381                        {
382                                CMediaSampleProperties OutputProperties(pMediaSample);
383                                #pragma region Dynamic Type Change
384                                if(OutputProperties.dwSampleFlags & AM_SAMPLE_TYPECHANGED)
385                                {
386                                        _A(OutputProperties.pMediaType);
387                                        _A(CheckMediaType(OutputProperties.pMediaType));
388                                        SetMediaType(OutputProperties.pMediaType);
389                                } else
390                                        _A(!OutputProperties.pMediaType);
391                                #pragma endregion
392                                const CMediaType pMediaType = GetMediaType();
393                                const CVideoInfoHeader2* pVideoInfoHeader2 = pMediaType.GetVideoInfoHeader2();
394                                OutputProperties.dwTypeSpecificFlags = (!(ThreadContext.m_nMediaSampleIndex & 1) ? AM_VIDEO_FLAG_FIELD2 : AM_VIDEO_FLAG_FIELD1);
395                                OutputProperties.dwSampleFlags = AM_SAMPLE_SPLICEPOINT | (ThreadContext.m_nMediaSampleIndex ? 0 : AM_SAMPLE_DATADISCONTINUITY) | AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID;
396                                OutputProperties.lActual = GetMediaType().GetCompatibleVideoInfoHeader().GetDataSize();
397                                OutputProperties.tStart = ThreadContext.m_nMediaSampleIndex * pVideoInfoHeader2->AvgTimePerFrame / 2;
398                                OutputProperties.tStop = OutputProperties.tStart + 1;
399                                OutputProperties.dwStreamId = 0;
400                                #pragma region Data
401                                FillMemory(OutputProperties.pbBuffer, OutputProperties.lActual, 0x80);
402                                const CSize Extent = pVideoInfoHeader2->GetExtent();
403                                SSIZE_T nFirstRowOffset, nNextRowOffset;
404                                pVideoInfoHeader2->GetData(nFirstRowOffset, nNextRowOffset);
405                                BYTE* pnData = OutputProperties.pbBuffer;
406                                static const REFERENCE_TIME g_nPeriod = 3 * 1000 * 10000i64; // 3 seconds for the move back and forth
407                                REFERENCE_TIME nField2Time = (ThreadContext.m_nMediaSampleIndex & ~1) * pVideoInfoHeader2->AvgTimePerFrame / 2;
408                                REFERENCE_TIME nField1Time = ((ThreadContext.m_nMediaSampleIndex - 1) | 1) * pVideoInfoHeader2->AvgTimePerFrame / 2;
409                                _Z5(atlTraceGeneral, 5, _T("m_nMediaSampleIndex %d, OutputProperties.tStart %s, nField2Time %s, nField1Time %s\n"), 
410                                        ThreadContext.m_nMediaSampleIndex,
411                                        _FilterGraphHelper::FormatReferenceTime(OutputProperties.tStart),
412                                        _FilterGraphHelper::FormatReferenceTime(nField2Time), 
413                                        _FilterGraphHelper::FormatReferenceTime(nField1Time), 
414                                        0);
415                                REFERENCE_TIME nPositionA = nField2Time % g_nPeriod;
416                                LONG nPositionB = (LONG) (abs((g_nPeriod / 2) - nPositionA) * (600 - 60) / (g_nPeriod / 2));
417                                Paint(pnData + nFirstRowOffset + (40 + 1) * nNextRowOffset + (60 + nPositionB) * 2, nNextRowOffset, 0xFF);
418                                REFERENCE_TIME nPositionC = nField1Time % g_nPeriod;
419                                LONG nPositionD = (LONG) (abs((g_nPeriod / 2) - nPositionC) * (600 - 60) / (g_nPeriod / 2));
420                                Paint(pnData + nFirstRowOffset + (40 + 0) * nNextRowOffset + (60 + nPositionD) * 2, nNextRowOffset, 0xFF); // Change color to 0x00 to distinguish between the fields
421                                if(GetFilter()->GetWeave())
422                                        OutputProperties.dwTypeSpecificFlags |= AM_VIDEO_FLAG_WEAVE;
423                                #pragma endregion
424                                OutputProperties.Set();
425                                ThreadContext.m_nMediaSampleIndex++;
426                                return TRUE;
427                        }
428                };
429
430        private:
431                CObjectPtr<COutputPin> m_pOutputPin;
432                CMediaType m_pRequestedMediaType;
433                BOOL m_bWeave;
434
435        public:
436        // CSourceFilter
437                CSourceFilter() throw() :
438                        CBasePersistT<CSourceFilter>(GetDataCriticalSection()),
439                        m_bWeave(FALSE)
440                {
441                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
442                }
443                ~CSourceFilter() throw()
444                {
445                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
446                }
447                HRESULT FinalConstruct() throw()
448                {
449                        _ATLTRY
450                        {
451                                m_pOutputPin.Construct()->Initialize(this, L"Output");
452                                AddPin(m_pOutputPin);
453                        }
454                        _ATLCATCH(Exception)
455                        {
456                                _C(Exception);
457                        }
458                        return S_OK;
459                }
460                VOID FinalRelease() throw()
461                {
462                        m_pOutputPin = NULL;
463                }
464                VOID DeliverBeginFlush(IPin*)
465                {
466                        m_pOutputPin->DeliverBeginFlush();
467                }
468                VOID DeliverEndFlush(IPin*)
469                {
470                        m_pOutputPin->DeliverEndFlush();
471                }
472                VOID DeliverNewSegment(IPin*, REFERENCE_TIME nStartTime, REFERENCE_TIME nStopTime, DOUBLE fRate)
473                {
474                        m_pOutputPin->DeliverNewSegment(nStartTime, nStopTime, fRate);
475                }
476                static BOOL CanCue() throw()
477                {
478                        return FALSE;
479                }
480                VOID CueFilter()
481                {
482                        m_pOutputPin->CuePin();
483                }
484                VOID RunFilter(REFERENCE_TIME nStartTime)
485                {
486                        m_pOutputPin->RunPin(nStartTime);
487                }
488                VOID PauseFilter() throw()
489                {
490                        m_pOutputPin->PausePin();
491                }
492                VOID StopFilter() throw()
493                {
494                        m_pOutputPin->StopPin();
495                }
496                const CObjectPtr<COutputPin>& GetOutputPin() const throw()
497                {
498                        return m_pOutputPin;
499                }
500                VOID Initialize()
501                {
502                        _A(!m_pRequestedMediaType);
503                        CMediaType pMediaType;
504                        //pMediaType.AllocateVideoInfo(720, 480, 16, MAKEFOURCC('Y', 'U', 'Y', '2'), 1000 * 10000i64 / 30);
505                        pMediaType.Allocate(MEDIATYPE_Video, MEDIASUBTYPE_YUY2, FORMAT_VideoInfo2, sizeof (VIDEOINFOHEADER2));
506                        CVideoInfoHeader2* pVideoInfoHeader2 = pMediaType.GetVideoInfoHeader2();
507                        CBitmapInfoHeader* pBitmapInfoHeader = &pVideoInfoHeader2->GetBitmapInfoHeader();
508                        pBitmapInfoHeader->biSize = sizeof (BITMAPINFOHEADER);
509                        pBitmapInfoHeader->biWidth = 720;
510                        pBitmapInfoHeader->biHeight = 480;
511                        pBitmapInfoHeader->biPlanes = 1;
512                        pBitmapInfoHeader->biBitCount = 16;
513                        pBitmapInfoHeader->biCompression = MEDIASUBTYPE_YUY2.Data1;
514                        pBitmapInfoHeader->biSizeImage = pBitmapInfoHeader->GetDataSize();
515                        pVideoInfoHeader2->GetSourcePosition().SetRect(0, 0, pBitmapInfoHeader->biWidth, pBitmapInfoHeader->biHeight);
516                        pVideoInfoHeader2->GetTargetPosition().SetRect(0, 0, pBitmapInfoHeader->biWidth, pBitmapInfoHeader->biHeight);
517                        pVideoInfoHeader2->AvgTimePerFrame = 1001 * 10000i64 / 30;
518//                      pVideoInfoHeader2->AvgTimePerFrame *= 10; // Uncomment to slow down 10 times
519                        pVideoInfoHeader2->dwBitRate = (DWORD) (8.0 * pBitmapInfoHeader->biSizeImage * 10000000.0 / pVideoInfoHeader2->AvgTimePerFrame + 0.5 - 1E-6);
520                        pVideoInfoHeader2->dwInterlaceFlags = AMINTERLACE_IsInterlaced | AMINTERLACE_FieldPatBothRegular | AMINTERLACE_DisplayModeBobOrWeave;
521//                      pVideoInfoHeader2->dwInterlaceFlags = 0; // Uncomment to remove interlacing
522                        pVideoInfoHeader2->dwPictAspectRatioX = 720;
523                        pVideoInfoHeader2->dwPictAspectRatioY = 480;
524                        pMediaType->bFixedSizeSamples = TRUE;
525                        pMediaType->lSampleSize = pBitmapInfoHeader->biSizeImage;
526                        m_pRequestedMediaType = pMediaType;
527                }
528                const CMediaType& GetRequestedMediaType() const throw()
529                {
530                        return m_pRequestedMediaType;
531                }
532                BOOL GetWeave() const throw()
533                {
534                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
535                        return m_bWeave;
536                }
537                VOID SetWeave(BOOL bWeave) throw()
538                {
539                        CRoCriticalSectionLock DataLock(GetDataCriticalSection());
540                        m_bWeave = bWeave;
541                }
542        };
543
544        ////////////////////////////////////////////////////////////
545        // CAmGraphBuilderCallback
546
547        class ATL_NO_VTABLE CAmGraphBuilderCallback :
548                public CComObjectRootEx<CComMultiThreadModelNoCS>,
549                public IAMGraphBuilderCallback
550        {
551        public:
552
553        BEGIN_COM_MAP(CAmGraphBuilderCallback)
554                COM_INTERFACE_ENTRY(IAMGraphBuilderCallback)
555        END_COM_MAP()
556
557        public:
558        // CAmGraphBuilderCallback
559                CAmGraphBuilderCallback() throw()
560                {
561                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
562                }
563                ~CAmGraphBuilderCallback() throw()
564                {
565                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
566                }
567                VOID SetGraphBuilder(IUnknown* pGraphBuilderUnknown)
568                {
569                        const CComQIPtr<IObjectWithSite> pObjectWithSite = pGraphBuilderUnknown;
570                        __D(pObjectWithSite, E_NOINTERFACE);
571                        __C(pObjectWithSite->SetSite(this));
572                }
573
574        // IAMGraphBuilderCallback
575                STDMETHOD(SelectedFilter)(IMoniker* pMoniker) throw()
576                {
577                        _Z5(atlTraceCOM, 5, _T("...\n"));
578                        _ATLTRY
579                        {
580                                _A(pMoniker);
581                                CComPtr<IBindCtx> pBindCtx;
582                                __C(CreateBindCtx(0, &pBindCtx));
583                                if(_FilterGraphHelper::IsFilterNonGrata(pMoniker))
584                                        return E_FAIL;
585                                const CStringW sMonikerDisplayName = _FilterGraphHelper::GetMonikerDisplayName(pMoniker, pBindCtx);
586                                CComPtr<IPropertyBag> pPropertyBag;
587                                __C(pMoniker->BindToStorage(pBindCtx, NULL, __uuidof(IPropertyBag), (VOID**) &pPropertyBag));
588                                const CStringW sFriendlyName = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("FriendlyName"));
589                                const CStringW sClassIdentifierString = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, OLESTR("CLSID"));
590                                const CStringW sPath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls\\InprocServer32"), sClassIdentifierString));
591                                _Z4(atlTraceGeneral, 4, _T("sMonikerDisplayName \"%ls\", sFriendlyName \"%ls\", sClassIdentifierString %ls, sPath \"%ls\"\n"), sMonikerDisplayName, sFriendlyName, sClassIdentifierString, sPath);
592                        }
593                        _ATLCATCH(Exception)
594                        {
595                                _C(Exception);
596                        }
597                        return S_OK;
598                }
599                STDMETHOD(CreatedFilter)(IBaseFilter* pBaseFilter) throw()
600                {
601                        _Z5(atlTraceCOM, 5, _T("...\n"));
602                        _ATLTRY
603                        {
604                                _A(pBaseFilter);
605                                _Z4(atlTraceGeneral, 4, _T("pBaseFilter %ls \"%ls\"\n"), _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter), _FilterGraphHelper::GetFilterName(pBaseFilter));
606                        }
607                        _ATLCATCH(Exception)
608                        {
609                                _C(Exception);
610                        }
611                        return S_OK;
612                }
613        };
614
615        ////////////////////////////////////////////////////
616        // CVmr9PropertyPage
617
618        class CVmr9PropertyPage :
619                public CPropertyPageT<CVmr9PropertyPage>,
620                public CDialogResize<CVmr9PropertyPage>
621        {
622        public:
623                enum { IDD = IDD_MAIN_VMR9 };
624
625        BEGIN_MSG_MAP_EX(CVmr9PropertyPage)
626                CHAIN_MSG_MAP(CPropertyPageT<CVmr9PropertyPage>)
627                CHAIN_MSG_MAP(CDialogResize<CVmr9PropertyPage>)
628                MSG_WM_INITDIALOG(OnInitDialog)
629                MSG_WM_DESTROY(OnDestroy)
630                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_RUN, OnRunButtonClicked)
631                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_PAUSE, OnPauseButtonClicked)
632                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_STOP, OnStopButtonClicked)
633                COMMAND_ID_HANDLER_EX(IDC_MAIN_VMR9_WEAVE, OnWeaveButtonClicked)
634                MESSAGE_HANDLER_EX(WM_FILTERGRAPHEVENT, OnFilterGraphEvent)
635                REFLECT_NOTIFICATIONS()
636        END_MSG_MAP()
637
638        BEGIN_DLGRESIZE_MAP(CVmr9PropertyPage)
639                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_VIDEO, DLSZ_SIZE_X | DLSZ_SIZE_Y)
640                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_RUN, DLSZ_MOVE_X)
641                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_PAUSE, DLSZ_MOVE_X)
642                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_STOP, DLSZ_MOVE_X)
643                DLGRESIZE_CONTROL(IDC_MAIN_VMR9_WEAVE, DLSZ_MOVE_Y)
644        END_DLGRESIZE_MAP()
645
646        public:
647
648                ////////////////////////////////////////////////////////
649                // Window Message Identifiers
650
651                enum
652                {
653                        WM_FIRST = WM_APP,
654                        WM_FILTERGRAPHEVENT,
655                };
656
657        private:
658                CMainPropertySheet& m_Owner;
659                CStatic m_VideoStatic;
660                CGenericFilterGraph m_FilterGraph;
661                CObjectPtr<CSourceFilter> m_pSourceFilter;
662                CVmr9Window m_RendererWindow;
663                CButton m_RunButton;
664                CButton m_PauseButton;
665                CButton m_StopButton;
666                CButton m_WeaveButton;
667
668                VOID UpdateControls()
669                {
670                        OAFilterState State;
671                        if(SUCCEEDED(m_FilterGraph.m_pMediaControl->GetState(0, &State)))
672                        {
673                                m_RunButton.EnableWindow(State != State_Running);
674                                m_PauseButton.EnableWindow(State != State_Paused);
675                                m_StopButton.EnableWindow(State != State_Stopped);
676                        } else
677                        {
678                                m_RunButton.EnableWindow(FALSE);
679                                m_PauseButton.EnableWindow(FALSE);
680                                m_StopButton.EnableWindow(FALSE);
681                        }
682                }
683
684        public:
685        // CVmr9PropertyPage
686                CVmr9PropertyPage(CMainPropertySheet* pOwner) :
687                        m_Owner(*pOwner)
688                {
689                }
690
691        // CDialogResize
692                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
693                {
694                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
695                        CRect VideoPosition;
696                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
697                        _W(ScreenToClient(VideoPosition));
698                        _W(m_RendererWindow.MoveWindow(VideoPosition));
699                }
700
701        // Window Message Handelrs
702                LRESULT OnInitDialog(HWND, LPARAM)
703                {
704                        m_VideoStatic = GetDlgItem(IDC_MAIN_VMR9_VIDEO);
705                        m_VideoStatic.ShowWindow(SW_HIDE);
706                        CRect VideoPosition;
707                        _W(m_VideoStatic.GetWindowRect(VideoPosition));
708                        _W(ScreenToClient(VideoPosition));
709                        m_RunButton = GetDlgItem(IDC_MAIN_VMR9_RUN);
710                        m_PauseButton = GetDlgItem(IDC_MAIN_VMR9_PAUSE);
711                        m_StopButton = GetDlgItem(IDC_MAIN_VMR9_STOP);
712                        m_WeaveButton = GetDlgItem(IDC_MAIN_VMR9_WEAVE);
713                        DlgResize_Init(TRUE);
714                        m_FilterGraph.CoCreateInstance();
715                        CObjectPtr<CAmGraphBuilderCallback> pAmGraphBuilderCallback;
716                        pAmGraphBuilderCallback.Construct();
717                        pAmGraphBuilderCallback->SetGraphBuilder(m_FilterGraph.m_pFilterGraph);
718                        const CComPtr<IBaseFilter> pBaseFilter = m_RendererWindow.CoCreateBaseFilterInstance();
719                        __C(m_FilterGraph->AddFilter(pBaseFilter, CT2CW(_T("VMR-9"))));
720                        m_RendererWindow.Create(m_hWnd);
721                        _W(m_RendererWindow.MoveWindow(VideoPosition));
722                        m_RendererWindow.ShowWindow(SW_SHOWNORMAL);
723                        m_RendererWindow.Initialize(pBaseFilter);
724                        CObjectPtr<CSourceFilter> pSourceFilter;
725                        pSourceFilter.Construct()->Initialize();
726                        pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
727                        m_pSourceFilter = pSourceFilter;
728                        __C(m_FilterGraph->AddFilter(pSourceFilter, CT2CW(_T("Source"))));
729                        __C(m_FilterGraph->Connect(pSourceFilter->GetOutputPin(), _FilterGraphHelper::GetFilterPin(m_RendererWindow.m_pBaseFilter)));
730                        __C(m_FilterGraph.m_pMediaEventEx->SetNotifyWindow((OAHWND) m_hWnd, WM_FILTERGRAPHEVENT, (LONG_PTR) this));
731                        UpdateControls();
732                        return 0;
733                }
734                LRESULT OnDestroy() throw()
735                {
736                        if(m_FilterGraph.m_pMediaControl)
737                                _V(m_FilterGraph.m_pMediaControl->Stop());
738                        m_RendererWindow.Terminate();
739                        m_pSourceFilter.Release();
740                        m_FilterGraph.Release();
741                        return 0;
742                }
743                LRESULT OnRunButtonClicked(UINT, INT, HWND)
744                {
745                        CWaitCursor WaitCursor;
746                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
747                        __C(m_FilterGraph.m_pMediaControl->Run());
748                        UpdateControls();
749                        #pragma region Capabilities
750                        _ATLTRY
751                        {
752                                const CComQIPtr<IVMRDeinterlaceControl9> pVmrDeinterlaceControl9 = m_RendererWindow.m_pBaseFilter;
753                                VMR9VideoDesc VideoDescription;
754                                ZeroMemory(&VideoDescription, sizeof VideoDescription);
755                                VideoDescription.dwSize = sizeof VideoDescription;
756                                const CVideoInfoHeader2* pVideoInfoHeader2 = m_pSourceFilter->GetRequestedMediaType().GetVideoInfoHeader2();
757                                _A(pVideoInfoHeader2);
758                                const CSize Extent = pVideoInfoHeader2->GetExtent();
759                                VideoDescription.dwSampleWidth = Extent.cx;
760                                VideoDescription.dwSampleHeight = Extent.cy;
761                                VideoDescription.SampleFormat = VMR9_SampleFieldInterleavedEvenFirst;
762                                VideoDescription.dwFourCC = pVideoInfoHeader2->GetBitmapInfoHeader().biCompression;
763                                VideoDescription.InputSampleFreq.dwNumerator = 30000;
764                                VideoDescription.InputSampleFreq.dwDenominator = 1001;
765                                VideoDescription.OutputFrameFreq.dwNumerator = 60000;
766                                VideoDescription.OutputFrameFreq.dwDenominator = 1001;
767                                DWORD nModeCount = 16;
768                                CTempBufferT<GUID> pModes(nModeCount);
769                                const HRESULT nGetNumberOfDeinterlaceModesResult = pVmrDeinterlaceControl9->GetNumberOfDeinterlaceModes(&VideoDescription, &nModeCount, pModes);
770                                _Z4(atlTraceGeneral, 4, _T("nGetNumberOfDeinterlaceModesResult 0x%08x, nModeCount %d\n"), nGetNumberOfDeinterlaceModesResult, nModeCount);
771                                if(SUCCEEDED(nGetNumberOfDeinterlaceModesResult))
772                                {
773                                        for(DWORD nModeIndex = 0; nModeIndex < nModeCount; nModeIndex++)
774                                        {
775                                                const GUID& Mode = pModes[nModeIndex];
776                                                _Z4(atlTraceGeneral, 4, _T("nModeIndex %d, Mode %s\n"), nModeIndex, FormatDeinterlaceMode(Mode));
777                                                VMR9DeinterlaceCaps Capabilities;
778                                                ZeroMemory(&Capabilities, sizeof Capabilities);
779                                                Capabilities.dwSize = sizeof Capabilities;
780                                                const HRESULT nGetDeinterlaceModeCapsResult = pVmrDeinterlaceControl9->GetDeinterlaceModeCaps(const_cast<GUID*>(&Mode), &VideoDescription, &Capabilities);
781                                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlaceModeCapsResult 0x%08x, Capabilities.dwNumPreviousOutputFrames %d, .dwNumForwardRefSamples %d, .dwNumBackwardRefSamples %d, .DeinterlaceTechnology 0x%x\n"), nGetDeinterlaceModeCapsResult, Capabilities.dwNumPreviousOutputFrames, Capabilities.dwNumForwardRefSamples, Capabilities.dwNumBackwardRefSamples, Capabilities.DeinterlaceTechnology);
782                                        }
783                                }
784                                GUID DeinterlaceMode = GUID_NULL;
785                                const HRESULT nGetDeinterlaceModeResult = pVmrDeinterlaceControl9->GetDeinterlaceMode(0, &DeinterlaceMode);
786                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlaceModeResult 0x%08x\n"), nGetDeinterlaceModeResult);
787                                if(SUCCEEDED(nGetDeinterlaceModeResult) && !(nGetDeinterlaceModeResult == S_FALSE && DeinterlaceMode == GUID_NULL))
788                                        _Z4(atlTraceGeneral, 4, _T("DeinterlaceMode %s\n"), FormatDeinterlaceMode(DeinterlaceMode));
789                                DWORD nPreferences = 0;
790                                const HRESULT nGetDeinterlacePrefsResult = pVmrDeinterlaceControl9->GetDeinterlacePrefs(&nPreferences);
791                                _Z4(atlTraceGeneral, 4, _T("nGetDeinterlacePrefsResult 0x%08x, nPreferences 0x%x\n"), nGetDeinterlacePrefsResult, nPreferences);
792                                GUID ActualDeinterlaceMode;
793                                const HRESULT nGetActualDeinterlaceModeResult = pVmrDeinterlaceControl9->GetActualDeinterlaceMode(0, &ActualDeinterlaceMode);
794                                _Z4(atlTraceGeneral, 4, _T("nGetActualDeinterlaceModeResult 0x%08x\n"), nGetActualDeinterlaceModeResult);
795                                if(SUCCEEDED(nGetActualDeinterlaceModeResult))
796                                        _Z4(atlTraceGeneral, 4, _T("ActualDeinterlaceMode %s\n"), FormatDeinterlaceMode(ActualDeinterlaceMode));
797                        }
798                        _ATLCATCHALL()
799                        {
800                                _Z_EXCEPTION();
801                        }
802                        #pragma endregion
803                        return 0;
804                }
805                LRESULT OnPauseButtonClicked(UINT, INT, HWND)
806                {
807                        CWaitCursor WaitCursor;
808                        __D(m_FilterGraph.m_pMediaControl, E_NOINTERFACE);
809                        __C(m_FilterGraph.m_pMediaControl->Pause());
810                        UpdateControls();
811                        return 0;
812                }
813                LRESULT OnStopButtonClicked(UINT, INT, HWND)
814                {
815                        CWaitCursor WaitCursor;
816                        if(m_FilterGraph.m_pMediaControl)
817                                _V(m_FilterGraph.m_pMediaControl->Stop());
818                        UpdateControls();
819                        return 0;
820                }
821                LRESULT OnWeaveButtonClicked(UINT, INT, HWND)
822                {
823                        if(m_pSourceFilter)
824                                m_pSourceFilter->SetWeave(m_WeaveButton.GetCheck());
825                        return 0;
826                }
827                LRESULT OnFilterGraphEvent(UINT, WPARAM, LPARAM)
828                {
829                        if(!m_FilterGraph.m_pMediaEventEx)
830                                return 0;
831                        _ATLTRY
832                        {
833                                for(; ; )
834                                {
835                                        LONG nEventCode;
836                                        LONG_PTR nParameter1, nParameter2;
837                                        const HRESULT nGetEventResult = m_FilterGraph.m_pMediaEventEx->GetEvent(&nEventCode, &nParameter1, &nParameter2, 0);
838                                        if(nGetEventResult == E_ABORT)
839                                                break;
840                                        __C(nGetEventResult);
841                                        _ATLTRY
842                                        {
843                                                switch(nEventCode)
844                                                {
845                                                case EC_ERRORABORT:
846                                                        _Z2(atlTraceGeneral, 2, _T("nEventCode EC_ERRORABORT 0x%02X, nParameter1 0x%08x, nParameter2 0x%08x\n"), nEventCode, nParameter1, nParameter2);
847                                                        _A(FAILED(nParameter1));
848                                                        AtlMessageBoxEx(m_hWnd, (LPCTSTR) AtlFormatString(_T("EC_ERRORABORT Event: %s."), AtlFormatSystemMessage((HRESULT) nParameter1).TrimRight(_T("\t\n\r ."))), IDS_ERROR, MB_ICONERROR | MB_OK);
849                                                        break;
850                                                default:
851                                                        _Z1(atlTraceGeneral, 1, _T("nEventCode 0x%02X, nParameter1 0x%08x, nParameter2 0x%08x\n"), nEventCode, nParameter1, nParameter2);
852                                                }
853                                        }
854                                        _ATLCATCHALL()
855                                        {
856                                                _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
857                                                _ATLRETHROW;
858                                        }
859                                        _V(m_FilterGraph.m_pMediaEventEx->FreeEventParams(nEventCode, nParameter1, nParameter2));
860                                }
861                        }
862                        _ATLCATCHALL()
863                        {
864                                _Z_EXCEPTION();
865                        }
866                        return 0;
867                }
868        };
869
870public:
871        CVmr9PropertyPage m_Vmr9PropertyPage;
872
873public:
874// CMainPropertySheet
875        CMainPropertySheet() :
876                CSizablePropertySheetT<CMainPropertySheet>(_T("Render Interlaced Video")),
877                m_Vmr9PropertyPage(this)
878        {
879                AddPage(m_Vmr9PropertyPage);
880        }
881        BOOL SetInitialPosition()
882        {
883                if(!__super::SetInitialPosition())
884                        return FALSE;
885                _W(PostMessage(WM_SETLARGERINITIALPOSITION));
886                return TRUE;
887        }
888        static CString FormatDeinterlaceMode(const GUID& DeinterlaceMode)
889        {
890                // NOTE: Windows SDK does not provide a linkable identifier...
891                struct __declspec(uuid("{335aa36e-7884-43a4-9c91-7f87faf3e37e}")) DXVA_DeinterlaceBobDevice;
892                struct __declspec(uuid("{0e85cb93-3046-4ff0-aecc-d58cb5f035fd}")) DXVA_DeinterlaceContainerDevice;
893                if(DeinterlaceMode == __uuidof(DXVA_DeinterlaceBobDevice))
894                        return _T("DXVA_DeinterlaceBobDevice");
895                if(DeinterlaceMode == __uuidof(DXVA_DeinterlaceContainerDevice))
896                        return _T("DXVA_DeinterlaceContainerDevice");
897                return CString(_PersistHelper::StringFromIdentifier(DeinterlaceMode));
898        }
899
900// Window Message Handelrs
901        LRESULT OnSetLargerInitialPosition(UINT, WPARAM, LPARAM)
902        {
903                CRect Position;
904                _W(GetWindowRect(Position));
905                Position.right += Position.Width();
906                Position.bottom += Position.Height() / 4;
907                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE));
908                _W(CenterWindow());
909                return 0;
910        }
911};
Note: See TracBrowser for help on using the repository browser.