[142] | 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" |
---|
[152] | 11 | #include "Handler.h" |
---|
[142] | 12 | |
---|
| 13 | #pragma region Re-Adding Removed from Windows SDK qedit.h |
---|
| 14 | |
---|
| 15 | struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85")) |
---|
| 16 | ISampleGrabberCB : 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 | |
---|
| 31 | struct __declspec(uuid("6b652fff-11fe-4fce-92ad-0266b5d7c78f")) |
---|
| 32 | ISampleGrabber : 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 | |
---|
| 56 | struct __declspec(uuid("c1f400a0-3f08-11d3-9f0b-006008039e37")) |
---|
| 57 | SampleGrabber; |
---|
| 58 | // [ default ] interface ISampleGrabber |
---|
| 59 | |
---|
| 60 | #pragma endregion |
---|
| 61 | |
---|
| 62 | //////////////////////////////////////////////////////////// |
---|
| 63 | // CFormatFlagHelper |
---|
| 64 | |
---|
| 65 | class CFormatFlagHelper |
---|
| 66 | { |
---|
| 67 | public: |
---|
| 68 | |
---|
| 69 | //////////////////////////////////////////////////// |
---|
| 70 | // FLAGNAME |
---|
| 71 | |
---|
| 72 | typedef struct _FLAGNAME |
---|
| 73 | { |
---|
| 74 | DWORD nValue; |
---|
| 75 | LPCTSTR pszName; |
---|
| 76 | } FLAGNAME; |
---|
| 77 | |
---|
| 78 | public: |
---|
| 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 | |
---|
| 148 | class CModule : |
---|
| 149 | public CAtlExeModuleT<CModule> |
---|
| 150 | { |
---|
| 151 | public: |
---|
| 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: |
---|
[143] | 168 | CModule* m_pModule; |
---|
[142] | 169 | CString m_sName; |
---|
| 170 | CString m_sNamePrefix; |
---|
| 171 | mutable CRoCriticalSection m_DataCriticalSection; |
---|
| 172 | CMediaType m_pMediaType; |
---|
[152] | 173 | CComPtr<CAbstractHandler> m_pHandler; |
---|
[217] | 174 | DWORD m_nPreviousFlags; |
---|
| 175 | REFERENCE_TIME m_nPreviousStartTime; |
---|
| 176 | REFERENCE_TIME m_nPreviousStopTime; |
---|
[142] | 177 | |
---|
| 178 | public: |
---|
| 179 | // CSampleGrabberCallback |
---|
[143] | 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; |
---|
[217] | 193 | m_nPreviousFlags = 0; |
---|
[143] | 194 | } |
---|
[142] | 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 | } |
---|
[143] | 207 | VOID PrintMediaType(const CMediaType& pMediaType) |
---|
[142] | 208 | { |
---|
[143] | 209 | _tprintf(_T("%s") _T("Media Type:\n\n"), m_sNamePrefix); |
---|
[142] | 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 | } |
---|
[152] | 260 | VOID SetHandler(CAbstractHandler* pHandler) |
---|
| 261 | { |
---|
| 262 | CRoCriticalSectionLock DataLock(m_DataCriticalSection); |
---|
| 263 | m_pHandler = pHandler; |
---|
| 264 | } |
---|
[142] | 265 | |
---|
| 266 | // ISampleGrabberCB |
---|
[143] | 267 | STDMETHOD(SampleCB)(DOUBLE fSampleTime, IMediaSample* pMediaSample) |
---|
[142] | 268 | { |
---|
| 269 | _A(pMediaSample); |
---|
| 270 | _ATLTRY |
---|
| 271 | { |
---|
| 272 | CMediaSampleProperties Properties(pMediaSample); |
---|
| 273 | _A(!Properties.pMediaType); |
---|
[217] | 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 | } |
---|
[143] | 293 | CRoCriticalSectionLock PrintLock(m_pModule->m_PrintCriticalSection); |
---|
[142] | 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), |
---|
[217] | 300 | _FilterGraphHelper::FormatReferenceTime(Properties.tStop), |
---|
[142] | 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]); |
---|
[283] | 312 | UINT32 nBufferCheck = 0; |
---|
| 313 | for(nIndex = 0; nIndex < (SIZE_T) Properties.lActual; nIndex++) |
---|
| 314 | nBufferCheck += (UINT8) Properties.pbBuffer[nIndex]; |
---|
[142] | 315 | if(nIndex > g_nMaximalPrintSize) |
---|
| 316 | sBuffer.Append(_T("...")); |
---|
[283] | 317 | _tprintf(_T("%s") _T(".cbBuffer %d, .lActual %d, pbBuffer %s [0x%08X]\n"), |
---|
[142] | 318 | m_sNamePrefix, |
---|
| 319 | Properties.cbBuffer, |
---|
| 320 | Properties.lActual, |
---|
| 321 | sBuffer, |
---|
[283] | 322 | nBufferCheck, |
---|
[142] | 323 | 0); |
---|
| 324 | } |
---|
[283] | 325 | _tprintf(_T("%s") _T("Time, %s") _T("\n"), |
---|
| 326 | m_sNamePrefix, |
---|
| 327 | _StringHelper::Join(TimeArray, _T(", ")), |
---|
| 328 | 0); |
---|
[152] | 329 | if(m_pHandler) |
---|
| 330 | m_pHandler->HandleSample(Properties); |
---|
[142] | 331 | _tprintf(_T("\n")); |
---|
[217] | 332 | m_nPreviousFlags = Properties.dwSampleFlags; |
---|
| 333 | m_nPreviousStartTime = Properties.tStart; |
---|
| 334 | m_nPreviousStopTime = Properties.tStop; |
---|
| 335 | |
---|
[142] | 336 | } |
---|
| 337 | _ATLCATCH(Exception) |
---|
| 338 | { |
---|
| 339 | _C(Exception); |
---|
| 340 | } |
---|
| 341 | return S_OK; |
---|
| 342 | } |
---|
[143] | 343 | STDMETHOD(BufferCB)(DOUBLE fSampleTime, BYTE* pnBuffer, LONG nBufferSize) |
---|
[142] | 344 | { |
---|
| 345 | return S_OK; |
---|
| 346 | } |
---|
| 347 | }; |
---|
| 348 | |
---|
| 349 | private: |
---|
| 350 | |
---|
| 351 | public: |
---|
| 352 | CPath m_sPath; |
---|
| 353 | BOOL m_bNoReferenceClock; |
---|
[217] | 354 | BOOL m_bSuppressLoadFailure; |
---|
[143] | 355 | mutable CRoCriticalSection m_PrintCriticalSection; |
---|
[142] | 356 | |
---|
| 357 | public: |
---|
| 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 | } |
---|
[143] | 381 | CModule() |
---|
[142] | 382 | { |
---|
| 383 | //m_sPath = GetDefaultPath(); |
---|
| 384 | m_bNoReferenceClock = FALSE; |
---|
[217] | 385 | m_bSuppressLoadFailure = FALSE; |
---|
[142] | 386 | } |
---|
[143] | 387 | ~CModule() |
---|
[142] | 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(); |
---|
[217] | 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 | } |
---|
[142] | 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(); |
---|
[143] | 421 | pSampleGrabberCallback->Initialize(this); |
---|
[142] | 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); |
---|
[152] | 428 | //typedef CHdycInterlacingHandler CHandler; |
---|
| 429 | //CObjectPtr<CHandler> pHandler; |
---|
| 430 | //pHandler.Construct()->Initialize(pMediaType); |
---|
| 431 | //pSampleGrabberCallback->SetHandler(pHandler); |
---|
[142] | 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 | |
---|
| 511 | int _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; |
---|
[217] | 541 | } else |
---|
| 542 | if(_tcschr(_T("Ee"), sArgument[0])) // Suppress Load Failure |
---|
| 543 | { |
---|
| 544 | Module.m_bSuppressLoadFailure = TRUE; |
---|
[142] | 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 | } |
---|
[152] | 568 | |
---|
| 569 | |
---|