1 | //////////////////////////////////////////////////////////// |
---|
2 | // Copyright (C) Roman Ryltsov, 2015-2017 |
---|
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 | |
---|
15 | class CModule : |
---|
16 | public CAtlExeModuleT<CModule> |
---|
17 | { |
---|
18 | public: |
---|
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 | CComPtr<IMFMediaSource> pMediaSource; |
---|
40 | //{ |
---|
41 | // static const LPCTSTR g_pszPath = |
---|
42 | // _T("D:\\Projects\\Alax.Info\\Repository-Private\\Utilities\\DirectShow\\ReferenceSource\\_Media\\720p50-Small-V.mp4"); |
---|
43 | // MF_OBJECT_TYPE ObjectType; |
---|
44 | // CComPtr<IUnknown> pMediaSourceUnknown; |
---|
45 | // __C(pSourceResolver->CreateObjectFromURL(CStringW(g_pszPath), MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &pMediaSourceUnknown)); |
---|
46 | // _A(ObjectType == MF_OBJECT_MEDIASOURCE); |
---|
47 | // pMediaSource = pMediaSourceUnknown; |
---|
48 | // __D(pMediaSource, E_NOINTERFACE); |
---|
49 | //} |
---|
50 | CComPtr<IMFMediaSource> pVideoMediaSource, pAudioMediaSource; |
---|
51 | const BOOL g_bVideo = TRUE; |
---|
52 | const SIZE g_Extent = |
---|
53 | { 1920, 1080 }; |
---|
54 | //{ 7680 / 2, 4320 / 2 }; |
---|
55 | //{ 7680, 4320 }; |
---|
56 | const LONG g_nFrameRateNumerator = 50000; |
---|
57 | const LONG g_nFrameRateDenominator = 1000; |
---|
58 | const LONG g_nVideoBitrate = (10 * 1000) * 1000; // MBps |
---|
59 | const BOOL g_bAudio = FALSE; |
---|
60 | const LONG g_nSampleRate = 48000; |
---|
61 | const LONG g_nChannelCount = 1; |
---|
62 | const LONG g_nBitDepth = 16; |
---|
63 | const LONG g_nAudioBitrate = 20 * 1000; // kBps |
---|
64 | const LONG g_nDuration = 1 * 60; // minutes |
---|
65 | #pragma region Video |
---|
66 | if(g_bVideo) |
---|
67 | { |
---|
68 | using namespace AlaxInfoDirectShowReferenceSource; |
---|
69 | CComPtr<IVideoMediaSource> pSource; |
---|
70 | __C(pSource.CoCreateInstance(__uuidof(VideoMediaSource))); |
---|
71 | __C(pSource->SetMediaType(g_Extent.cx, g_Extent.cy, CComVariant(_PersistHelper::StringFromIdentifier(MEDIASUBTYPE_RGB32)))); |
---|
72 | //__C(pSource->SetMediaTypeAspectRatio(...)); |
---|
73 | __C(pSource->SetMediaTypeRate(g_nFrameRateNumerator, g_nFrameRateDenominator)); |
---|
74 | __C(pSource->put_Duration((DOUBLE) g_nDuration)); |
---|
75 | pVideoMediaSource = pSource; |
---|
76 | } |
---|
77 | #pragma endregion |
---|
78 | #pragma region Audio |
---|
79 | if(g_bAudio) |
---|
80 | { |
---|
81 | using namespace AlaxInfoDirectShowReferenceSource; |
---|
82 | CComPtr<IAudioMediaSource> pSource; |
---|
83 | __C(pSource.CoCreateInstance(__uuidof(AudioMediaSource))); |
---|
84 | __C(pSource->SetMediaType(NULL, g_nSampleRate, g_nChannelCount, g_nBitDepth)); |
---|
85 | __C(pSource->put_Duration((DOUBLE) g_nDuration)); |
---|
86 | pAudioMediaSource = pSource; |
---|
87 | } |
---|
88 | #pragma endregion |
---|
89 | __D(pVideoMediaSource || pAudioMediaSource, E_UNNAMED); |
---|
90 | if(pVideoMediaSource && pAudioMediaSource) |
---|
91 | { |
---|
92 | CComPtr<IMFCollection> pCollection; |
---|
93 | __C(MFCreateCollection(&pCollection)); |
---|
94 | __C(pCollection->AddElement(pVideoMediaSource)); |
---|
95 | __C(pCollection->AddElement(pAudioMediaSource)); |
---|
96 | __C(MFCreateAggregateSource(pCollection, &pMediaSource)); |
---|
97 | } else |
---|
98 | pMediaSource = pVideoMediaSource ? pVideoMediaSource : pAudioMediaSource; |
---|
99 | _A(pMediaSource); |
---|
100 | #pragma endregion |
---|
101 | CPath sFilePath; |
---|
102 | { |
---|
103 | SYSTEMTIME Time; |
---|
104 | GetLocalTime(&Time); |
---|
105 | const CString sFileName = AtlFormatString(_T("%04d%02d%02d-%02d%02d%02d.mp4"), Time.wYear, Time.wMonth, Time.wDay, Time.wHour, Time.wMinute, Time.wSecond); |
---|
106 | sFilePath = Combine(GetPathDirectory(GetModulePath()), sFileName); |
---|
107 | } |
---|
108 | #pragma region Topology |
---|
109 | // NOTE: Creating Topologies https://msdn.microsoft.com/en-us/library/windows/desktop/ms702144 |
---|
110 | // Topology Node Attributes https://msdn.microsoft.com/en-us/library/windows/desktop/aa369728 |
---|
111 | // Tutorial: Encoding an MP4 File https://msdn.microsoft.com/en-us/library/ff819476 |
---|
112 | MF::CTopology pTopology; |
---|
113 | //pTopology.Create(); |
---|
114 | #pragma region Profile |
---|
115 | CComPtr<IMFTranscodeProfile> pTranscodeProfile; |
---|
116 | { |
---|
117 | __C(MFCreateTranscodeProfile(&pTranscodeProfile)); |
---|
118 | #pragma region Video |
---|
119 | if(pVideoMediaSource) |
---|
120 | { |
---|
121 | MF::CAttributes pAttributes; |
---|
122 | pAttributes.Create(8); |
---|
123 | pAttributes[MF_MT_SUBTYPE] = |
---|
124 | MFVideoFormat_H264; |
---|
125 | //MFVideoFormat_HEVC; |
---|
126 | pAttributes[MF_MT_AVG_BITRATE] = (UINT32) g_nVideoBitrate; |
---|
127 | pAttributes[MF_MT_FRAME_SIZE].SetSize(g_Extent.cx, g_Extent.cy); |
---|
128 | pAttributes[MF_MT_FRAME_RATE].SetRatio(g_nFrameRateNumerator, g_nFrameRateDenominator); |
---|
129 | __C(pTranscodeProfile->SetVideoAttributes(pAttributes)); |
---|
130 | pAttributes.Trace(); |
---|
131 | } |
---|
132 | #pragma endregion |
---|
133 | #pragma region Audio |
---|
134 | if(pAudioMediaSource) |
---|
135 | { |
---|
136 | // NOTE: The following audio attributes can be set: https://msdn.microsoft.com/en-us/library/windows/desktop/dd369143 |
---|
137 | // Audio Media Types |
---|
138 | // MF_TRANSCODE_DONOT_INSERT_ENCODER |
---|
139 | // MF_TRANSCODE_ENCODINGPROFILE |
---|
140 | // MF_TRANSCODE_QUALITYVSSPEED |
---|
141 | MF::CAttributes pAttributes; |
---|
142 | pAttributes.Create(8); |
---|
143 | pAttributes[MF_MT_SUBTYPE] = MFAudioFormat_AAC; |
---|
144 | pAttributes[MF_MT_AUDIO_SAMPLES_PER_SECOND] = (UINT32) g_nSampleRate; |
---|
145 | pAttributes[MF_MT_AUDIO_NUM_CHANNELS] = (UINT32) g_nChannelCount; |
---|
146 | pAttributes[MF_MT_AUDIO_BITS_PER_SAMPLE] = (UINT32) g_nBitDepth; |
---|
147 | pAttributes[MF_MT_AUDIO_AVG_BYTES_PER_SECOND] = (UINT32) g_nAudioBitrate; |
---|
148 | __C(pTranscodeProfile->SetAudioAttributes(pAttributes)); |
---|
149 | pAttributes.Trace(); |
---|
150 | } |
---|
151 | #pragma endregion |
---|
152 | MF::CAttributes pAttributes; |
---|
153 | pAttributes.Create(2); |
---|
154 | pAttributes[MF_TRANSCODE_CONTAINERTYPE] = |
---|
155 | MFTranscodeContainerType_MPEG4; |
---|
156 | //MFTranscodeContainerType_FMPEG4; |
---|
157 | pAttributes[MF_TRANSCODE_TOPOLOGYMODE] = (UINT32) MF_TRANSCODE_TOPOLOGYMODE_HARDWARE_ALLOWED; |
---|
158 | __C(pTranscodeProfile->SetContainerAttributes(pAttributes)); |
---|
159 | } |
---|
160 | #pragma endregion |
---|
161 | __C(MFCreateTranscodeTopology(pMediaSource, CT2CW((LPCTSTR) sFilePath), pTranscodeProfile, &pTopology.m_p)); |
---|
162 | pTopology.Trace(); |
---|
163 | #pragma endregion |
---|
164 | #pragma region Session |
---|
165 | CComPtr<IMFMediaSession> pMediaSession; |
---|
166 | __C(MFCreateMediaSession(NULL, &pMediaSession)); |
---|
167 | __C(pMediaSession->SetTopology(0, pTopology)); |
---|
168 | for(BOOL bDone = FALSE; !bDone; ) |
---|
169 | { |
---|
170 | MF::CMediaEvent pMediaEvent; |
---|
171 | __C(pMediaSession->GetEvent(0, &pMediaEvent)); |
---|
172 | pMediaEvent.Trace(); |
---|
173 | MediaEventType Type; |
---|
174 | __C(pMediaEvent->GetType(&Type)); |
---|
175 | HRESULT nStatus; |
---|
176 | __C(pMediaEvent->GetStatus(&nStatus)); |
---|
177 | switch(Type) |
---|
178 | { |
---|
179 | case MESessionTopologySet: |
---|
180 | { |
---|
181 | MF::CPropVariant vValue; |
---|
182 | if(SUCCEEDED(pMediaEvent->GetValue(&vValue)) && vValue.vt == VT_UNKNOWN) |
---|
183 | { |
---|
184 | MF::CTopology pTopology; |
---|
185 | pTopology.m_p = CComQIPtr<IMFTopology>(vValue.punkVal); |
---|
186 | pTopology.Trace(); |
---|
187 | } |
---|
188 | } |
---|
189 | break; |
---|
190 | case MESessionTopologyStatus: |
---|
191 | { |
---|
192 | const MF_TOPOSTATUS TopoStatus = (MF_TOPOSTATUS) pMediaEvent.GetUINT32(MF_EVENT_TOPOLOGY_STATUS); |
---|
193 | _Z4(atlTraceGeneral, 4, _T("TopoStatus %s\n"), MF::FormatTopologyStatus(TopoStatus)); |
---|
194 | switch(TopoStatus) |
---|
195 | { |
---|
196 | case MF_TOPOSTATUS_READY: |
---|
197 | { |
---|
198 | pTopology.Trace(); |
---|
199 | MF::CPropVariant vStartPosition; |
---|
200 | //vStartPosition.vt = VT_I8; |
---|
201 | //vStartPosition.hVal.QuadPart = 2 * 1000 * 10000i64; |
---|
202 | __C(pMediaSession->Start(&GUID_NULL, &vStartPosition)); |
---|
203 | } |
---|
204 | break; |
---|
205 | case MF_TOPOSTATUS_ENDED: |
---|
206 | break; |
---|
207 | } |
---|
208 | } |
---|
209 | break; |
---|
210 | case MESessionStarted: |
---|
211 | break; |
---|
212 | case MESessionEnded: |
---|
213 | __C(pMediaSession->Stop()); |
---|
214 | break; |
---|
215 | case MESessionStopped: |
---|
216 | __C(pMediaSession->Close()); |
---|
217 | break; |
---|
218 | case MESessionClosed: |
---|
219 | bDone = TRUE; |
---|
220 | break; |
---|
221 | } |
---|
222 | if(FAILED(nStatus)) |
---|
223 | bDone = TRUE; |
---|
224 | } |
---|
225 | __C(pMediaSession->Shutdown()); |
---|
226 | #pragma endregion |
---|
227 | } |
---|
228 | }; |
---|
229 | |
---|
230 | int _tmain(int argc, _TCHAR* argv[]) |
---|
231 | { |
---|
232 | _ATLTRY |
---|
233 | { |
---|
234 | CModule Module; |
---|
235 | Module.WinMain(SW_SHOWNORMAL); |
---|
236 | } |
---|
237 | _ATLCATCH(Exception) |
---|
238 | { |
---|
239 | _tprintf(_T("Fatal Error 0x%08X\n"), (HRESULT) Exception); |
---|
240 | } |
---|
241 | return 0; |
---|
242 | } |
---|