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 | #import "libid:1469D378-8829-4ff0-9B3B-07DD5B16F3CB" raw_interfaces_only // DecklinkPublicLib |
---|
10 | #include <windows.h> |
---|
11 | #include <dshow.h> |
---|
12 | #include <dvdmedia.h> // VIDEOINFOHEADER2 |
---|
13 | |
---|
14 | #pragma comment(lib, "strmiids.lib") |
---|
15 | |
---|
16 | inline VOID __C(HRESULT nResult) { ATLENSURE_SUCCEEDED(nResult); } |
---|
17 | inline VOID __D(BOOL bResult, HRESULT nResult) { ATLENSURE_THROW(bResult, nResult); } |
---|
18 | inline VOID __D(const VOID* pvResult, HRESULT nResult) { ATLENSURE_THROW(pvResult, nResult); } |
---|
19 | |
---|
20 | //#pragma pack(show) |
---|
21 | |
---|
22 | CString StringFromData(const BYTE* pnData, SIZE_T nDataSize) |
---|
23 | { |
---|
24 | CString sString; |
---|
25 | for(SIZE_T nIndex = 0; nIndex < nDataSize; nIndex++) |
---|
26 | sString.AppendFormat(_T("%02X "), pnData[nIndex]); |
---|
27 | sString.TrimRight(); |
---|
28 | return sString; |
---|
29 | } |
---|
30 | CString StringFromData(const VOID* pvData, SIZE_T nDataSize) |
---|
31 | { |
---|
32 | return StringFromData((const BYTE*) pvData, nDataSize); |
---|
33 | } |
---|
34 | CString StringFromCode(DWORD nCode) |
---|
35 | { |
---|
36 | // NOTE: More precisely, we need to compare each byte against 0x20, but this one is good enough too |
---|
37 | if(nCode < 0x20202020) |
---|
38 | return (LPCTSTR) NULL; |
---|
39 | TCHAR pszCode[] = |
---|
40 | { |
---|
41 | (nCode >> 0) & 0xFF, |
---|
42 | (nCode >> 8) & 0xFF, |
---|
43 | (nCode >> 16) & 0xFF, |
---|
44 | (nCode >> 24) & 0xFF, |
---|
45 | 0 |
---|
46 | }; |
---|
47 | return pszCode; |
---|
48 | } |
---|
49 | |
---|
50 | int _tmain(int argc, _TCHAR* argv[]) |
---|
51 | { |
---|
52 | _ATLTRY |
---|
53 | { |
---|
54 | __C(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); |
---|
55 | _ATLTRY |
---|
56 | { |
---|
57 | CComPtr<ICreateDevEnum> pCreateDevEnum; |
---|
58 | __C(pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum)); |
---|
59 | CComPtr<IEnumMoniker> pEnumMoniker; |
---|
60 | __C(pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0)); |
---|
61 | CComPtr<IMoniker> pMoniker; |
---|
62 | while(pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK) |
---|
63 | { |
---|
64 | _ATLTRY |
---|
65 | { |
---|
66 | LPOLESTR pszDisplayName = NULL; |
---|
67 | ATLVERIFY(SUCCEEDED(pMoniker->GetDisplayName(NULL, NULL, &pszDisplayName))); |
---|
68 | // TODO: Free pszDisplayName |
---|
69 | if(pszDisplayName) |
---|
70 | _tprintf(_T("Moniker Display Name: %ls\n"), pszDisplayName); |
---|
71 | CComPtr<IPropertyBag> pPropertyBag; |
---|
72 | __C(pMoniker->BindToStorage(NULL, NULL, __uuidof(IPropertyBag), (VOID**) &pPropertyBag)); |
---|
73 | CComVariant vFriendlyName; |
---|
74 | __C(pPropertyBag->Read(L"FriendlyName", &vFriendlyName, NULL)); |
---|
75 | __D(vFriendlyName.vt == VT_BSTR, E_FAIL); |
---|
76 | _tprintf(_T("Friendly Name: %s\n"), CString(vFriendlyName.bstrVal)); |
---|
77 | CComPtr<IBaseFilter> pBaseFilter; |
---|
78 | __C(pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (VOID**) &pBaseFilter)); |
---|
79 | #pragma region DeckLink Specific |
---|
80 | const CComQIPtr<DecklinkPublicLib::IDecklinkIOControl> pDecklinkIoControl = pBaseFilter; |
---|
81 | if(pDecklinkIoControl) |
---|
82 | _ATLTRY |
---|
83 | { |
---|
84 | ULONG nIoFeatures = 0; |
---|
85 | __C(pDecklinkIoControl->GetIOFeatures(&nIoFeatures)); |
---|
86 | _tprintf(_T("DeckLink IO Features: 0x%08x\n"), nIoFeatures); |
---|
87 | } |
---|
88 | _ATLCATCHALL() |
---|
89 | { |
---|
90 | } |
---|
91 | #pragma endregion |
---|
92 | CComPtr<IEnumPins> pEnumPins; |
---|
93 | __C(pBaseFilter->EnumPins(&pEnumPins)); |
---|
94 | CComPtr<IPin> pPin; |
---|
95 | while(pEnumPins->Next(1, &pPin, NULL) == S_OK) |
---|
96 | { |
---|
97 | _ATLTRY |
---|
98 | { |
---|
99 | CComQIPtr<IAMStreamConfig> pAmStreamConfig = pPin; |
---|
100 | if(pAmStreamConfig) |
---|
101 | { |
---|
102 | PIN_INFO PinInformation; |
---|
103 | __C(pPin->QueryPinInfo(&PinInformation)); |
---|
104 | reinterpret_cast<CComPtr<IBaseFilter>&>(PinInformation.pFilter) = NULL; |
---|
105 | _tprintf(_T(" Pin: %s\n"), CString(PinInformation.achName)); |
---|
106 | INT nCapabilityCount = 0; |
---|
107 | INT nSize = 0; |
---|
108 | __C(pAmStreamConfig->GetNumberOfCapabilities(&nCapabilityCount, &nSize)); |
---|
109 | _tprintf(_T(" Capability Count: %d\n"), nCapabilityCount); |
---|
110 | _tprintf(_T(" Structure Size: %d (expected %d)\n"), nSize, sizeof (VIDEO_STREAM_CONFIG_CAPS)); |
---|
111 | CTempBuffer<VIDEO_STREAM_CONFIG_CAPS> pCapability; |
---|
112 | __D(nSize >= sizeof *pCapability, E_FAIL); |
---|
113 | __D(pCapability.AllocateBytes(nSize), E_OUTOFMEMORY); |
---|
114 | for(INT nCapabilityIndex = 0; nCapabilityIndex < nCapabilityCount; nCapabilityIndex++) |
---|
115 | { |
---|
116 | _tprintf(_T(" Capability %d:\n"), nCapabilityIndex); |
---|
117 | AM_MEDIA_TYPE* pMediaType = NULL; |
---|
118 | __C(pAmStreamConfig->GetStreamCaps(nCapabilityIndex, &pMediaType, (BYTE*) (VIDEO_STREAM_CONFIG_CAPS*) pCapability)); |
---|
119 | ATLASSERT(pMediaType); |
---|
120 | // TODO: Free pMediaType |
---|
121 | _tprintf(_T(" AM_MEDIA_TYPE:\n")); |
---|
122 | _tprintf(_T(" Media Type Data: %s\n"), StringFromData(pMediaType, sizeof *pMediaType)); |
---|
123 | if(pMediaType->cbFormat) |
---|
124 | _tprintf(_T(" Media Type Format Data: %s\n"), StringFromData(pMediaType->pbFormat, pMediaType->cbFormat)); |
---|
125 | // SUGG: majortype, subtype |
---|
126 | if(memcmp((const BYTE*) &pMediaType->subtype + sizeof (DWORD), (const BYTE*) &MEDIASUBTYPE_MJPG + sizeof (DWORD), sizeof (GUID) - sizeof (DWORD)) == 0) |
---|
127 | { |
---|
128 | const CString sSubtypeCode = StringFromCode(pMediaType->subtype.Data1); |
---|
129 | if(!sSubtypeCode.IsEmpty()) |
---|
130 | _tprintf(_T(" .subtype: %s\n"), sSubtypeCode); |
---|
131 | } |
---|
132 | _tprintf(_T(" .bFixedSizeSamples: %d\n"), pMediaType->bFixedSizeSamples); |
---|
133 | _tprintf(_T(" .bTemporalCompression: %d\n"), pMediaType->bTemporalCompression); |
---|
134 | _tprintf(_T(" .lSampleSize: %d\n"), pMediaType->lSampleSize); |
---|
135 | // SUGG: formattype, pUnk |
---|
136 | _tprintf(_T(" .cbFormat: %d\n"), pMediaType->cbFormat); |
---|
137 | const BYTE* pnExtraData = pMediaType->pbFormat; |
---|
138 | SIZE_T nExtraDataSize = pMediaType->cbFormat; |
---|
139 | if(pMediaType->formattype == FORMAT_VideoInfo) |
---|
140 | { |
---|
141 | const VIDEOINFOHEADER* pVideoInfoHeader = (VIDEOINFOHEADER*) pMediaType->pbFormat; |
---|
142 | _tprintf(_T(" VIDEOINFOHEADER:\n")); |
---|
143 | _tprintf(_T(" .rcSource: (%d, %d) - (%d, %d)\n"), pVideoInfoHeader->rcSource); |
---|
144 | _tprintf(_T(" .rcSource: (%d, %d) - (%d, %d)\n"), pVideoInfoHeader->rcTarget); |
---|
145 | _tprintf(_T(" .dwBitRate: %d\n"), pVideoInfoHeader->dwBitRate); |
---|
146 | _tprintf(_T(" .dwBitErrorRate: %d\n"), pVideoInfoHeader->dwBitErrorRate); |
---|
147 | _tprintf(_T(" .AvgTimePerFrame: %I64d\n"), pVideoInfoHeader->AvgTimePerFrame); |
---|
148 | _tprintf(_T(" BITMAPINFOHEADER:\n")); |
---|
149 | _tprintf(_T(" .biSize: %d\n"), pVideoInfoHeader->bmiHeader.biSize); |
---|
150 | _tprintf(_T(" .biWidth: %d\n"), pVideoInfoHeader->bmiHeader.biWidth); |
---|
151 | _tprintf(_T(" .biHeight: %d\n"), pVideoInfoHeader->bmiHeader.biHeight); |
---|
152 | _tprintf(_T(" .biPlanes: %d\n"), pVideoInfoHeader->bmiHeader.biPlanes); |
---|
153 | _tprintf(_T(" .biBitCount: %d\n"), pVideoInfoHeader->bmiHeader.biBitCount); |
---|
154 | _tprintf(_T(" .biCompression: %d %s\n"), pVideoInfoHeader->bmiHeader.biCompression, StringFromCode(pVideoInfoHeader->bmiHeader.biCompression)); |
---|
155 | _tprintf(_T(" .biSizeImage: %d\n"), pVideoInfoHeader->bmiHeader.biSizeImage); |
---|
156 | pnExtraData += sizeof *pVideoInfoHeader; |
---|
157 | nExtraDataSize -= sizeof *pVideoInfoHeader; |
---|
158 | } else |
---|
159 | if(pMediaType->formattype == FORMAT_VideoInfo2) |
---|
160 | { |
---|
161 | const VIDEOINFOHEADER2* pVideoInfoHeader2 = (VIDEOINFOHEADER2*) pMediaType->pbFormat; |
---|
162 | _tprintf(_T(" VIDEOINFOHEADER2:\n")); |
---|
163 | // SUGG: Extra data |
---|
164 | pnExtraData += sizeof *pVideoInfoHeader2; |
---|
165 | nExtraDataSize -= sizeof *pVideoInfoHeader2; |
---|
166 | } |
---|
167 | if(nExtraDataSize > 0) |
---|
168 | { |
---|
169 | CString sLine; |
---|
170 | for(SIZE_T nIndex = 0; nIndex < nExtraDataSize && nIndex < 63; nIndex++) |
---|
171 | { |
---|
172 | sLine.AppendFormat(_T("%02X "), pnExtraData[nIndex]); |
---|
173 | if(((nIndex + 1) % 0x10) == 0x00 || nIndex == 62) |
---|
174 | { |
---|
175 | if(nIndex == 62 && nExtraDataSize > nIndex + 1) |
---|
176 | sLine.Append(_T("...")); |
---|
177 | _tprintf(_T(" Extra [%04X]: %s\n"), nIndex & ~0x000F, sLine); |
---|
178 | sLine.Empty(); |
---|
179 | } |
---|
180 | } |
---|
181 | ATLASSERT(sLine.IsEmpty()); |
---|
182 | } |
---|
183 | ATLASSERT(pCapability->guid == MEDIATYPE_Video); |
---|
184 | _tprintf(_T(" VIDEO_STREAM_CONFIG_CAPS:\n")); |
---|
185 | _tprintf(_T(" Data: %s\n"), StringFromData((VIDEO_STREAM_CONFIG_CAPS*) pCapability, sizeof *pCapability)); |
---|
186 | _tprintf(_T(" .VideoStandard: %d\n"), pCapability->VideoStandard); |
---|
187 | _tprintf(_T(" .InputSize: %d x %d\n"), pCapability->InputSize); |
---|
188 | _tprintf(_T(" .MinCroppingSize: %d x %d\n"), pCapability->MinCroppingSize); |
---|
189 | _tprintf(_T(" .MaxCroppingSize: %d x %d\n"), pCapability->MaxCroppingSize); |
---|
190 | _tprintf(_T(" .CropGranularityX: %d\n"), pCapability->CropGranularityX); |
---|
191 | _tprintf(_T(" .CropAlignX: %d\n"), pCapability->CropAlignX); |
---|
192 | _tprintf(_T(" .CropAlignY: %d\n"), pCapability->CropAlignY); |
---|
193 | _tprintf(_T(" .MinOutputSize: %d x %d\n"), pCapability->MinOutputSize); |
---|
194 | _tprintf(_T(" .MaxOutputSize: %d x %d\n"), pCapability->MaxOutputSize); |
---|
195 | _tprintf(_T(" .OutputGranularityX: %d\n"), pCapability->OutputGranularityX); |
---|
196 | _tprintf(_T(" .OutputGranularityY: %d\n"), pCapability->OutputGranularityY); |
---|
197 | _tprintf(_T(" .StretchTapsX: %d\n"), pCapability->StretchTapsX); |
---|
198 | _tprintf(_T(" .StretchTapsY: %d\n"), pCapability->StretchTapsY); |
---|
199 | _tprintf(_T(" .ShrinkTapsX: %d\n"), pCapability->ShrinkTapsX); |
---|
200 | _tprintf(_T(" .ShrinkTapsY: %d\n"), pCapability->ShrinkTapsY); |
---|
201 | _tprintf(_T(" .MinFrameInterval: %I64d\n"), pCapability->MinFrameInterval); |
---|
202 | _tprintf(_T(" .MaxFrameInterval: %I64d\n"), pCapability->MaxFrameInterval); |
---|
203 | _tprintf(_T(" .MinBitsPerSecond: %d\n"), pCapability->MinBitsPerSecond); |
---|
204 | _tprintf(_T(" .MaxBitsPerSecond: %d\n"), pCapability->MaxBitsPerSecond); |
---|
205 | } |
---|
206 | } |
---|
207 | } |
---|
208 | _ATLCATCHALL() |
---|
209 | { |
---|
210 | _tprintf(_T("An exception has been caught\n")); |
---|
211 | } |
---|
212 | pPin.Release(); |
---|
213 | } |
---|
214 | } |
---|
215 | _ATLCATCHALL() |
---|
216 | { |
---|
217 | _tprintf(_T("An exception has been caught\n")); |
---|
218 | } |
---|
219 | pMoniker.Release(); |
---|
220 | _tprintf(_T("\n")); |
---|
221 | } |
---|
222 | } |
---|
223 | _ATLCATCHALL() |
---|
224 | { |
---|
225 | CoUninitialize(); |
---|
226 | _ATLRETHROW; |
---|
227 | } |
---|
228 | CoUninitialize(); |
---|
229 | } |
---|
230 | _ATLCATCHALL() |
---|
231 | { |
---|
232 | } |
---|
233 | return 0; |
---|
234 | } |
---|
235 | |
---|