1 | //////////////////////////////////////////////////////////// |
---|
2 | // Copyright (C) Roman Ryltsov, 2016 |
---|
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 | #pragma once |
---|
9 | |
---|
10 | #include "rodshow.h" |
---|
11 | #include "romf.h" |
---|
12 | |
---|
13 | //////////////////////////////////////////////////////////// |
---|
14 | // CModule |
---|
15 | |
---|
16 | class CModule : |
---|
17 | public CAtlExeModuleT<CModule> |
---|
18 | { |
---|
19 | public: |
---|
20 | |
---|
21 | public: |
---|
22 | static CEvent g_TerminationEvent; |
---|
23 | CString m_sVideoIdentifier; |
---|
24 | UINT32 m_nBitrate; |
---|
25 | CString m_sAudioIdentifier; |
---|
26 | UINT m_nDuration; |
---|
27 | |
---|
28 | public: |
---|
29 | // CModule |
---|
30 | CModule() |
---|
31 | { |
---|
32 | AtlTraceSetDefaultSettings(); |
---|
33 | _Z4_THIS(); |
---|
34 | //_W(CExceptionFilter::Initialize()); |
---|
35 | m_nBitrate = 0; |
---|
36 | m_nDuration = 10; |
---|
37 | } |
---|
38 | ~CModule() |
---|
39 | { |
---|
40 | _Z4_THIS(); |
---|
41 | //CExceptionFilter::Terminate(); |
---|
42 | } |
---|
43 | bool ParseCommandLine(LPCTSTR pszCommandLine, HRESULT* pnResult) |
---|
44 | { |
---|
45 | _A(pnResult); |
---|
46 | _ATLTRY |
---|
47 | { |
---|
48 | CCommandLineArguments Arguments(pszCommandLine); |
---|
49 | CCommandLineArguments::CArgument Argument; |
---|
50 | while(Arguments.Next(Argument)) |
---|
51 | { |
---|
52 | __D(!Argument.m_bSwitch, E_UNNAMED); |
---|
53 | #pragma region help |
---|
54 | if(Argument.m_sValue.CompareNoCase(_T("help")) == 0) |
---|
55 | { |
---|
56 | _tprintf( |
---|
57 | _T("Syntax: %s argument [argument...]") _T("\n") |
---|
58 | _T("\n") |
---|
59 | _T("Arguments:") _T("\n") |
---|
60 | _T("\t") _T("help - displays syntax") _T("\n"), |
---|
61 | FindFileName(GetModulePath())); |
---|
62 | return false; |
---|
63 | } else |
---|
64 | #pragma endregion |
---|
65 | __C(E_UNNAMED); |
---|
66 | } |
---|
67 | } |
---|
68 | _ATLCATCH(Exception) |
---|
69 | { |
---|
70 | *pnResult = Exception; |
---|
71 | return false; |
---|
72 | } |
---|
73 | *pnResult = S_OK; |
---|
74 | return true; |
---|
75 | } |
---|
76 | HRESULT PreMessageLoop(INT nShowCommand) |
---|
77 | { |
---|
78 | const HRESULT nResult = __super::PreMessageLoop(nShowCommand); |
---|
79 | return SUCCEEDED(nResult) ? S_OK : nResult; |
---|
80 | } |
---|
81 | BOOL InternalHandlerRoutine(DWORD nType) |
---|
82 | { |
---|
83 | _W(g_TerminationEvent.Set()); |
---|
84 | return TRUE; |
---|
85 | } |
---|
86 | static BOOL WINAPI HandlerRoutine(DWORD nType) |
---|
87 | { |
---|
88 | return static_cast<CModule*>(_pAtlModule)->InternalHandlerRoutine(nType); |
---|
89 | } |
---|
90 | VOID ProcessInput(const CComPtr<IMFTransform>& pTransform, const MFT_INPUT_STREAM_INFO& InputStreamInformation, LONGLONG nSampleDuration, UINT nSampleIndex) |
---|
91 | { |
---|
92 | _A(pTransform); |
---|
93 | MF::CSample pSample; |
---|
94 | pSample.Create(); |
---|
95 | CComPtr<IMFMediaBuffer> pMediaBuffer; |
---|
96 | __C(MFCreateMemoryBuffer(InputStreamInformation.cbSize, &pMediaBuffer)); |
---|
97 | __C(pMediaBuffer->SetCurrentLength(InputStreamInformation.cbSize)); |
---|
98 | __C(pSample->AddBuffer(pMediaBuffer)); |
---|
99 | const LONGLONG nTime = nSampleIndex * nSampleDuration; |
---|
100 | __C(pSample->SetSampleTime(nTime)); |
---|
101 | __C(pSample->SetSampleDuration(1)); //nSampleDuration)); |
---|
102 | pSample[MFSampleExtension_CleanPoint] = (UINT32) 1; |
---|
103 | pSample[MFSampleExtension_Discontinuity] = (UINT32) (!nTime ? 1 : 0); |
---|
104 | pSample.Trace(); |
---|
105 | for(; ; ) |
---|
106 | { |
---|
107 | const HRESULT nProcessInputResult = pTransform->ProcessInput(0, pSample, 0); |
---|
108 | _Z45_MFHRESULT(nProcessInputResult); |
---|
109 | _tprintf(_T("Line %d: nTime %s, nProcessInputResult %s\n"), __LINE__, (LPCTSTR) MF::FormatNanoTime(nTime), (LPCTSTR) MF::FormatResult(nProcessInputResult)); |
---|
110 | if(nProcessInputResult == MF_E_NOTACCEPTING) |
---|
111 | { |
---|
112 | Sleep(200); |
---|
113 | continue; |
---|
114 | } |
---|
115 | if(nProcessInputResult == S_OK) |
---|
116 | break; |
---|
117 | __C(nProcessInputResult); |
---|
118 | } |
---|
119 | } |
---|
120 | VOID ProcessOutput(const CComPtr<IMFTransform>& pTransform, const MFT_OUTPUT_STREAM_INFO& OutputStreamInformation, UINT nAttemptCount = 1) |
---|
121 | { |
---|
122 | _A(pTransform); |
---|
123 | MF::CSample pSample; |
---|
124 | pSample.Create(); |
---|
125 | CComPtr<IMFMediaBuffer> pMediaBuffer; |
---|
126 | __C(MFCreateMemoryBuffer(OutputStreamInformation.cbSize, &pMediaBuffer)); |
---|
127 | __C(pSample->AddBuffer(pMediaBuffer)); |
---|
128 | for(UINT nAttemptIndex = 0; nAttemptIndex < nAttemptCount; nAttemptIndex++) |
---|
129 | { |
---|
130 | MFT_OUTPUT_DATA_BUFFER Buffer = { 0 }; |
---|
131 | Buffer.pSample = pSample; |
---|
132 | DWORD nStatus = 0; |
---|
133 | HRESULT nProcessOutputResult = pTransform->ProcessOutput(0, 1, &Buffer, &nStatus); |
---|
134 | _Z4_MFHRESULT(nProcessOutputResult); |
---|
135 | _tprintf(_T("Line %d: nProcessOutputResult %s\n"), __LINE__, (LPCTSTR) MF::FormatResult(nProcessOutputResult)); |
---|
136 | if(nProcessOutputResult == MF_E_TRANSFORM_NEED_MORE_INPUT) |
---|
137 | { |
---|
138 | Sleep(200); |
---|
139 | continue; |
---|
140 | } |
---|
141 | if(nProcessOutputResult == S_OK) |
---|
142 | { |
---|
143 | pSample.Trace(); |
---|
144 | LONGLONG nTime, nDuration; |
---|
145 | __C(pSample->GetSampleTime(&nTime)); |
---|
146 | __C(pSample->GetSampleDuration(&nDuration)); |
---|
147 | DWORD nLength; |
---|
148 | __C(pSample->GetTotalLength(&nLength)); |
---|
149 | _tprintf(_T("Line %d: nTime %s, nDuration %s, nLength %d\n"), __LINE__, (LPCTSTR) MF::FormatNanoTime(nTime), (LPCTSTR) MF::FormatNanoTime(nDuration), nLength); |
---|
150 | break; |
---|
151 | } |
---|
152 | __C(nProcessOutputResult); |
---|
153 | } |
---|
154 | } |
---|
155 | VOID RunMessageLoop() |
---|
156 | { |
---|
157 | MF::CStartup Startup; |
---|
158 | //__E(g_TerminationEvent.Create(NULL, TRUE, FALSE, NULL)); |
---|
159 | //__E(SetConsoleCtrlHandler(&CModule::HandlerRoutine, TRUE)); |
---|
160 | |
---|
161 | CComPtr<IMFTransform> pTransform; |
---|
162 | // NOTE: Video Processor MFT https://msdn.microsoft.com/en-us/library/windows/desktop/hh162913 |
---|
163 | __C(pTransform.CoCreateInstance(CLSID_VideoProcessorMFT)); |
---|
164 | MF::CMediaType pInputMediaType; |
---|
165 | pInputMediaType.Create(); |
---|
166 | pInputMediaType[MF_MT_MAJOR_TYPE] = MFMediaType_Video; |
---|
167 | pInputMediaType[MF_MT_SUBTYPE] = MFVideoFormat_RGB32; |
---|
168 | pInputMediaType[MF_MT_ALL_SAMPLES_INDEPENDENT] = (UINT32) 1; |
---|
169 | pInputMediaType[MF_MT_FRAME_SIZE].SetSize(720, 480); |
---|
170 | pInputMediaType[MF_MT_DEFAULT_STRIDE] = (UINT32) 2880; |
---|
171 | pInputMediaType[MF_MT_PIXEL_ASPECT_RATIO].SetRatio(1, 1); |
---|
172 | pInputMediaType[MF_MT_INTERLACE_MODE] = (UINT32) MFVideoInterlace_Progressive; |
---|
173 | pInputMediaType[MF_MT_FRAME_RATE].SetRatio(5, 1); |
---|
174 | pInputMediaType[MF_MT_FIXED_SIZE_SAMPLES] = (UINT32) 1; |
---|
175 | pInputMediaType[MF_MT_SAMPLE_SIZE] = (UINT32) 1382400; |
---|
176 | pInputMediaType[MF_MT_AVG_BITRATE] = (UINT32) 55296000; |
---|
177 | static const BYTE g_pnAperture[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00 }; |
---|
178 | pInputMediaType[MF_MT_MINIMUM_DISPLAY_APERTURE].SetBlob(g_pnAperture, DIM(g_pnAperture)); |
---|
179 | pInputMediaType[MF_MT_PAN_SCAN_APERTURE].SetBlob(g_pnAperture, DIM(g_pnAperture)); |
---|
180 | pInputMediaType[MF_MT_PAN_SCAN_ENABLED] = (UINT32) 1; |
---|
181 | __C(pTransform->SetInputType(0, pInputMediaType, 0)); |
---|
182 | MF::CMediaType pOutputMediaType; |
---|
183 | pOutputMediaType.Create(); |
---|
184 | pOutputMediaType[MF_MT_MAJOR_TYPE] = MFMediaType_Video; |
---|
185 | pOutputMediaType[MF_MT_SUBTYPE] = MFVideoFormat_IYUV; |
---|
186 | pOutputMediaType[MF_MT_FRAME_SIZE].SetSize(720, 480); |
---|
187 | pOutputMediaType[MF_MT_PIXEL_ASPECT_RATIO].SetRatio(1, 1); |
---|
188 | pOutputMediaType[MF_MT_INTERLACE_MODE] = (UINT32) MFVideoInterlace_Progressive; |
---|
189 | pOutputMediaType[MF_MT_FRAME_RATE].SetRatio(5, 1); |
---|
190 | pOutputMediaType[MF_MT_VIDEO_NOMINAL_RANGE] = (UINT32) MFNominalRange_Wide; |
---|
191 | __C(pTransform->SetOutputType(0, pOutputMediaType, 0)); |
---|
192 | |
---|
193 | MFT_INPUT_STREAM_INFO InputStreamInformation = { 0 }; |
---|
194 | __C(pTransform->GetInputStreamInfo(0, &InputStreamInformation)); |
---|
195 | MFT_OUTPUT_STREAM_INFO OutputStreamInformation = { 0 }; |
---|
196 | __C(pTransform->GetOutputStreamInfo(0, &OutputStreamInformation)); |
---|
197 | MF::CAttributes pAttributes; |
---|
198 | __C(pTransform->GetAttributes(&pAttributes)); |
---|
199 | pAttributes[MF_XVP_DISABLE_FRC] = (UINT32) 0; |
---|
200 | pAttributes[MF_VIDEO_PROCESSOR_ALGORITHM] = (UINT32) 0; |
---|
201 | pAttributes[MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT] = (UINT32) 6; |
---|
202 | pAttributes.Trace(); |
---|
203 | __C(pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0)); |
---|
204 | __C(pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0)); |
---|
205 | |
---|
206 | const LONGLONG nSampleDuration = 200 * 10000i64; |
---|
207 | |
---|
208 | ProcessOutput(pTransform, OutputStreamInformation, 1); |
---|
209 | ProcessInput(pTransform, InputStreamInformation, nSampleDuration, 0); |
---|
210 | ProcessOutput(pTransform, OutputStreamInformation); |
---|
211 | ProcessOutput(pTransform, OutputStreamInformation, 1); |
---|
212 | ProcessInput(pTransform, InputStreamInformation, nSampleDuration, 1); |
---|
213 | ProcessOutput(pTransform, OutputStreamInformation); |
---|
214 | |
---|
215 | // TODO: Termination/Cleanup |
---|
216 | } |
---|
217 | }; |
---|
218 | |
---|
219 | __declspec(selectany) CEvent CModule::g_TerminationEvent; |
---|
220 | |
---|