source: trunk/Utilities/DumpMediaSamples/DumpMediaSamples.cpp @ 937

Last change on this file since 937 was 283, checked in by roman, 8 years ago
  • Property svn:keywords set to Id
File size: 22.0 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2006-2012
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 <qedit.h>
10#include "rodshow.h"
11#include "Handler.h"
12
13#pragma region Re-Adding Removed from Windows SDK qedit.h
14
15struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
16ISampleGrabberCB : IUnknown
17{
18    //
19    // Raw methods provided by interface
20    //
21
22      virtual HRESULT __stdcall SampleCB (
23        double SampleTime,
24        struct IMediaSample * pSample ) = 0;
25      virtual HRESULT __stdcall BufferCB (
26        double SampleTime,
27        unsigned char * pBuffer,
28        long BufferLen ) = 0;
29};
30
31struct __declspec(uuid("6b652fff-11fe-4fce-92ad-0266b5d7c78f"))
32ISampleGrabber : IUnknown
33{
34    //
35    // Raw methods provided by interface
36    //
37
38      virtual HRESULT __stdcall SetOneShot (
39        long OneShot ) = 0;
40      virtual HRESULT __stdcall SetMediaType (
41        struct _AMMediaType * pType ) = 0;
42      virtual HRESULT __stdcall GetConnectedMediaType (
43        struct _AMMediaType * pType ) = 0;
44      virtual HRESULT __stdcall SetBufferSamples (
45        long BufferThem ) = 0;
46      virtual HRESULT __stdcall GetCurrentBuffer (
47        /*[in,out]*/ long * pBufferSize,
48        /*[out]*/ long * pBuffer ) = 0;
49      virtual HRESULT __stdcall GetCurrentSample (
50        /*[out,retval]*/ struct IMediaSample * * ppSample ) = 0;
51      virtual HRESULT __stdcall SetCallback (
52        struct ISampleGrabberCB * pCallback,
53        long WhichMethodToCallback ) = 0;
54};
55
56struct __declspec(uuid("c1f400a0-3f08-11d3-9f0b-006008039e37"))
57SampleGrabber;
58    // [ default ] interface ISampleGrabber
59
60#pragma endregion
61
62////////////////////////////////////////////////////////////
63// CFormatFlagHelper
64
65class CFormatFlagHelper
66{
67public:
68
69        ////////////////////////////////////////////////////
70        // FLAGNAME
71
72        typedef struct _FLAGNAME
73        {
74                DWORD nValue;
75                LPCTSTR pszName;
76        } FLAGNAME;
77
78public:
79// CFormatFlagHelper
80        static CString StringFromFlags(DWORD nValue, const FLAGNAME* pFlagNames, SIZE_T nFlagNameCount)
81        {
82                CString sText;
83                DWORD nKnownValues = 0;
84                for(SIZE_T nIndex = 0; nIndex < nFlagNameCount; nIndex++)
85                {
86                        nKnownValues |= pFlagNames[nIndex].nValue;
87                        if(!(nValue & pFlagNames[nIndex].nValue))
88                                continue;
89                        if(!sText.IsEmpty())
90                                sText.Append(_T(" | "));
91                        sText.Append(pFlagNames[nIndex].pszName);
92                }
93                DWORD nUnnamedValue = nValue & ~nKnownValues;
94                if(nUnnamedValue)
95                {
96                        if(!sText.IsEmpty())
97                                sText.Append(_T(" | "));
98                        sText.AppendFormat(_T("0x%08x"), nUnnamedValue);
99                }
100                return sText;
101        }
102        template <SIZE_T t_nCount>
103        static CString StringFromFlags(DWORD nValue, const FLAGNAME (&pFlagNames)[t_nCount])
104        {
105                return StringFromFlags(nValue, pFlagNames, t_nCount);
106        }
107        static CString StringFromTypeSpecificFlags(DWORD nValue)
108        {
109                static const FLAGNAME g_pNames[] =
110                {
111                        //{ AM_VIDEO_FLAG_FIELD_MASK
112                        //{ AM_VIDEO_FLAG_INTERLEAVED_FRAME
113                        { AM_VIDEO_FLAG_FIELD1, _T("AM_VIDEO_FLAG_FIELD1") },
114                        { AM_VIDEO_FLAG_FIELD2, _T("AM_VIDEO_FLAG_FIELD2") },
115                        { AM_VIDEO_FLAG_FIELD1FIRST, _T("AM_VIDEO_FLAG_FIELD1FIRST") },
116                        { AM_VIDEO_FLAG_WEAVE, _T("AM_VIDEO_FLAG_WEAVE") },
117                        //{ AM_VIDEO_FLAG_IPB_MASK
118                        //{ AM_VIDEO_FLAG_I_SAMPLE
119                        { AM_VIDEO_FLAG_P_SAMPLE, _T("AM_VIDEO_FLAG_P_SAMPLE") },
120                        { AM_VIDEO_FLAG_B_SAMPLE, _T("AM_VIDEO_FLAG_B_SAMPLE") },
121                        { AM_VIDEO_FLAG_REPEAT_FIELD, _T("AM_VIDEO_FLAG_REPEAT_FIELD") },
122                };
123                return StringFromFlags(nValue, g_pNames);
124        }
125        static CString StringFromSampleFlags(DWORD nValue)
126        {
127                static const FLAGNAME g_pNames[] =
128                {
129                        { AM_SAMPLE_SPLICEPOINT, _T("AM_SAMPLE_SPLICEPOINT") },
130                        { AM_SAMPLE_PREROLL, _T("AM_SAMPLE_PREROLL") },
131                        { AM_SAMPLE_DATADISCONTINUITY, _T("AM_SAMPLE_DATADISCONTINUITY") },
132                        { AM_SAMPLE_TYPECHANGED, _T("AM_SAMPLE_TYPECHANGED") },
133                        { AM_SAMPLE_TIMEVALID, _T("AM_SAMPLE_TIMEVALID") },
134                        { AM_SAMPLE_TIMEDISCONTINUITY, _T("AM_SAMPLE_TIMEDISCONTINUITY") },
135                        { AM_SAMPLE_FLUSH_ON_PAUSE, _T("AM_SAMPLE_FLUSH_ON_PAUSE") },
136                        { AM_SAMPLE_STOPVALID, _T("AM_SAMPLE_STOPVALID") },
137                        { AM_SAMPLE_ENDOFSTREAM, _T("AM_SAMPLE_ENDOFSTREAM") },
138                        //{ AM_STREAM_MEDIA
139                        //{ AM_STREAM_CONTROL
140                };
141                return StringFromFlags(nValue, g_pNames);
142        }
143};
144
145////////////////////////////////////////////////////////////
146// CModule
147
148class CModule :
149        public CAtlExeModuleT<CModule>
150{
151public:
152
153        ////////////////////////////////////////////////////////
154        // CSampleGrabberCallback
155
156        class ATL_NO_VTABLE CSampleGrabberCallback :
157                public CComObjectRootEx<CComMultiThreadModel>,
158                public ISampleGrabberCB,
159                public CFormatFlagHelper
160        {
161        public:
162
163        BEGIN_COM_MAP(CSampleGrabberCallback)
164                COM_INTERFACE_ENTRY(ISampleGrabberCB)
165        END_COM_MAP()
166
167        private:
168                CModule* m_pModule;
169                CString m_sName;
170                CString m_sNamePrefix;
171                mutable CRoCriticalSection m_DataCriticalSection;
172                CMediaType m_pMediaType;
173                CComPtr<CAbstractHandler> m_pHandler;
174                DWORD m_nPreviousFlags;
175                REFERENCE_TIME m_nPreviousStartTime;
176                REFERENCE_TIME m_nPreviousStopTime;
177
178        public:
179        // CSampleGrabberCallback
180                CSampleGrabberCallback() :
181                        m_pModule(NULL)
182                {
183                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
184                }
185                ~CSampleGrabberCallback()
186                {
187                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
188                }
189                VOID Initialize(CModule* pModule)
190                {
191                        _A(!m_pModule && pModule);
192                        m_pModule = pModule;
193                        m_nPreviousFlags = 0;
194                }
195                VOID SetName(const CString& sName)
196                {
197                        _A(m_sName.IsEmpty());
198                        m_sName = sName;
199                        m_sNamePrefix = AtlFormatString(_T("[%s] "), sName);
200                }
201                VOID SetMediaType(const AM_MEDIA_TYPE* pMediaType)
202                {
203                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
204                        PrintMediaType(pMediaType);
205                        m_pMediaType = pMediaType;
206                }
207                VOID PrintMediaType(const CMediaType& pMediaType)
208                {
209                        _tprintf(_T("%s") _T("Media Type:\n\n"), m_sNamePrefix);
210                        _tprintf(_T("majortype %ls, subtype %ls, pUnk 0x%08x\n"), _PersistHelper::StringFromIdentifier(pMediaType->majortype), _PersistHelper::StringFromIdentifier(pMediaType->subtype), (LONG) (LONG_PTR) pMediaType->pUnk);
211                        _tprintf(_T("bFixedSizeSamples %d, bTemporalCompression %d, lSampleSize %d\n"), pMediaType->bFixedSizeSamples, pMediaType->bTemporalCompression, pMediaType->lSampleSize);
212                        _tprintf(_T("formattype %ls, cbFormat %d, pbFormat 0x%08x\n"), _PersistHelper::StringFromIdentifier(pMediaType->formattype), pMediaType->cbFormat, (UINT) (UINT_PTR) pMediaType->pbFormat);
213                        if(pMediaType->formattype == FORMAT_VideoInfo)
214                        {
215                                const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) (pMediaType->pbFormat ? pMediaType->pbFormat : (BYTE*) (pMediaType + 1));
216                                _tprintf(_T("pbFormat as VIDEOINFOHEADER:\n"));
217                                _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);
218                                _tprintf(_T("  dwBitRate %d, dwBitErrorRate %d, AvgTimePerFrame %s\n"), pVideoInfoHeader->dwBitRate, pVideoInfoHeader->dwBitErrorRate, _FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame));
219                                _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));
220                                _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);
221                        } else
222                        if(pMediaType->formattype == FORMAT_VideoInfo2)
223                        {
224                                const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) (pMediaType->pbFormat ? pMediaType->pbFormat : (BYTE*) (pMediaType + 1));
225                                _tprintf(_T("pbFormat as VIDEOINFOHEADER2:\n"));
226                                _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);
227                                _tprintf(_T("  dwBitRate %d, dwBitErrorRate %d, AvgTimePerFrame %s\n"), pVideoInfoHeader2->dwBitRate, pVideoInfoHeader2->dwBitErrorRate, _FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame));
228                                _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);
229                                _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));
230                                _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);
231                        } else
232                        if(pMediaType->formattype == FORMAT_WaveFormatEx)
233                        {
234                                const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) (pMediaType->pbFormat ? pMediaType->pbFormat : (BYTE*) (pMediaType + 1));
235                                _tprintf(_T("pbFormat as WAVEFORMATEX:\n"));
236                                _tprintf(_T("  wFormatTag %d\n"), pWaveFormatEx->wFormatTag);
237                                _tprintf(_T("  nChannels %d\n"), pWaveFormatEx->nChannels);
238                                _tprintf(_T("  nSamplesPerSec %d\n"), pWaveFormatEx->nSamplesPerSec);
239                                _tprintf(_T("  nAvgBytesPerSec %d\n"), pWaveFormatEx->nAvgBytesPerSec);
240                                _tprintf(_T("  nBlockAlign %d\n"), pWaveFormatEx->nBlockAlign);
241                                _tprintf(_T("  wBitsPerSample %d\n"), pWaveFormatEx->wBitsPerSample);
242                                _tprintf(_T("  cbSize %d\n"), pWaveFormatEx->cbSize);
243                                if(pWaveFormatEx->cbSize > 0)
244                                {
245                                        const BYTE* pnExtraData = (const BYTE*) (pWaveFormatEx + 1);
246                                        const SIZE_T nExtraDataSize = pWaveFormatEx->cbSize;
247                                        for(SIZE_T nIndex1 = 0; nIndex1 < nExtraDataSize; nIndex1 += 0x10)
248                                        {
249                                                CString sText;
250                                                for(SIZE_T nIndex2 = nIndex1; nIndex2 < min(nIndex1 + 0x10, nExtraDataSize); nIndex2++)
251                                                        sText.AppendFormat(_T("%02X "), pnExtraData[nIndex2]);
252                                                sText.TrimRight(_T(" "));
253                                                _tprintf(_T("  pnExtraData[0x%04x] %s\n"), nIndex1, sText);
254                                        }
255                                }
256                        } else
257                                ;
258                        _tprintf(_T("\n"));
259                }
260                VOID SetHandler(CAbstractHandler* pHandler)
261                {
262                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
263                        m_pHandler = pHandler;
264                }
265
266        // ISampleGrabberCB
267        STDMETHOD(SampleCB)(DOUBLE fSampleTime, IMediaSample* pMediaSample)
268                {
269                        _A(pMediaSample);
270                        _ATLTRY
271                        {
272                                CMediaSampleProperties Properties(pMediaSample);
273                                _A(!Properties.pMediaType);
274                                CRoArrayT<CString> TimeArray;
275                                if(Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
276                                {
277                                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
278                                        TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStart));
279                                        if(m_nPreviousFlags & AM_SAMPLE_TIMEVALID)
280                                                TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStart - m_nPreviousStartTime));
281                                        else
282                                                TimeArray.Add(_T(""));
283                                        if(m_nPreviousFlags & AM_SAMPLE_STOPVALID)
284                                                TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStart - m_nPreviousStopTime));
285                                        else
286                                                TimeArray.Add(_T(""));
287                                        if(Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
288                                        {
289                                                TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStop));
290                                                TimeArray.Add(_FilterGraphHelper::FormatReferenceTime(Properties.tStop - Properties.tStart));
291                                        }
292                                }
293                                CRoCriticalSectionLock PrintLock(m_pModule->m_PrintCriticalSection);
294                                _tprintf(_T("%s") _T("fSampleTime %s, .dwTypeSpecificFlags 0x%08x%s, .dwSampleFlags 0x%08x%s, .tStart %s, .tStop %s, .dwStreamId %d\n"), 
295                                        m_sNamePrefix,
296                                        _StringHelper::FormatNumber(fSampleTime, 3),
297                                        Properties.dwTypeSpecificFlags, Properties.dwTypeSpecificFlags ? (LPCTSTR) AtlFormatString(_T(" (%s)"), StringFromTypeSpecificFlags(Properties.dwTypeSpecificFlags)) : _T(""),
298                                        Properties.dwSampleFlags, Properties.dwSampleFlags ? (LPCTSTR) AtlFormatString(_T(" (%s)"), StringFromSampleFlags(Properties.dwSampleFlags)) : _T(""),
299                                        _FilterGraphHelper::FormatReferenceTime(Properties.tStart), 
300                                        _FilterGraphHelper::FormatReferenceTime(Properties.tStop), 
301                                        Properties.dwStreamId,
302                                        0);
303                                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
304                                BOOL bBufferHandled = FALSE;
305                                if(!bBufferHandled)
306                                {
307                                        CString sBuffer;
308                                        static const SIZE_T g_nMaximalPrintSize = 48;
309                                        SIZE_T nIndex;
310                                        for(nIndex = 0; nIndex < (SIZE_T) Properties.lActual && nIndex < g_nMaximalPrintSize; nIndex++)
311                                                sBuffer.AppendFormat(_T("%02X "), Properties.pbBuffer[nIndex]);
312                                        UINT32 nBufferCheck = 0;
313                                        for(nIndex = 0; nIndex < (SIZE_T) Properties.lActual; nIndex++)
314                                                nBufferCheck += (UINT8) Properties.pbBuffer[nIndex];
315                                        if(nIndex > g_nMaximalPrintSize)
316                                                sBuffer.Append(_T("..."));
317                                        _tprintf(_T("%s") _T(".cbBuffer %d, .lActual %d, pbBuffer %s [0x%08X]\n"), 
318                                                m_sNamePrefix,
319                                                Properties.cbBuffer,
320                                                Properties.lActual,
321                                                sBuffer,
322                                                nBufferCheck,
323                                                0);
324                                }
325                                _tprintf(_T("%s") _T("Time, %s") _T("\n"),
326                                        m_sNamePrefix,
327                                        _StringHelper::Join(TimeArray, _T(", ")), 
328                                        0);
329                                if(m_pHandler)
330                                        m_pHandler->HandleSample(Properties);
331                                _tprintf(_T("\n"));
332                                m_nPreviousFlags = Properties.dwSampleFlags;
333                                m_nPreviousStartTime = Properties.tStart;
334                                m_nPreviousStopTime = Properties.tStop;
335
336                        }
337                        _ATLCATCH(Exception)
338                        {
339                                _C(Exception);
340                        }
341                        return S_OK;
342                }
343        STDMETHOD(BufferCB)(DOUBLE fSampleTime, BYTE* pnBuffer, LONG nBufferSize)
344                {
345                        return S_OK;
346                }
347        };
348
349private:
350
351public:
352        CPath m_sPath;
353        BOOL m_bNoReferenceClock;
354        BOOL m_bSuppressLoadFailure;
355        mutable CRoCriticalSection m_PrintCriticalSection;
356
357public:
358// CModule
359        static VOID LoadGraphBuilderFromFile(IGraphBuilder* pGraphBuilder, LPCTSTR pszPath)
360        {
361                _A(pGraphBuilder && pszPath);
362                CComQIPtr<IPersistStream> pPersistStream = pGraphBuilder;
363                __D(pPersistStream, E_NOINTERFACE);
364                CStringW sPathW(pszPath);
365                __C(StgIsStorageFile(sPathW));
366                CComPtr<IStorage> pStorage;
367                __C(StgOpenStorage(sPathW, 0, STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE, 0, 0, &pStorage));
368                CComPtr<IStream> pStream;
369                __C(pStorage->OpenStream(L"ActiveMovieGraph", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream));
370                __C(pPersistStream->Load(pStream));
371        }
372        static CPath GetDefaultPath()
373        {
374                TCHAR pszPath[MAX_PATH] = { 0 };
375                _W(GetModuleFileName(_AtlBaseModule.GetModuleInstance(), pszPath, DIM(pszPath)));
376                _W(RemoveFileSpec(pszPath));
377                _W(RemoveFileSpec(pszPath));
378                _W(Combine(pszPath, pszPath, _T("Debug.grf")));
379                return pszPath;
380        }
381        CModule()
382        {
383                //m_sPath = GetDefaultPath();
384                m_bNoReferenceClock = FALSE;
385                m_bSuppressLoadFailure = FALSE;
386        }
387        ~CModule()
388        {
389        }
390        HRESULT PreMessageLoop(INT nShowCommand)
391        {
392                __C(__super::PreMessageLoop(nShowCommand));
393                return S_OK;
394        }
395        VOID RunMessageLoop()
396        {
397                CGenericFilterGraph FilterGraph;
398                FilterGraph.CoCreateInstance();
399                _ATLTRY
400                {
401                        LoadGraphBuilderFromFile(FilterGraph.m_pFilterGraph, m_sPath);
402                }
403                _ATLCATCH(Exception)
404                {
405                        _tprintf(_T("Error loading filter graph: %s\n"), Ds::FormatResult(Exception));
406                        if(!m_bSuppressLoadFailure)
407                                _ATLRETHROW;
408                }
409                #pragma region Sample Grabbers
410                _FilterGraphHelper::CFilterArray FilterArray;
411                _FilterGraphHelper::GetGraphFilters(FilterGraph.m_pFilterGraph, FilterArray);
412                __D(!FilterArray.IsEmpty(), E_UNNAMED);
413                SIZE_T nSampleGrabberIndex = 0;
414                for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
415                {
416                        const CComQIPtr<ISampleGrabber> pSampleGrabber = FilterArray[nIndex];
417                        if(!pSampleGrabber)
418                                continue;
419                        CObjectPtr<CSampleGrabberCallback> pSampleGrabberCallback;
420                        pSampleGrabberCallback.Construct();
421                        pSampleGrabberCallback->Initialize(this);
422                        if(FilterArray.GetCount() > 1)
423                                pSampleGrabberCallback->SetName(AtlFormatString(_T("%c"), 'A' + nSampleGrabberIndex));
424                        __C(pSampleGrabber->SetCallback(pSampleGrabberCallback, 0));
425                        nSampleGrabberIndex++;
426                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(_FilterGraphHelper::GetFilterPin(CComQIPtr<IBaseFilter>(pSampleGrabber), PINDIR_INPUT));
427                        pSampleGrabberCallback->SetMediaType(pMediaType);
428                        //typedef CHdycInterlacingHandler CHandler;
429                        //CObjectPtr<CHandler> pHandler;
430                        //pHandler.Construct()->Initialize(pMediaType);
431                        //pSampleGrabberCallback->SetHandler(pHandler);
432                }
433                #pragma endregion
434                if(m_bNoReferenceClock)
435                        __C(FilterGraph.m_pMediaFilter->SetSyncSource(NULL));
436                _tprintf(_T("Media Samples:\n\n"));
437                __C(FilterGraph.m_pMediaControl->Run());
438                #pragma region Wait for Completion
439                #if TRUE
440                        const CComPtr<IMediaEventEx>& pMediaEvent = FilterGraph.m_pMediaEventEx;
441                        for(; ; )
442                        {
443                                // SUGG: Replace Sleep/GetMessage with MsgWaitForMultipleObjects/PeekMessage to wait for graph event and window messages
444                                static const ULONG g_nTimeout = 10;
445                                if(pMediaEvent)
446                                {
447                                        LONG nCompletionEventCode = 0;
448                                        const HRESULT nWaitForCompletionResult = pMediaEvent->WaitForCompletion(g_nTimeout, &nCompletionEventCode);
449                                        for(; ; )
450                                        {
451                                                LONG nEventCode = 0;
452                                                LONG_PTR nParameter1 = 0, nParameter2 = 0;
453                                                const HRESULT nGetEventResult = pMediaEvent->GetEvent(&nEventCode, &nParameter1, &nParameter2, 0);
454                                                if(nGetEventResult == E_ABORT)
455                                                        break;
456                                                __C(nGetEventResult);
457                                                _ATLTRY
458                                                {
459                                                        switch(nEventCode)
460                                                        {
461                                                        case EC_COMPLETE:
462                                                                _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);
463                                                                break;
464                                                        case EC_USERABORT:
465                                                                _tprintf(_T("Event: EC_USERABORT (0x%x), Parameter1 0x%08x, Parameter2 0x%08x\n"), nEventCode, nParameter1, nParameter2);
466                                                                break;
467                                                        case EC_ERRORABORT:
468                                                                _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);
469                                                                break;
470                                                        default:
471                                                                _tprintf(_T("Event: Code 0x%x, Parameter1 0x%08x, Parameter2 0x%08x\n"), nEventCode, nParameter1, nParameter2);
472                                                        }
473                                                }
474                                                _ATLCATCHALL()
475                                                {
476                                                        _V(pMediaEvent->FreeEventParams(nEventCode, nParameter1, nParameter2));
477                                                        _ATLRETHROW;
478                                                }
479                                                _V(pMediaEvent->FreeEventParams(nEventCode, nParameter1, nParameter2));
480                                        }
481                                        if(nWaitForCompletionResult != E_ABORT)
482                                        {
483                                                __C(nWaitForCompletionResult);
484                                                _tprintf(_T("\nCompleted: Event Code 0x%x\n"), nCompletionEventCode);
485                                                break;
486                                        }
487                                } else
488                                        Sleep(g_nTimeout);
489                                MSG Message;
490                                while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE))
491                                {
492                                        TranslateMessage(&Message);
493                                        DispatchMessage(&Message);
494                                }
495                        }
496                #else
497                        MSG Message;
498                        while(GetMessage(&Message, NULL, WM_NULL, WM_NULL) > 0)
499                        {
500                                TranslateMessage(&Message);
501                                DispatchMessage(&Message);
502                        }
503                #endif
504                #pragma endregion
505        }
506};
507
508////////////////////////////////////////////////////////////
509// Main
510
511int _tmain(int argc, _TCHAR* argv[])
512{
513        INT nResult = 0;
514        _ATLTRY
515        {
516                CModule Module;
517                #pragma region Parse Command Line
518                for(INT nIndex = 1; nIndex < argc; nIndex++)
519                {
520                        CString sArgument = argv[nIndex];
521                        _A(!sArgument.IsEmpty());
522                        #pragma region Switches
523                        if(_tcschr(_T("-/"), sArgument[0]))
524                        {
525                                sArgument.Delete(0);
526                                #pragma region Switch Value/Specification
527                                CString sArgumentValue;
528                                if(sArgument.GetLength() > 1)
529                                {
530                                        SIZE_T nIndex = 1;
531                                        if(sArgument[1] == _T(':'))
532                                                nIndex++;
533                                        sArgumentValue = (LPCTSTR) sArgument + nIndex;
534                                }
535                                INT nIntegerArgumentValue = 0;
536                                const BOOL bIntegerArgumentValueValid = !sArgumentValue.IsEmpty() ? AtlStringToInteger(sArgumentValue, nIntegerArgumentValue) : FALSE;
537                                #pragma endregion
538                                if(_tcschr(_T("Cc"), sArgument[0])) // No Reference Clock
539                                {
540                                        Module.m_bNoReferenceClock = TRUE;
541                                } else
542                                if(_tcschr(_T("Ee"), sArgument[0])) // Suppress Load Failure
543                                {
544                                        Module.m_bSuppressLoadFailure = TRUE;
545                                }
546                                continue;
547                        }
548                        #pragma endregion
549                        if(sArgument.GetLength() >= 2 && sArgument[0] == _T('"') && sArgument[sArgument.GetLength() - 1] == _T('"'))
550                                sArgument = sArgument.Mid(1, sArgument.GetLength() - 2);
551                        __D(!_tcslen(Module.m_sPath), E_UNNAMED);
552                        Module.m_sPath = (LPCTSTR) sArgument;
553                }
554                #pragma endregion
555                __D(_tcslen(Module.m_sPath), E_UNNAMED);
556                nResult = Module.WinMain(SW_SHOWNORMAL);
557        }
558        _ATLCATCH(Exception)
559        {
560                _tprintf(_T("Fatal: Error 0x%08x\n"), (HRESULT) Exception);
561        }
562        _ATLCATCHALL()
563        {
564                _tprintf(_T("Fatal: Fatal error\n"));
565        }
566        return nResult;
567}
568
569
Note: See TracBrowser for help on using the repository browser.