source: trunk/Utilities/DirectShowReferenceSource/Sample/MfGenerate/Application.cpp

Last change on this file was 823, checked in by roman, 6 years ago

Sync and added MfGenerateFlac? sample

File size: 10.3 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2015-2018
3// Created by Roman Ryltsov roman@alax.info
4//
5// A permission to use the source code is granted as long as reference to
6// source website http://alax.info is retained.
7
8#include "stdafx.h"
9#include "romf.h"
10#import "libid:9E3ABA93-C8D8-41D3-B39E-29508FDE5757" raw_interfaces_only // AlaxInfoDirectShowReferenceSource
11
12////////////////////////////////////////////////////////////
13// CModule
14
15class CModule :
16        public CAtlExeModuleT<CModule>
17{
18public:
19// CModule
20        bool ParseCommandLine(LPCTSTR pszCommandLine, HRESULT* pnResult)
21        {
22                _A(pnResult);
23                pszCommandLine;
24                *pnResult = S_OK;
25                return true;
26        }
27        HRESULT PreMessageLoop(int nShowCommand)
28        {
29                // NOTE: Suppress S_FALSE
30                _C(__super::PreMessageLoop(nShowCommand));
31                return S_OK;
32        }
33        VOID RunMessageLoop()
34        {
35                MF::CStartup Statup;
36                CComPtr<IMFSourceResolver> pSourceResolver;
37                __C(MFCreateSourceResolver(&pSourceResolver));
38                #pragma region Media Source
39                CComQIPtr<IMFMediaSource> pMediaSource;
40
41                //{
42                //      static const LPCTSTR g_pszPath =
43                //              _T("D:\\Projects\\Alax.Info\\Repository-Private\\Utilities\\DirectShow\\ReferenceSource\\_Media\\720p50-Small-V.mp4");
44                //      MF_OBJECT_TYPE ObjectType;
45                //      CComPtr<IUnknown> pMediaSourceUnknown;
46                //      __C(pSourceResolver->CreateObjectFromURL(CStringW(g_pszPath), MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &pMediaSourceUnknown));
47                //      _A(ObjectType == MF_OBJECT_MEDIASOURCE);
48                //      pMediaSource = pMediaSourceUnknown;
49                //      __D(pMediaSource, E_NOINTERFACE);
50                //}
51
52                //const SIZE g_Extent = { 640, 360 };
53                //const LONG g_nFrameRateNumerator = 30000;
54                //const LONG g_nFrameRateDenominator = 1001;
55                //const LONG g_nDuration = 1 * 60; // 1 minutes
56                //const LONG g_nBitrate = (2 << 10) * 1000; // 2 MBps
57
58                //const SIZE g_Extent = { 720, 480 };
59                //const LONG g_nFrameRateNumerator = 90; //30 * 1000;
60                //const LONG g_nFrameRateDenominator = 1; //1001;
61                //const LONG g_nDuration = 60; //5 * 60; // 5 minutes
62                //const LONG g_nBitrate = (2 << 10) * 1000; // 2 MBps
63
64                //const SIZE g_Extent = { 1280, 720 };
65                //const LONG g_nFrameRateNumerator = 60 * 1000;
66                //const LONG g_nFrameRateDenominator = 1000;
67                //const LONG g_nDuration = 5 * 60; // 5 minutes
68                //const LONG g_nBitrate = (5 << 10) * 1000; // 5 MBps
69
70                const SIZE g_Extent = { 1920, 1080 };
71                const LONG g_nFrameRateNumerator = 50 * 1000; // frames/second
72                const LONG g_nFrameRateDenominator = 1000;
73                const LONG g_nDuration = 1 * 60; // minutes
74                const LONG g_nBitrate = (10 * 1000) * 1000; // 10 MBps
75
76                //const SIZE g_Extent = { 4096, 2304 };
77                //const LONG g_nFrameRateNumerator = 50;
78                //const LONG g_nFrameRateDenominator = 1;
79                //const LONG g_nDuration = 5 * 60; // 5 minutes
80                //const LONG g_nBitrate = (2 << 10) * 1000; // 2 MBps
81
82                #pragma region DXGI Device Manager
83                static SIZE_T g_nDxgiAdapterIndex = 0;
84                MF::CDxgiDeviceManager pDxgiDeviceManager;
85                {
86                        #pragma region DXGI Adapter
87                        DXGI::CFactory2 pFactory2;
88                        pFactory2.DebugCreate();
89                        CRoArrayT<DXGI::CAdapter1> AdapterArray;
90                        _A(pFactory2.EnumerateAdapters(AdapterArray) == 3);
91                        DXGI::CAdapter1& pAdapter1 = AdapterArray[g_nDxgiAdapterIndex];
92                        #pragma region D3D11 Device
93                        CComPtr<ID3D11Device> pDevice;
94                        UINT nFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
95                        #if defined(_DEBUG)
96                                nFlags |= D3D11_CREATE_DEVICE_DEBUG;
97                        #endif // defined(_DEBUG)
98                        static const D3D_FEATURE_LEVEL g_pFeatureLevels[] = 
99                        {
100                                D3D_FEATURE_LEVEL_12_1,
101                                D3D_FEATURE_LEVEL_12_0,
102                                D3D_FEATURE_LEVEL_11_1,
103                                D3D_FEATURE_LEVEL_11_0,
104                                D3D_FEATURE_LEVEL_10_1,
105                                D3D_FEATURE_LEVEL_10_0,
106                                D3D_FEATURE_LEVEL_9_3,
107                                D3D_FEATURE_LEVEL_9_2,
108                                D3D_FEATURE_LEVEL_9_1,
109                        };
110                        D3D_FEATURE_LEVEL FeatureLevel;
111                        CComPtr<ID3D11DeviceContext> pDeviceContext;
112                        // SUGG: Reuse CVideoInput's CreateDevice doing D3D11CreateDevice
113                        __C(D3D11CreateDevice(pAdapter1, D3D_DRIVER_TYPE_UNKNOWN, NULL, nFlags, g_pFeatureLevels, DIM(g_pFeatureLevels), D3D11_SDK_VERSION, &pDevice, &FeatureLevel, &pDeviceContext));
114                        const CComQIPtr<ID3D11Multithread> pMultithread = pDevice;
115                        __D(pMultithread, E_NOINTERFACE);
116                        pMultithread->SetMultithreadProtected(TRUE);
117                        #pragma endregion
118                        #pragma endregion
119                        pDxgiDeviceManager.Create();
120                        pDxgiDeviceManager.Reset(pDevice);
121                }
122                #pragma endregion
123
124                {
125                        using namespace AlaxInfoDirectShowReferenceSource;
126                        CComPtr<IVideoMediaSource> pVideoMediaSource;
127                        __C(pVideoMediaSource.CoCreateInstance(__uuidof(VideoMediaSource)));
128                        __C(pVideoMediaSource->SetMediaType(g_Extent.cx, g_Extent.cy, CComVariant(_PersistHelper::StringFromIdentifier(MEDIASUBTYPE_RGB32))));
129                        //__C(pVideoMediaSource->SetMediaTypeAspectRatio(...));
130                        __C(pVideoMediaSource->SetMediaTypeRate(g_nFrameRateNumerator, g_nFrameRateDenominator));
131                        __C(pVideoMediaSource->put_Duration((DOUBLE) g_nDuration));
132                        pMediaSource = pVideoMediaSource;
133                }
134                #pragma endregion
135                CComPtr<IMFSourceReader> pSourceReader;
136                {
137                        MF::CAttributes pAttributes;
138                        if(pDxgiDeviceManager)
139                        {
140                                pAttributes.Create(4);
141                                pAttributes[MF_READWRITE_D3D_OPTIONAL] = (UINT32) 0;
142                                pAttributes[MF_SOURCE_READER_D3D_MANAGER] = (IMFDXGIDeviceManager*) pDxgiDeviceManager;
143                        }
144                        __C(MFCreateSourceReaderFromMediaSource(pMediaSource, pAttributes, &pSourceReader));
145                }
146                MF::CMediaType pMediaType;
147                __C(pSourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pMediaType));
148                pMediaType.Trace();
149                SYSTEMTIME Time;
150                GetLocalTime(&Time);
151                const CString sFileName = AtlFormatString(_T("%04d%02d%02d-%02d%02d%02d.mp4"), Time.wYear, Time.wMonth, Time.wDay, Time.wHour, Time.wMinute, Time.wSecond);
152                CComPtr<IMFSinkWriter> pSinkWriter;
153                {
154                        MF::CAttributes pAttributes;
155                        if(pDxgiDeviceManager)
156                        {
157                                pAttributes.Create(4);
158                                pAttributes[MF_READWRITE_D3D_OPTIONAL] = (UINT32) 0;
159                                pAttributes[MF_SINK_WRITER_D3D_MANAGER] = (IMFDXGIDeviceManager*) pDxgiDeviceManager;
160                        }
161                        __C(MFCreateSinkWriterFromURL(Combine(GetPathDirectory(GetModulePath()), sFileName), NULL, pAttributes, &pSinkWriter));
162                }
163                MF::CMediaType pWriterMediaType;
164                pWriterMediaType.Create();
165                // NOTE: H.264 Video Encoder https://msdn.microsoft.com/en-us/library/windows/desktop/dd797816
166                pWriterMediaType[MF_MT_MAJOR_TYPE] = MFMediaType_Video;
167                pWriterMediaType[MF_MT_SUBTYPE] = MFVideoFormat_H264;
168                pWriterMediaType.CopyFrom(pMediaType, MF_MT_FRAME_RATE);
169                pWriterMediaType.CopyFrom(pMediaType, MF_MT_FRAME_SIZE);
170                pWriterMediaType.CopyFrom(pMediaType, MF_MT_INTERLACE_MODE);
171                pWriterMediaType.CopyFrom(pMediaType, MF_MT_PIXEL_ASPECT_RATIO);
172                pWriterMediaType[MF_MT_AVG_BITRATE] = (UINT32) g_nBitrate;
173                //pWriterMediaType[MF_MT_MPEG2_PROFILE] = (UINT32) eAVEncH264VProfile_High;
174                pWriterMediaType.Trace();
175                DWORD nWriterStreamIndex;
176                __C(pSinkWriter->AddStream(pWriterMediaType, &nWriterStreamIndex));
177                // NOTE: Sink Writer Attributes https://msdn.microsoft.com/en-us/library/windows/desktop/dd389284
178
179                //class __declspec(uuid("4E498B6F-7DCA-403E-A523-912A73943341")) NvEncoderTransform;
180                //MFT_REGISTER_TYPE_INFO pInputTypeInformation[] = { { MFMediaType_Video, MFVideoFormat_ARGB32 } };
181                //MFT_REGISTER_TYPE_INFO pOutputTypeInformation[] = { { MFMediaType_Video, MFVideoFormat_H264 } };
182                //__C(MFTRegisterLocalByCLSID(__uuidof(NvEncoderTransform), MFT_CATEGORY_VIDEO_ENCODER, L"Rainway H.264 Encoder for NVIDIA HW", MFT_ENUM_FLAG_ASYNCMFT, DIM(pInputTypeInformation), pInputTypeInformation, DIM(pOutputTypeInformation), pOutputTypeInformation));
183                {
184                        MF::CAttributes pAttributes;
185                        pAttributes.Create(10);
186                        pAttributes[MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS] = (UINT32) 1;
187                        __C(pSinkWriter->SetInputMediaType(nWriterStreamIndex, pMediaType, pAttributes));
188                }
189                MF::CSinkWriterHelper::TraceTransformsT<MF::CSinkWriterHelper::CVideoTraceTraits>(pSinkWriter);
190
191                CRoArrayT<CComPtr<IMFTransform>> TransformArray;
192                MF::CSinkWriterHelper::GetTransforms(pSinkWriter, nWriterStreamIndex, TransformArray);
193                _A(!TransformArray.IsEmpty());
194                MF::CCodecApi pCodecApi(TransformArray[TransformArray.GetCount() - 1]);
195                pCodecApi[CODECAPI_AVEncCommonRateControlMode] = (UINT32) eAVEncCommonRateControlMode_CBR;
196                pCodecApi[CODECAPI_AVEncCommonMeanBitRate] = (UINT32) g_nBitrate;
197                pCodecApi[CODECAPI_AVEncMPVGOPSize] = (UINT32) 1;
198                //pCodecApi[CODECAPI_AVEncMPVDefaultBPictureCount] = (UINT32) 0;
199
200                const ULONG nTimeA = GetTickCount();
201                __C(pSinkWriter->BeginWriting());
202                for(; ; )
203                {
204                        DWORD nStreamIndex, nStreamFlags;
205                        LONGLONG nTime;
206                        MF::CSample pSample;
207                        __C(pSourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &nStreamIndex, &nStreamFlags, &nTime, &pSample));
208                        _Z4(atlTraceGeneral, 4, _T("nStreamIndex %d, nStreamFlags %s, nTime %s, pSample 0x%p\n"), nStreamIndex, MF::FormatSourceReaderStreamFlags(nStreamFlags), MF::FormatNanoTime(nTime), pSample);
209                        if(pSample)
210                        {
211                                pSample.Trace();
212                                #pragma region Re-Configuration
213                                #if defined(_DEBUG)
214                                        static INT g_nState = 0;
215                                        if(!g_nState && pSample.GetTime() >= 30000 * 10000i64)
216                                        {
217                                                g_nState = 1;
218                                                const CComQIPtr<IMFSinkWriterEncoderConfig> pSinkWriterEncoderConfig = pSinkWriter;
219                                                __D(pSinkWriterEncoderConfig, E_NOINTERFACE);
220                                                MF::CAttributes pAttributes;
221                                                pAttributes.Create(4);
222                                                //pAttributes[CODECAPI_AVEncCommonRateControlMode] = (UINT32) eAVEncCommonRateControlMode_CBR;
223                                                pAttributes[CODECAPI_AVEncCommonMeanBitRate] = (UINT32) g_nBitrate / 4;
224                                                // NOTE: MF_SOURCE_READER_FIRST_VIDEO_STREAM results in MF_E_INVALIDSTREAMNUMBER
225                                                __C(pSinkWriterEncoderConfig->PlaceEncodingParameters(0, pAttributes));
226                                                // SUGG: Check IMFSinkWriterEncoderConfig::SetTargetMediaType as well
227                                        }
228                                #endif // defined(_DEBUG)
229                                #pragma endregion
230                                __C(pSinkWriter->WriteSample(nWriterStreamIndex, pSample));
231                        }
232                        if(nStreamFlags & MF_SOURCE_READERF_ENDOFSTREAM)
233                        {
234                                _A(!pSample);
235                                break;
236                        }
237                }
238                __C(pSourceReader->Flush(MF_SOURCE_READER_ALL_STREAMS));
239                const ULONG nTimeB = GetTickCount();
240                _tprintf(_T("Elapsed Time: %.2f seconds\n"), (DOUBLE) (nTimeB - nTimeA) / 1E3);
241                __C(pSinkWriter->Finalize());
242        }
243};
244
245int _tmain(int argc, _TCHAR* argv[])
246{
247        _ATLTRY
248        {
249                CModule Module;
250                Module.WinMain(SW_SHOWNORMAL);
251        }
252        _ATLCATCH(Exception)
253        {
254                _tprintf(_T("Fatal Error 0x%08X\n"), (HRESULT) Exception);
255        }
256        return 0;
257}
258
Note: See TracBrowser for help on using the repository browser.