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