1 | //////////////////////////////////////////////////////////// |
---|
2 | // Copyright (C) Roman Ryltsov, 2006-2014 |
---|
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 "rodshow.h" |
---|
10 | |
---|
11 | //////////////////////////////////////////////////////////// |
---|
12 | // CFormatFlagHelper |
---|
13 | |
---|
14 | class CFormatFlagHelper |
---|
15 | { |
---|
16 | public: |
---|
17 | |
---|
18 | //////////////////////////////////////////////////// |
---|
19 | // FLAGNAME |
---|
20 | |
---|
21 | typedef struct _FLAGNAME |
---|
22 | { |
---|
23 | DWORD nValue; |
---|
24 | LPCTSTR pszName; |
---|
25 | } FLAGNAME; |
---|
26 | |
---|
27 | public: |
---|
28 | // CFormatFlagHelper |
---|
29 | static CString StringFromFlags(DWORD nValue, const FLAGNAME* pFlagNames, SIZE_T nFlagNameCount) |
---|
30 | { |
---|
31 | CString sText; |
---|
32 | DWORD nKnownValues = 0; |
---|
33 | for(SIZE_T nIndex = 0; nIndex < nFlagNameCount; nIndex++) |
---|
34 | { |
---|
35 | nKnownValues |= pFlagNames[nIndex].nValue; |
---|
36 | if(!(nValue & pFlagNames[nIndex].nValue)) |
---|
37 | continue; |
---|
38 | if(!sText.IsEmpty()) |
---|
39 | sText.Append(_T(" | ")); |
---|
40 | sText.Append(pFlagNames[nIndex].pszName); |
---|
41 | } |
---|
42 | DWORD nUnnamedValue = nValue & ~nKnownValues; |
---|
43 | if(nUnnamedValue) |
---|
44 | { |
---|
45 | if(!sText.IsEmpty()) |
---|
46 | sText.Append(_T(" | ")); |
---|
47 | sText.AppendFormat(_T("0x%08x"), nUnnamedValue); |
---|
48 | } |
---|
49 | return sText; |
---|
50 | } |
---|
51 | template <SIZE_T t_nCount> |
---|
52 | static CString StringFromFlags(DWORD nValue, const FLAGNAME (&pFlagNames)[t_nCount]) |
---|
53 | { |
---|
54 | return StringFromFlags(nValue, pFlagNames, t_nCount); |
---|
55 | } |
---|
56 | static CString StringFromTypeSpecificFlags(DWORD nValue) |
---|
57 | { |
---|
58 | static const FLAGNAME g_pNames[] = |
---|
59 | { |
---|
60 | //{ AM_VIDEO_FLAG_FIELD_MASK |
---|
61 | //{ AM_VIDEO_FLAG_INTERLEAVED_FRAME |
---|
62 | { AM_VIDEO_FLAG_FIELD1, _T("AM_VIDEO_FLAG_FIELD1") }, |
---|
63 | { AM_VIDEO_FLAG_FIELD2, _T("AM_VIDEO_FLAG_FIELD2") }, |
---|
64 | { AM_VIDEO_FLAG_FIELD1FIRST, _T("AM_VIDEO_FLAG_FIELD1FIRST") }, |
---|
65 | { AM_VIDEO_FLAG_WEAVE, _T("AM_VIDEO_FLAG_WEAVE") }, |
---|
66 | //{ AM_VIDEO_FLAG_IPB_MASK |
---|
67 | //{ AM_VIDEO_FLAG_I_SAMPLE |
---|
68 | { AM_VIDEO_FLAG_P_SAMPLE, _T("AM_VIDEO_FLAG_P_SAMPLE") }, |
---|
69 | { AM_VIDEO_FLAG_B_SAMPLE, _T("AM_VIDEO_FLAG_B_SAMPLE") }, |
---|
70 | { AM_VIDEO_FLAG_REPEAT_FIELD, _T("AM_VIDEO_FLAG_REPEAT_FIELD") }, |
---|
71 | }; |
---|
72 | return StringFromFlags(nValue, g_pNames); |
---|
73 | } |
---|
74 | static CString StringFromSampleFlags(DWORD nValue) |
---|
75 | { |
---|
76 | static const FLAGNAME g_pNames[] = |
---|
77 | { |
---|
78 | { AM_SAMPLE_SPLICEPOINT, _T("AM_SAMPLE_SPLICEPOINT") }, |
---|
79 | { AM_SAMPLE_PREROLL, _T("AM_SAMPLE_PREROLL") }, |
---|
80 | { AM_SAMPLE_DATADISCONTINUITY, _T("AM_SAMPLE_DATADISCONTINUITY") }, |
---|
81 | { AM_SAMPLE_TYPECHANGED, _T("AM_SAMPLE_TYPECHANGED") }, |
---|
82 | { AM_SAMPLE_TIMEVALID, _T("AM_SAMPLE_TIMEVALID") }, |
---|
83 | { AM_SAMPLE_TIMEDISCONTINUITY, _T("AM_SAMPLE_TIMEDISCONTINUITY") }, |
---|
84 | { AM_SAMPLE_FLUSH_ON_PAUSE, _T("AM_SAMPLE_FLUSH_ON_PAUSE") }, |
---|
85 | { AM_SAMPLE_STOPVALID, _T("AM_SAMPLE_STOPVALID") }, |
---|
86 | { AM_SAMPLE_ENDOFSTREAM, _T("AM_SAMPLE_ENDOFSTREAM") }, |
---|
87 | //{ AM_STREAM_MEDIA |
---|
88 | //{ AM_STREAM_CONTROL |
---|
89 | }; |
---|
90 | return StringFromFlags(nValue, g_pNames); |
---|
91 | } |
---|
92 | }; |
---|
93 | |
---|
94 | //////////////////////////////////////////////////////////// |
---|
95 | // CModule |
---|
96 | |
---|
97 | class CModule : |
---|
98 | public CAtlExeModuleT<CModule> |
---|
99 | { |
---|
100 | public: |
---|
101 | |
---|
102 | //////////////////////////////////////////////////////// |
---|
103 | // CSampleGrabberCallback |
---|
104 | |
---|
105 | class ATL_NO_VTABLE CSampleGrabberCallback : |
---|
106 | public CComObjectRootEx<CComMultiThreadModel>, |
---|
107 | public ISampleGrabberCB, |
---|
108 | public CFormatFlagHelper |
---|
109 | { |
---|
110 | public: |
---|
111 | |
---|
112 | BEGIN_COM_MAP(CSampleGrabberCallback) |
---|
113 | COM_INTERFACE_ENTRY(ISampleGrabberCB) |
---|
114 | END_COM_MAP() |
---|
115 | |
---|
116 | private: |
---|
117 | CModule* m_pModule; |
---|
118 | CString m_sName; |
---|
119 | CString m_sNamePrefix; |
---|
120 | mutable CRoCriticalSection m_DataCriticalSection; |
---|
121 | CMediaType m_pMediaType; |
---|
122 | CComPtr<CAbstractHandler> m_pHandler; |
---|
123 | DWORD m_nPreviousFlags; |
---|
124 | REFERENCE_TIME m_nPreviousStartTime; |
---|
125 | REFERENCE_TIME m_nPreviousStopTime; |
---|
126 | |
---|
127 | public: |
---|
128 | // CSampleGrabberCallback |
---|
129 | CSampleGrabberCallback() : |
---|
130 | m_pModule(NULL) |
---|
131 | { |
---|
132 | _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this); |
---|
133 | } |
---|
134 | ~CSampleGrabberCallback() |
---|
135 | { |
---|
136 | _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this); |
---|
137 | } |
---|
138 | VOID Initialize(CModule* pModule) |
---|
139 | { |
---|
140 | _A(!m_pModule && pModule); |
---|
141 | m_pModule = pModule; |
---|
142 | m_nPreviousFlags = 0; |
---|
143 | } |
---|
144 | VOID SetName(const CString& sName) |
---|
145 | { |
---|
146 | _A(m_sName.IsEmpty()); |
---|
147 | m_sName = sName; |
---|
148 | m_sNamePrefix = AtlFormatString(_T("[%s] "), sName); |
---|
149 | } |
---|
150 | VOID SetMediaType(const AM_MEDIA_TYPE* pMediaType) |
---|
151 | { |
---|
152 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
153 | PrintMediaType(pMediaType); |
---|
154 | m_pMediaType = pMediaType; |
---|
155 | } |
---|
156 | VOID PrintMediaType(const CMediaType& pMediaType) |
---|
157 | { |
---|
158 | _tprintf(_T("%s") _T("Media Type:\n\n"), m_sNamePrefix); |
---|
159 | _tprintf(_T("majortype %ls, subtype %ls, pUnk 0x%08x\n"), _PersistHelper::StringFromIdentifier(pMediaType->majortype), _PersistHelper::StringFromIdentifier(pMediaType->subtype), (LONG) (LONG_PTR) pMediaType->pUnk); |
---|
160 | _tprintf(_T("bFixedSizeSamples %d, bTemporalCompression %d, lSampleSize %d\n"), pMediaType->bFixedSizeSamples, pMediaType->bTemporalCompression, pMediaType->lSampleSize); |
---|
161 | _tprintf(_T("formattype %ls, cbFormat %d, pbFormat 0x%08x\n"), _PersistHelper::StringFromIdentifier(pMediaType->formattype), pMediaType->cbFormat, (UINT) (UINT_PTR) pMediaType->pbFormat); |
---|
162 | if(pMediaType->formattype == FORMAT_VideoInfo) |
---|
163 | { |
---|
164 | const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) (pMediaType->pbFormat ? pMediaType->pbFormat : (BYTE*) (pMediaType + 1)); |
---|
165 | _tprintf(_T("pbFormat as VIDEOINFOHEADER:\n")); |
---|
166 | _tprintf(_T(" rcSource { %d, %d, %d, %d ), rcTarget { %d, %d, %d, %d }\n"), pVideoInfoHeader->rcSource.left, pVideoInfoHeader->rcSource.top, pVideoInfoHeader->rcSource.right, pVideoInfoHeader->rcSource.bottom, pVideoInfoHeader->rcTarget.left, pVideoInfoHeader->rcTarget.top, pVideoInfoHeader->rcTarget.right, pVideoInfoHeader->rcTarget.bottom); |
---|
167 | _tprintf(_T(" dwBitRate %d, dwBitErrorRate %d, AvgTimePerFrame %s\n"), pVideoInfoHeader->dwBitRate, pVideoInfoHeader->dwBitErrorRate, _FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame)); |
---|
168 | _tprintf(_T(" bmiHeader.biSize %d, bmiHeader.biWidth %d, bmiHeader.biHeight %d, bmiHeader.biPlanes %d, bmiHeader.biBitCount %d, bmiHeader.biCompression %s\n"), pVideoInfoHeader->bmiHeader.biSize, pVideoInfoHeader->bmiHeader.biWidth, pVideoInfoHeader->bmiHeader.biHeight, pVideoInfoHeader->bmiHeader.biPlanes, pVideoInfoHeader->bmiHeader.biBitCount, _FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader->bmiHeader.biCompression)); |
---|
169 | _tprintf(_T(" bmiHeader.biSizeImage %d, bmiHeader.biXPelsPerMeter %d, bmiHeader.biYPelsPerMeter %d, bmiHeader.biClrUsed %d, bmiHeader.biClrImportant %d\n"), pVideoInfoHeader->bmiHeader.biSizeImage, pVideoInfoHeader->bmiHeader.biXPelsPerMeter, pVideoInfoHeader->bmiHeader.biYPelsPerMeter, pVideoInfoHeader->bmiHeader.biClrUsed, pVideoInfoHeader->bmiHeader.biClrImportant); |
---|
170 | } else |
---|
171 | if(pMediaType->formattype == FORMAT_VideoInfo2) |
---|
172 | { |
---|
173 | const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) (pMediaType->pbFormat ? pMediaType->pbFormat : (BYTE*) (pMediaType + 1)); |
---|
174 | _tprintf(_T("pbFormat as VIDEOINFOHEADER2:\n")); |
---|
175 | _tprintf(_T(" rcSource { %d, %d, %d, %d ), rcTarget { %d, %d, %d, %d }\n"), pVideoInfoHeader2->rcSource.left, pVideoInfoHeader2->rcSource.top, pVideoInfoHeader2->rcSource.right, pVideoInfoHeader2->rcSource.bottom, pVideoInfoHeader2->rcTarget.left, pVideoInfoHeader2->rcTarget.top, pVideoInfoHeader2->rcTarget.right, pVideoInfoHeader2->rcTarget.bottom); |
---|
176 | _tprintf(_T(" dwBitRate %d, dwBitErrorRate %d, AvgTimePerFrame %s\n"), pVideoInfoHeader2->dwBitRate, pVideoInfoHeader2->dwBitErrorRate, _FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame)); |
---|
177 | _tprintf(_T(" dwInterlaceFlags 0x%x, dwCopyProtectFlags 0x%x, dwPictAspectRatioX %d, dwPictAspectRatioY %d, dwControlFlags 0x%x\n"), pVideoInfoHeader2->dwInterlaceFlags, pVideoInfoHeader2->dwCopyProtectFlags, pVideoInfoHeader2->dwPictAspectRatioX, pVideoInfoHeader2->dwPictAspectRatioY, pVideoInfoHeader2->dwControlFlags); |
---|
178 | _tprintf(_T(" bmiHeader.biSize %d, bmiHeader.biWidth %d, bmiHeader.biHeight %d, bmiHeader.biPlanes %d, bmiHeader.biBitCount %d, bmiHeader.biCompression %s\n"), pVideoInfoHeader2->bmiHeader.biSize, pVideoInfoHeader2->bmiHeader.biWidth, pVideoInfoHeader2->bmiHeader.biHeight, pVideoInfoHeader2->bmiHeader.biPlanes, pVideoInfoHeader2->bmiHeader.biBitCount, _FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader2->bmiHeader.biCompression)); |
---|
179 | _tprintf(_T(" bmiHeader.biSizeImage %d, bmiHeader.biXPelsPerMeter %d, bmiHeader.biYPelsPerMeter %d, bmiHeader.biClrUsed %d, bmiHeader.biClrImportant %d\n"), pVideoInfoHeader2->bmiHeader.biSizeImage, pVideoInfoHeader2->bmiHeader.biXPelsPerMeter, pVideoInfoHeader2->bmiHeader.biYPelsPerMeter, pVideoInfoHeader2->bmiHeader.biClrUsed, pVideoInfoHeader2->bmiHeader.biClrImportant); |
---|
180 | } else |
---|
181 | if(pMediaType->formattype == FORMAT_WaveFormatEx) |
---|
182 | { |
---|
183 | const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) (pMediaType->pbFormat ? pMediaType->pbFormat : (BYTE*) (pMediaType + 1)); |
---|
184 | _tprintf(_T("pbFormat as WAVEFORMATEX:\n")); |
---|
185 | _tprintf(_T(" wFormatTag %d\n"), pWaveFormatEx->wFormatTag); |
---|
186 | _tprintf(_T(" nChannels %d\n"), pWaveFormatEx->nChannels); |
---|
187 | _tprintf(_T(" nSamplesPerSec %d\n"), pWaveFormatEx->nSamplesPerSec); |
---|
188 | _tprintf(_T(" nAvgBytesPerSec %d\n"), pWaveFormatEx->nAvgBytesPerSec); |
---|
189 | _tprintf(_T(" nBlockAlign %d\n"), pWaveFormatEx->nBlockAlign); |
---|
190 | _tprintf(_T(" wBitsPerSample %d\n"), pWaveFormatEx->wBitsPerSample); |
---|
191 | _tprintf(_T(" cbSize %d\n"), pWaveFormatEx->cbSize); |
---|
192 | if(pWaveFormatEx->cbSize > 0) |
---|
193 | { |
---|
194 | const BYTE* pnExtraData = (const BYTE*) (pWaveFormatEx + 1); |
---|
195 | const SIZE_T nExtraDataSize = pWaveFormatEx->cbSize; |
---|
196 | for(SIZE_T nIndex1 = 0; nIndex1 < nExtraDataSize; nIndex1 += 0x10) |
---|
197 | { |
---|
198 | CString sText; |
---|
199 | for(SIZE_T nIndex2 = nIndex1; nIndex2 < min(nIndex1 + 0x10, nExtraDataSize); nIndex2++) |
---|
200 | sText.AppendFormat(_T("%02X "), pnExtraData[nIndex2]); |
---|
201 | sText.TrimRight(_T(" ")); |
---|
202 | _tprintf(_T(" pnExtraData[0x%04x] %s\n"), nIndex1, sText); |
---|
203 | } |
---|
204 | } |
---|
205 | } else |
---|
206 | ; |
---|
207 | _tprintf(_T("\n")); |
---|
208 | } |
---|
209 | VOID SetHandler(CAbstractHandler* pHandler) |
---|
210 | { |
---|
211 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
212 | m_pHandler = pHandler; |
---|
213 | } |
---|
214 | |
---|
215 | // ISampleGrabberCB |
---|
216 | STDMETHOD(SampleCB)(DOUBLE fSampleTime, IMediaSample* pMediaSample) |
---|
217 | { |
---|
218 | _A(pMediaSample); |
---|
219 | _ATLTRY |
---|
220 | { |
---|
221 | CMediaSampleProperties Properties(pMediaSample); |
---|
222 | _A(!Properties.pMediaType); |
---|
223 | CRoArrayT<CString> TimeArray; |
---|
224 | if(Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID) |
---|
225 | { |
---|
226 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
227 | TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStart)); |
---|
228 | if(m_nPreviousFlags & AM_SAMPLE_TIMEVALID) |
---|
229 | TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStart - m_nPreviousStartTime)); |
---|
230 | else |
---|
231 | TimeArray.Add(_T("")); |
---|
232 | if(m_nPreviousFlags & AM_SAMPLE_STOPVALID) |
---|
233 | TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStart - m_nPreviousStopTime)); |
---|
234 | else |
---|
235 | TimeArray.Add(_T("")); |
---|
236 | if(Properties.dwSampleFlags & AM_SAMPLE_STOPVALID) |
---|
237 | { |
---|
238 | TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStop)); |
---|
239 | TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStop - Properties.tStart)); |
---|
240 | } |
---|
241 | } |
---|
242 | CRoCriticalSectionLock PrintLock(m_pModule->m_PrintCriticalSection); |
---|
243 | _tprintf(_T("%s") _T("fSampleTime %s, .dwTypeSpecificFlags 0x%08x%s, .dwSampleFlags 0x%08x%s, .tStart %s, .tStop %s, .dwStreamId %d\n"), |
---|
244 | m_sNamePrefix, |
---|
245 | _StringHelper::FormatNumber(fSampleTime, 3), |
---|
246 | Properties.dwTypeSpecificFlags, Properties.dwTypeSpecificFlags ? (LPCTSTR) AtlFormatString(_T(" (%s)"), StringFromTypeSpecificFlags(Properties.dwTypeSpecificFlags)) : _T(""), |
---|
247 | Properties.dwSampleFlags, Properties.dwSampleFlags ? (LPCTSTR) AtlFormatString(_T(" (%s)"), StringFromSampleFlags(Properties.dwSampleFlags)) : _T(""), |
---|
248 | _FilterGraphHelper::FormatReferenceTime(Properties.tStart), |
---|
249 | _FilterGraphHelper::FormatReferenceTime(Properties.tStop), |
---|
250 | Properties.dwStreamId, |
---|
251 | 0); |
---|
252 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
253 | BOOL bBufferHandled = FALSE; |
---|
254 | if(TRUE && !bBufferHandled) |
---|
255 | { |
---|
256 | CString sBuffer; |
---|
257 | static const SIZE_T g_nMaximalPrintSize = 48; |
---|
258 | SIZE_T nIndex; |
---|
259 | for(nIndex = 0; nIndex < (SIZE_T) Properties.lActual && nIndex < g_nMaximalPrintSize; nIndex++) |
---|
260 | sBuffer.AppendFormat(_T("%02X "), Properties.pbBuffer[nIndex]); |
---|
261 | UINT32 nBufferCheck = 0; |
---|
262 | for(nIndex = 0; nIndex < (SIZE_T) Properties.lActual; nIndex++) |
---|
263 | nBufferCheck += (UINT8) Properties.pbBuffer[nIndex]; |
---|
264 | if(nIndex > g_nMaximalPrintSize) |
---|
265 | sBuffer.Append(_T("...")); |
---|
266 | _tprintf(_T("%s") _T(".cbBuffer %d, .lActual %d, pbBuffer %s [0x%08X]\n"), |
---|
267 | m_sNamePrefix, |
---|
268 | Properties.cbBuffer, |
---|
269 | Properties.lActual, |
---|
270 | sBuffer, |
---|
271 | nBufferCheck, |
---|
272 | 0); |
---|
273 | } |
---|
274 | if(!TRUE && !bBufferHandled) |
---|
275 | { |
---|
276 | _tprintf(_T("%s") _T(".cbBuffer %d, .lActual %d\n"), |
---|
277 | m_sNamePrefix, |
---|
278 | Properties.cbBuffer, |
---|
279 | Properties.lActual, |
---|
280 | 0); |
---|
281 | for(LONG nIndex = 0; nIndex < Properties.lActual; nIndex += 0x0010) |
---|
282 | { |
---|
283 | _tprintf(_T("%s") _T("%06X: %s\n"), |
---|
284 | m_sNamePrefix, |
---|
285 | nIndex, |
---|
286 | AtlFormatData(Properties.pbBuffer + nIndex, min(Properties.lActual - nIndex, 0x0010)), |
---|
287 | 0); |
---|
288 | } |
---|
289 | } |
---|
290 | _tprintf(_T("%s") _T("Time, %s") _T("\n"), |
---|
291 | m_sNamePrefix, |
---|
292 | _StringHelper::Join(TimeArray, _T(", ")), |
---|
293 | 0); |
---|
294 | if(m_pHandler) |
---|
295 | m_pHandler->HandleSample(Properties); |
---|
296 | _tprintf(_T("\n")); |
---|
297 | m_nPreviousFlags = Properties.dwSampleFlags; |
---|
298 | m_nPreviousStartTime = Properties.tStart; |
---|
299 | m_nPreviousStopTime = Properties.tStop; |
---|
300 | } |
---|
301 | _ATLCATCH(Exception) |
---|
302 | { |
---|
303 | _C(Exception); |
---|
304 | } |
---|
305 | return S_OK; |
---|
306 | } |
---|
307 | STDMETHOD(BufferCB)(DOUBLE fSampleTime, BYTE* pnBuffer, LONG nBufferSize) |
---|
308 | { |
---|
309 | return S_OK; |
---|
310 | } |
---|
311 | }; |
---|
312 | |
---|
313 | private: |
---|
314 | |
---|
315 | public: |
---|
316 | CPath m_sPath; |
---|
317 | BOOL m_bNoReferenceClock; |
---|
318 | BOOL m_bSuppressLoadFailure; |
---|
319 | mutable CRoCriticalSection m_PrintCriticalSection; |
---|
320 | |
---|
321 | public: |
---|
322 | // CModule |
---|
323 | static VOID LoadGraphBuilderFromFile(IGraphBuilder* pGraphBuilder, LPCTSTR pszPath) |
---|
324 | { |
---|
325 | _A(pGraphBuilder && pszPath); |
---|
326 | CComQIPtr<IPersistStream> pPersistStream = pGraphBuilder; |
---|
327 | __D(pPersistStream, E_NOINTERFACE); |
---|
328 | CStringW sPathW(pszPath); |
---|
329 | __C(StgIsStorageFile(sPathW)); |
---|
330 | CComPtr<IStorage> pStorage; |
---|
331 | __C(StgOpenStorage(sPathW, 0, STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE, 0, 0, &pStorage)); |
---|
332 | CComPtr<IStream> pStream; |
---|
333 | __C(pStorage->OpenStream(L"ActiveMovieGraph", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream)); |
---|
334 | __C(pPersistStream->Load(pStream)); |
---|
335 | } |
---|
336 | static CPath GetDefaultPath() |
---|
337 | { |
---|
338 | TCHAR pszPath[MAX_PATH] = { 0 }; |
---|
339 | _W(GetModuleFileName(_AtlBaseModule.GetModuleInstance(), pszPath, DIM(pszPath))); |
---|
340 | _W(RemoveFileSpec(pszPath)); |
---|
341 | _W(RemoveFileSpec(pszPath)); |
---|
342 | _W(Combine(pszPath, pszPath, _T("Debug.grf"))); |
---|
343 | return pszPath; |
---|
344 | } |
---|
345 | CModule() |
---|
346 | { |
---|
347 | //m_sPath = GetDefaultPath(); |
---|
348 | m_bNoReferenceClock = FALSE; |
---|
349 | m_bSuppressLoadFailure = FALSE; |
---|
350 | } |
---|
351 | ~CModule() |
---|
352 | { |
---|
353 | } |
---|
354 | HRESULT PreMessageLoop(INT nShowCommand) |
---|
355 | { |
---|
356 | __C(__super::PreMessageLoop(nShowCommand)); |
---|
357 | return S_OK; |
---|
358 | } |
---|
359 | VOID RunMessageLoop() |
---|
360 | { |
---|
361 | CGenericFilterGraph FilterGraph; |
---|
362 | FilterGraph.CoCreateInstance(); |
---|
363 | _ATLTRY |
---|
364 | { |
---|
365 | LoadGraphBuilderFromFile(FilterGraph.m_pFilterGraph, m_sPath); |
---|
366 | } |
---|
367 | _ATLCATCH(Exception) |
---|
368 | { |
---|
369 | _tprintf(_T("Error loading filter graph: %s\n"), Ds::FormatResult(Exception)); |
---|
370 | if(!m_bSuppressLoadFailure) |
---|
371 | _ATLRETHROW; |
---|
372 | } |
---|
373 | #pragma region Sample Grabbers |
---|
374 | _FilterGraphHelper::CFilterArray FilterArray; |
---|
375 | _FilterGraphHelper::GetGraphFilters(FilterGraph.m_pFilterGraph, FilterArray); |
---|
376 | __D(!FilterArray.IsEmpty(), E_UNNAMED); |
---|
377 | SIZE_T nSampleGrabberIndex = 0; |
---|
378 | for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++) |
---|
379 | { |
---|
380 | const CComQIPtr<ISampleGrabber> pSampleGrabber = FilterArray[nIndex]; |
---|
381 | if(!pSampleGrabber) |
---|
382 | continue; |
---|
383 | CObjectPtr<CSampleGrabberCallback> pSampleGrabberCallback; |
---|
384 | pSampleGrabberCallback.Construct(); |
---|
385 | pSampleGrabberCallback->Initialize(this); |
---|
386 | if(FilterArray.GetCount() > 1) |
---|
387 | pSampleGrabberCallback->SetName(AtlFormatString(_T("%c"), 'A' + nSampleGrabberIndex)); |
---|
388 | __C(pSampleGrabber->SetCallback(pSampleGrabberCallback, 0)); |
---|
389 | nSampleGrabberIndex++; |
---|
390 | const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(_FilterGraphHelper::GetFilterPin(CComQIPtr<IBaseFilter>(pSampleGrabber), PINDIR_INPUT)); |
---|
391 | pSampleGrabberCallback->SetMediaType(pMediaType); |
---|
392 | //typedef CHdycInterlacingHandler CHandler; |
---|
393 | //CObjectPtr<CHandler> pHandler; |
---|
394 | //pHandler.Construct()->Initialize(pMediaType); |
---|
395 | //pSampleGrabberCallback->SetHandler(pHandler); |
---|
396 | } |
---|
397 | #pragma endregion |
---|
398 | if(m_bNoReferenceClock) |
---|
399 | __C(FilterGraph.m_pMediaFilter->SetSyncSource(NULL)); |
---|
400 | _tprintf(_T("Media Samples:\n\n")); |
---|
401 | __C(FilterGraph.m_pMediaControl->Run()); |
---|
402 | #pragma region Wait for Completion |
---|
403 | #if TRUE |
---|
404 | const CComPtr<IMediaEventEx>& pMediaEvent = FilterGraph.m_pMediaEventEx; |
---|
405 | for(; ; ) |
---|
406 | { |
---|
407 | // SUGG: Replace Sleep/GetMessage with MsgWaitForMultipleObjects/PeekMessage to wait for graph event and window messages |
---|
408 | static const ULONG g_nTimeout = 10; |
---|
409 | if(pMediaEvent) |
---|
410 | { |
---|
411 | LONG nCompletionEventCode = 0; |
---|
412 | const HRESULT nWaitForCompletionResult = pMediaEvent->WaitForCompletion(g_nTimeout, &nCompletionEventCode); |
---|
413 | for(; ; ) |
---|
414 | { |
---|
415 | LONG nEventCode = 0; |
---|
416 | LONG_PTR nParameter1 = 0, nParameter2 = 0; |
---|
417 | const HRESULT nGetEventResult = pMediaEvent->GetEvent(&nEventCode, &nParameter1, &nParameter2, 0); |
---|
418 | if(nGetEventResult == E_ABORT) |
---|
419 | break; |
---|
420 | __C(nGetEventResult); |
---|
421 | _ATLTRY |
---|
422 | { |
---|
423 | switch(nEventCode) |
---|
424 | { |
---|
425 | case EC_COMPLETE: |
---|
426 | _tprintf(_T("Event: EC_COMPLETE (0x%x), Error Code 0x%08x (%s), Parameter2 0x%08x\n"), nEventCode, (HRESULT) nParameter1, AtlFormatSystemMessage((HRESULT) nParameter1).TrimRight(_T("\t\n\r .")), nParameter2); |
---|
427 | break; |
---|
428 | case EC_USERABORT: |
---|
429 | _tprintf(_T("Event: EC_USERABORT (0x%x), Parameter1 0x%08x, Parameter2 0x%08x\n"), nEventCode, nParameter1, nParameter2); |
---|
430 | break; |
---|
431 | case EC_ERRORABORT: |
---|
432 | _tprintf(_T("Event: EC_ERRORABORT (0x%x), Error Code 0x%08x (%s), Parameter2 0x%08x\n"), nEventCode, nParameter1, AtlFormatSystemMessage((HRESULT) nParameter1).TrimRight(_T("\t\n\r .")), nParameter2); |
---|
433 | break; |
---|
434 | default: |
---|
435 | _tprintf(_T("Event: Code %s, Parameter1 0x%08x, Parameter2 0x%08x\n"), _FilterGraphHelper::FormatEventCode(nEventCode), nParameter1, nParameter2); |
---|
436 | } |
---|
437 | } |
---|
438 | _ATLCATCHALL() |
---|
439 | { |
---|
440 | _V(pMediaEvent->FreeEventParams(nEventCode, nParameter1, nParameter2)); |
---|
441 | _ATLRETHROW; |
---|
442 | } |
---|
443 | _V(pMediaEvent->FreeEventParams(nEventCode, nParameter1, nParameter2)); |
---|
444 | } |
---|
445 | if(nWaitForCompletionResult != E_ABORT) |
---|
446 | { |
---|
447 | __C(nWaitForCompletionResult); |
---|
448 | _tprintf(_T("\nCompleted: Event Code 0x%x\n"), nCompletionEventCode); |
---|
449 | break; |
---|
450 | } |
---|
451 | } else |
---|
452 | Sleep(g_nTimeout); |
---|
453 | MSG Message; |
---|
454 | while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE)) |
---|
455 | { |
---|
456 | TranslateMessage(&Message); |
---|
457 | DispatchMessage(&Message); |
---|
458 | } |
---|
459 | } |
---|
460 | #else |
---|
461 | MSG Message; |
---|
462 | while(GetMessage(&Message, NULL, WM_NULL, WM_NULL) > 0) |
---|
463 | { |
---|
464 | TranslateMessage(&Message); |
---|
465 | DispatchMessage(&Message); |
---|
466 | } |
---|
467 | #endif |
---|
468 | #pragma endregion |
---|
469 | } |
---|
470 | }; |
---|
471 | |
---|