source: trunk/Utilities/ConfigureVideoResizerDmo/ConfigureVideoResizerDmo.cpp

Last change on this file was 84, checked in by roman, 7 years ago
  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2012
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id$
6
7#include "stdafx.h"
8#include <dshow.h>
9#include <dmo.h>
10#include <dmodshow.h>
11#include <wmcodecdsp.h>
12#include <atlstr.h>
13#include <atlcoll.h>
14
15#pragma comment(lib, "strmiids.lib")
16#pragma comment(lib, "dmoguids.lib")
17#pragma comment(lib, "msdmo.lib")
18#pragma comment(lib, "wmcodecdspuuid.lib")
19
20#pragma region Re-Adding Removed from Windows SDK qedit.h
21
22struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
23ISampleGrabberCB : IUnknown
24{
25    //
26    // Raw methods provided by interface
27    //
28
29      virtual HRESULT __stdcall SampleCB (
30        double SampleTime,
31        struct IMediaSample * pSample ) = 0;
32      virtual HRESULT __stdcall BufferCB (
33        double SampleTime,
34        unsigned char * pBuffer,
35        long BufferLen ) = 0;
36};
37
38struct __declspec(uuid("6b652fff-11fe-4fce-92ad-0266b5d7c78f"))
39ISampleGrabber : IUnknown
40{
41    //
42    // Raw methods provided by interface
43    //
44
45      virtual HRESULT __stdcall SetOneShot (
46        long OneShot ) = 0;
47      virtual HRESULT __stdcall SetMediaType (
48        struct _AMMediaType * pType ) = 0;
49      virtual HRESULT __stdcall GetConnectedMediaType (
50        struct _AMMediaType * pType ) = 0;
51      virtual HRESULT __stdcall SetBufferSamples (
52        long BufferThem ) = 0;
53      virtual HRESULT __stdcall GetCurrentBuffer (
54        /*[in,out]*/ long * pBufferSize,
55        /*[out]*/ long * pBuffer ) = 0;
56      virtual HRESULT __stdcall GetCurrentSample (
57        /*[out,retval]*/ struct IMediaSample * * ppSample ) = 0;
58      virtual HRESULT __stdcall SetCallback (
59        struct ISampleGrabberCB * pCallback,
60        long WhichMethodToCallback ) = 0;
61};
62
63struct __declspec(uuid("c1f400a0-3f08-11d3-9f0b-006008039e37"))
64SampleGrabber;
65    // [ default ] interface ISampleGrabber
66
67#pragma endregion
68
69typedef CAtlArray<CComPtr<IPin>> CPinArray;
70
71SIZE_T GetPins(IBaseFilter* pBaseFilter, CPinArray& PinArray)
72{
73        ATLASSERT(pBaseFilter);
74        ATLASSERT(PinArray.IsEmpty());
75        CComPtr<IEnumPins> pEnumPins;
76        ATLENSURE_SUCCEEDED(pBaseFilter->EnumPins(&pEnumPins));
77        CComPtr<IPin> pPin;
78        while(pEnumPins->Next(1, &pPin, NULL) == S_OK)
79        {
80                ATLVERIFY(PinArray.Add(pPin) >= 0);
81                pPin.Release();
82        }
83        return PinArray.GetCount();
84}
85
86int _tmain(int argc, _TCHAR* argv[])
87{
88        _ATLTRY
89        {
90                ATLENSURE_THROW(argc > 1, E_INVALIDARG);
91                CString sPath = argv[1];
92                ATLENSURE_SUCCEEDED(CoInitialize(NULL));
93                {
94                        #pragma region Prepare Graph
95                        CComPtr<IGraphBuilder> pGraphBuilder;
96                        ATLENSURE_SUCCEEDED(pGraphBuilder.CoCreateInstance(CLSID_FilterGraph));
97                        CComPtr<IBaseFilter> pSourceBaseFilter;
98                        ATLENSURE_SUCCEEDED(pGraphBuilder->AddSourceFilter(CT2CW(sPath), NULL, &pSourceBaseFilter));
99                        CPinArray SourcePinArray;
100                        ATLVERIFY(GetPins(pSourceBaseFilter, SourcePinArray) >= 1);
101                        CComPtr<IBaseFilter> pRendererBaseFilter;
102                        ATLENSURE_SUCCEEDED(pRendererBaseFilter.CoCreateInstance(CLSID_VideoMixingRenderer));
103                        ATLENSURE_SUCCEEDED(pGraphBuilder->AddFilter(pRendererBaseFilter, CT2CW(_T("Renderer"))));
104                        CPinArray RendererPinArray;
105                        ATLVERIFY(GetPins(pRendererBaseFilter, RendererPinArray) >= 1);
106                        HRESULT nRenderExResult = E_FAIL;
107                        for(SIZE_T nIndex = 0; nIndex < SourcePinArray.GetCount(); nIndex++)
108                        {
109                                nRenderExResult = pGraphBuilder->Connect(SourcePinArray[nIndex], RendererPinArray[0]);
110                                if(SUCCEEDED(nRenderExResult))
111                                        break;
112                        }
113                        ATLENSURE_SUCCEEDED(nRenderExResult);
114                        #pragma endregion
115                        #pragma region Insert Resizer
116                        #pragma region Insertion Point, Automatic Media Type, Pins
117                        const CComPtr<IPin> pRendererInputPin = RendererPinArray[0];
118                        CComPtr<IPin> pRendererInputPeerPin;
119                        ATLENSURE_SUCCEEDED(pRendererInputPin->ConnectedTo(&pRendererInputPeerPin));
120                        AM_MEDIA_TYPE OriginalMediaType;
121                        ZeroMemory(&OriginalMediaType, sizeof OriginalMediaType);
122                        ATLENSURE_SUCCEEDED(pRendererInputPin->ConnectionMediaType(&OriginalMediaType));
123                        CComHeapPtr<BYTE> pnOriginalMediaTypeFormat;
124                        pnOriginalMediaTypeFormat.Attach(OriginalMediaType.pbFormat); // To be automatically released later on
125                        // NOTE: Sover videos are decoded into other formats, these cases are not covered by this sample
126                        ATLASSERT(OriginalMediaType.formattype == FORMAT_VideoInfo);
127                        const VIDEOINFOHEADER* pOriginalVideoInfoHeader = (const VIDEOINFOHEADER*) OriginalMediaType.pbFormat;
128                        ATLENSURE_SUCCEEDED(pRendererInputPin->Disconnect());
129                        ATLENSURE_SUCCEEDED(pRendererInputPeerPin->Disconnect());
130                        #pragma endregion
131                        #pragma region Insert Sample Grabber
132                        // NOTE: In this sample we force video resize in 32-bit RGB domain
133                        CComPtr<IBaseFilter> pSgBaseFilter;
134                        ATLENSURE_SUCCEEDED(pSgBaseFilter.CoCreateInstance(__uuidof(SampleGrabber)));
135                        ATLENSURE_SUCCEEDED(pGraphBuilder->AddFilter(pSgBaseFilter, CT2CW(_T("32-Bit RGB Sample Grabber"))));
136                        const CComQIPtr<ISampleGrabber> pSampleGrabber = pSgBaseFilter;
137                        ATLENSURE_THROW(pSampleGrabber, E_NOINTERFACE);
138                        AM_MEDIA_TYPE Rgb32MediaType;
139                        ZeroMemory(&Rgb32MediaType, sizeof Rgb32MediaType);
140                        Rgb32MediaType.majortype = MEDIATYPE_Video;
141                        Rgb32MediaType.subtype = MEDIASUBTYPE_RGB32;
142                        ATLENSURE_SUCCEEDED(pSampleGrabber->SetMediaType(&Rgb32MediaType));
143                        CPinArray SgPinArray;
144                        ATLVERIFY(GetPins(pSgBaseFilter, SgPinArray) >= 2);
145                        // ASSU: First pin is input, Second pin is output
146                        ATLENSURE_SUCCEEDED(pGraphBuilder->Connect(pRendererInputPeerPin, SgPinArray[0]));
147                        pRendererInputPeerPin = SgPinArray[1];
148                        #pragma endregion
149                        #pragma region Insert Resizer Filter
150                        CComPtr<IBaseFilter> pBaseFilter;
151                        ATLENSURE_SUCCEEDED(pBaseFilter.CoCreateInstance(CLSID_DMOWrapperFilter));
152                        const CComQIPtr<IDMOWrapperFilter> pDmoWrapperFilter = pBaseFilter;
153                        ATLENSURE_THROW(pDmoWrapperFilter, E_NOINTERFACE);
154                        ATLENSURE_SUCCEEDED(pDmoWrapperFilter->Init(CLSID_CResizerDMO, DMOCATEGORY_VIDEO_EFFECT));
155                        ATLENSURE_SUCCEEDED(pGraphBuilder->AddFilter(pBaseFilter, CT2CW(_T("Resizer"))));
156                        CPinArray PinArray;
157                        ATLVERIFY(GetPins(pBaseFilter, PinArray) >= 2);
158                        // ASSU: First pin is input, Second pin is output
159                        #pragma endregion
160                        const CComPtr<IPin>& pInputPin = PinArray[0];
161                        const CComPtr<IPin>& pOutputPin = PinArray[1];
162                        #pragma endregion
163                        const CComQIPtr<IWMResizerProps> pWmResizerProps = pBaseFilter;
164                        ATLENSURE_THROW(pWmResizerProps, E_NOINTERFACE);
165                        ATLENSURE_SUCCEEDED(pWmResizerProps->SetFullCropRegion(
166                                0, 0, pOriginalVideoInfoHeader->bmiHeader.biWidth, pOriginalVideoInfoHeader->bmiHeader.biHeight,
167                                0, 0, pOriginalVideoInfoHeader->bmiHeader.biWidth, 2 * pOriginalVideoInfoHeader->bmiHeader.biHeight
168                                ));
169                        ATLENSURE_SUCCEEDED(pGraphBuilder->Connect(pRendererInputPeerPin, pInputPin));
170                        #pragma region Input Pin Format
171                        AM_MEDIA_TYPE InputMediaType;
172                        ZeroMemory(&InputMediaType, sizeof InputMediaType);
173                        ATLENSURE_SUCCEEDED(pInputPin->ConnectionMediaType(&InputMediaType));
174                        CComHeapPtr<BYTE> pnInputMediaTypeFormat;
175                        pnInputMediaTypeFormat.Attach(InputMediaType.pbFormat); // To be automatically released later on
176                        ATLASSERT(InputMediaType.formattype == FORMAT_VideoInfo);
177                        const VIDEOINFOHEADER* pInputVideoInfoHeader = (const VIDEOINFOHEADER*) InputMediaType.pbFormat;
178                        #pragma endregion
179                        #pragma region Prepare Output Media Type
180                        VIDEOINFOHEADER OutputVideoInfoHeader = *pInputVideoInfoHeader;
181                        SetRect(&OutputVideoInfoHeader.rcSource, 0, 0, pInputVideoInfoHeader->bmiHeader.biWidth, pInputVideoInfoHeader->bmiHeader.biHeight);
182                        OutputVideoInfoHeader.rcTarget = OutputVideoInfoHeader.rcSource;
183                        OutputVideoInfoHeader.dwBitRate = 0;
184                        OutputVideoInfoHeader.dwBitErrorRate = 0;
185                        ATLASSERT(OutputVideoInfoHeader.bmiHeader.biSize == sizeof OutputVideoInfoHeader.bmiHeader);
186                        // NOTE: Twice as high
187                        OutputVideoInfoHeader.bmiHeader.biHeight <<= 1;
188                        OutputVideoInfoHeader.bmiHeader.biSizeImage <<= 1;
189                        AM_MEDIA_TYPE OutputMediaType = InputMediaType;
190                        OutputMediaType.lSampleSize = OutputVideoInfoHeader.bmiHeader.biSizeImage;
191                        ATLASSERT(!OutputMediaType.pUnk);
192                        OutputMediaType.cbFormat = sizeof OutputVideoInfoHeader;
193                        OutputMediaType.pbFormat = (BYTE*) &OutputVideoInfoHeader;
194                        #pragma endregion
195                        const CComQIPtr<IMediaObject> pMediaObject = pBaseFilter;
196                        ATLENSURE_THROW(pMediaObject, E_NOINTERFACE);
197                        ATLENSURE_SUCCEEDED(pMediaObject->SetOutputType(0, (DMO_MEDIA_TYPE*) &OutputMediaType, 0));
198                        #if !TRUE
199                                CComPtr<IBaseFilter> pCscBaseFilter;
200                                ATLENSURE_SUCCEEDED(pCscBaseFilter.CoCreateInstance(CLSID_Colour));
201                                ATLENSURE_SUCCEEDED(pGraphBuilder->AddFilter(pCscBaseFilter, CT2CW(_T("Color Space Converter"))));
202                                CPinArray CscPinArray;
203                                ATLVERIFY(GetPins(pCscBaseFilter, CscPinArray) >= 2);
204                                // ASSU: First pin is input, Second pin is output
205                                ATLENSURE_SUCCEEDED(pGraphBuilder->ConnectDirect(pOutputPin, CscPinArray[0], &OutputMediaType));
206                                ATLENSURE_SUCCEEDED(pGraphBuilder->Connect(CscPinArray[1], pRendererInputPin));
207                        #else
208                                ATLENSURE_SUCCEEDED(pGraphBuilder->ConnectDirect(pOutputPin, pRendererInputPin, &OutputMediaType));
209                        #endif
210                        #pragma region Run Graph
211                        const CComQIPtr<IMediaControl> pMediaControl = pGraphBuilder;
212                        ATLENSURE_THROW(pMediaControl, E_NOINTERFACE);
213                        ATLENSURE_SUCCEEDED(pMediaControl->Run());
214                        //MessageBox(GetActiveWindow(), _T("Connect Remotely to the Graph"), _T("Debug"), MB_ICONINFORMATION | MB_OK);
215                        const CComQIPtr<IMediaEvent> pMediaEvent = pGraphBuilder;
216                        ATLENSURE_THROW(pMediaEvent, E_NOINTERFACE);
217                        LONG nEventCode;
218                        ATLENSURE_SUCCEEDED(pMediaEvent->WaitForCompletion(INFINITE, &nEventCode));
219                        #pragma endregion
220                }
221                CoUninitialize();
222        }
223        _ATLCATCH(Exception)
224        {
225                _tprintf(_T("Fatal Error 0x%08x\n"), (HRESULT) Exception);
226        }
227        _ATLCATCHALL()
228        {
229                _tprintf(_T("Fatal Error\n"));
230        }
231        return 0;
232}
233
Note: See TracBrowser for help on using the repository browser.