sync with trunk r49322
[reactos.git] / dll / directx / ksproxy / datatype.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/datatype.cpp
5 * PURPOSE: IKsDataTypeHandler interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 /* FIXME guid mess */
12 #ifndef _MSC_VER
13 const GUID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
14 #endif
15 const GUID IID_IClassFactory = {0x00000001, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
16
17 class CKsDataTypeHandler : public IKsDataTypeHandler
18 {
19 public:
20 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
21
22 STDMETHODIMP_(ULONG) AddRef()
23 {
24 InterlockedIncrement(&m_Ref);
25 return m_Ref;
26 }
27 STDMETHODIMP_(ULONG) Release()
28 {
29 InterlockedDecrement(&m_Ref);
30
31 if (!m_Ref)
32 {
33 delete this;
34 return 0;
35 }
36 return m_Ref;
37 }
38
39 HRESULT STDMETHODCALLTYPE KsCompleteIoOperation(IN OUT IMediaSample *Sample, IN OUT PVOID StreamHeader, IN KSIOOPERATION IoOperation, IN BOOL Cancelled);
40 HRESULT STDMETHODCALLTYPE KsIsMediaTypeInRanges(IN PVOID DataRanges);
41 HRESULT STDMETHODCALLTYPE KsPrepareIoOperation(IN OUT IMediaSample *Sample, IN OUT PVOID StreamHeader, IN KSIOOPERATION IoOperation);
42 HRESULT STDMETHODCALLTYPE KsQueryExtendedSize(OUT ULONG* ExtendedSize);
43 HRESULT STDMETHODCALLTYPE KsSetMediaType(IN const AM_MEDIA_TYPE* AmMediaType);
44
45 CKsDataTypeHandler() : m_Ref(0), m_Type(0){};
46 virtual ~CKsDataTypeHandler()
47 {
48 if (m_Type)
49 {
50 if (m_Type->pbFormat)
51 CoTaskMemFree(m_Type->pbFormat);
52
53 if (m_Type->pUnk)
54 m_Type->pUnk->Release();
55
56 CoTaskMemFree(m_Type);
57 }
58
59 };
60
61 protected:
62 LONG m_Ref;
63 AM_MEDIA_TYPE * m_Type;
64 };
65
66
67 HRESULT
68 STDMETHODCALLTYPE
69 CKsDataTypeHandler::QueryInterface(
70 IN REFIID refiid,
71 OUT PVOID* Output)
72 {
73 if (IsEqualGUID(refiid, IID_IUnknown) ||
74 IsEqualGUID(refiid, IID_IKsDataTypeHandler))
75 {
76 *Output = PVOID(this);
77 reinterpret_cast<IUnknown*>(*Output)->AddRef();
78 return NOERROR;
79 }
80 return E_NOINTERFACE;
81 }
82
83
84 HRESULT
85 STDMETHODCALLTYPE
86 CKsDataTypeHandler::KsCompleteIoOperation(
87 IN OUT IMediaSample *Sample,
88 IN OUT PVOID StreamHeader,
89 IN KSIOOPERATION IoOperation,
90 IN BOOL Cancelled)
91 {
92 return NOERROR;
93 }
94
95
96 HRESULT
97 STDMETHODCALLTYPE
98 CKsDataTypeHandler::KsIsMediaTypeInRanges(
99 IN PVOID DataRanges)
100 {
101 PKSMULTIPLE_ITEM DataList;
102 PKSDATARANGE DataRange;
103 ULONG Index;
104 HRESULT hr = S_FALSE;
105
106 #ifdef KSPROXY_TRACE
107 OutputDebugStringW(L"CKsDataTypeHandler::KsIsMediaTypeInRanges\n");
108 #endif
109
110 DataList = (PKSMULTIPLE_ITEM)DataRanges;
111 DataRange = (PKSDATARANGE)(DataList + 1);
112
113 for(Index = 0; Index < DataList->Count; Index++)
114 {
115 BOOL bMatch = FALSE;
116
117 if (DataRange->FormatSize >= sizeof(KSDATARANGE))
118 {
119 bMatch = IsEqualGUID(DataRange->MajorFormat, GUID_NULL);
120 }
121
122 if (!bMatch && DataRange->FormatSize >= sizeof(KSDATARANGE_AUDIO))
123 {
124 bMatch = IsEqualGUID(DataRange->MajorFormat, MEDIATYPE_Audio);
125 }
126
127 if (bMatch)
128 {
129 if (IsEqualGUID(DataRange->SubFormat, m_Type->subtype) ||
130 IsEqualGUID(DataRange->SubFormat, GUID_NULL))
131 {
132 if (IsEqualGUID(DataRange->Specifier, m_Type->formattype) ||
133 IsEqualGUID(DataRange->Specifier, GUID_NULL))
134 {
135 if (!IsEqualGUID(m_Type->formattype, FORMAT_WaveFormatEx) && !IsEqualGUID(DataRange->Specifier, FORMAT_WaveFormatEx))
136 {
137 //found match
138 hr = S_OK;
139 break;
140 }
141
142 if (DataRange->FormatSize >= sizeof(KSDATARANGE_AUDIO) && m_Type->cbFormat >= sizeof(WAVEFORMATEX))
143 {
144 LPWAVEFORMATEX Format = (LPWAVEFORMATEX)m_Type->pbFormat;
145 PKSDATARANGE_AUDIO AudioRange = (PKSDATARANGE_AUDIO)DataRange;
146
147 if (Format->nSamplesPerSec >= AudioRange->MinimumSampleFrequency &&
148 Format->nSamplesPerSec <= AudioRange->MaximumSampleFrequency &&
149 Format->wBitsPerSample >= AudioRange->MinimumSampleFrequency &&
150 Format->wBitsPerSample <= AudioRange->MaximumBitsPerSample &&
151 Format->nChannels <= AudioRange->MaximumChannels)
152 {
153 // found match
154 hr = S_OK;
155 break;
156 }
157 }
158 }
159 }
160 }
161
162 DataRange = (PKSDATARANGE)(((ULONG_PTR)DataRange + DataRange->FormatSize + 7) & ~7);
163 }
164 return S_OK;
165 }
166
167 HRESULT
168 STDMETHODCALLTYPE
169 CKsDataTypeHandler::KsPrepareIoOperation(
170 IN OUT IMediaSample *Sample,
171 IN OUT PVOID StreamHeader,
172 IN KSIOOPERATION IoOperation)
173 {
174 return NOERROR;
175 }
176
177 HRESULT
178 STDMETHODCALLTYPE
179 CKsDataTypeHandler::KsQueryExtendedSize(
180 OUT ULONG* ExtendedSize)
181 {
182 /* no header extension required */
183 *ExtendedSize = 0;
184 return NOERROR;
185 }
186
187 HRESULT
188 STDMETHODCALLTYPE
189 CKsDataTypeHandler::KsSetMediaType(
190 IN const AM_MEDIA_TYPE* AmMediaType)
191 {
192 #ifdef KSPROXY_TRACE
193 OutputDebugString("CKsDataTypeHandler::KsSetMediaType\n");
194 #endif
195
196 if (m_Type)
197 {
198 /* media type can only be set once */
199 return E_FAIL;
200 }
201
202 m_Type = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
203 if (!m_Type)
204 return E_OUTOFMEMORY;
205
206 CopyMemory(m_Type, AmMediaType, sizeof(AM_MEDIA_TYPE));
207
208 if (m_Type->cbFormat)
209 {
210 m_Type->pbFormat = (BYTE*)CoTaskMemAlloc(m_Type->cbFormat);
211
212 if (!m_Type->pbFormat)
213 {
214 CoTaskMemFree(m_Type);
215 return E_OUTOFMEMORY;
216 }
217
218 CopyMemory(m_Type->pbFormat, AmMediaType->pbFormat, m_Type->cbFormat);
219 }
220
221 if (m_Type->pUnk)
222 m_Type->pUnk->AddRef();
223
224
225 return S_OK;
226 }
227
228 HRESULT
229 WINAPI
230 CKsDataTypeHandler_Constructor (
231 IUnknown * pUnkOuter,
232 REFIID riid,
233 LPVOID * ppv)
234 {
235 #ifdef KSPROXY_TRACE
236 OutputDebugStringW(L"CKsDataTypeHandler_Constructor\n");
237 #endif
238
239 CKsDataTypeHandler * handler = new CKsDataTypeHandler();
240
241 if (!handler)
242 return E_OUTOFMEMORY;
243
244 if (FAILED(handler->QueryInterface(riid, ppv)))
245 {
246 /* not supported */
247 delete handler;
248 return E_NOINTERFACE;
249 }
250
251 return NOERROR;
252 }