1 /*
2  * Implementation of IMediaStream Interfaces
3  *
4  * Copyright 2005, 2008, 2012 Christian Costa
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #ifndef __REACTOS__
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
24 #endif
25 #define COBJMACROS
26 
27 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "dshow.h"
32 
33 #include "wine/strmbase.h"
34 
35 #include "amstream_private.h"
36 
37 #include "ddstream.h"
38 #include "wine/debug.h"
39 
40 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
41 
42 #include <initguid.h>
43 DEFINE_GUID(IID_IDirectDraw7, 0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b);
44 
45 static HRESULT ddrawstreamsample_create(IDirectDrawMediaStream *parent, IDirectDrawSurface *surface,
46     const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
47 static HRESULT audiostreamsample_create(IAudioMediaStream *parent, IAudioData *audio_data, IAudioStreamSample **audio_stream_sample);
48 
49 struct DirectDrawMediaStreamImpl;
50 
51 typedef struct {
52     BaseInputPin pin;
53     struct DirectDrawMediaStreamImpl *parent;
54 } DirectDrawMediaStreamInputPin;
55 
56 typedef struct DirectDrawMediaStreamImpl {
57     IAMMediaStream IAMMediaStream_iface;
58     IDirectDrawMediaStream IDirectDrawMediaStream_iface;
59     LONG ref;
60     IMultiMediaStream* parent;
61     MSPID purpose_id;
62     STREAM_TYPE stream_type;
63     IDirectDraw7 *ddraw;
64     DirectDrawMediaStreamInputPin *input_pin;
65     CRITICAL_SECTION critical_section;
66 } DirectDrawMediaStreamImpl;
67 
68 static inline DirectDrawMediaStreamImpl *impl_from_DirectDrawMediaStream_IAMMediaStream(IAMMediaStream *iface)
69 {
70     return CONTAINING_RECORD(iface, DirectDrawMediaStreamImpl, IAMMediaStream_iface);
71 }
72 
73 /*** IUnknown methods ***/
74 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_QueryInterface(IAMMediaStream *iface,
75                                                         REFIID riid, void **ret_iface)
76 {
77     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
78 
79     TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
80 
81     if (IsEqualGUID(riid, &IID_IUnknown) ||
82         IsEqualGUID(riid, &IID_IMediaStream) ||
83         IsEqualGUID(riid, &IID_IAMMediaStream))
84     {
85         IAMMediaStream_AddRef(iface);
86         *ret_iface = iface;
87         return S_OK;
88     }
89     else if (IsEqualGUID(riid, &IID_IDirectDrawMediaStream))
90     {
91         IAMMediaStream_AddRef(iface);
92         *ret_iface = &This->IDirectDrawMediaStream_iface;
93         return S_OK;
94     }
95     else if (IsEqualGUID(riid, &IID_IPin))
96     {
97         IAMMediaStream_AddRef(iface);
98         *ret_iface = &This->input_pin->pin.pin.IPin_iface;
99         return S_OK;
100     }
101     else if (IsEqualGUID(riid, &IID_IMemInputPin))
102     {
103         IAMMediaStream_AddRef(iface);
104         *ret_iface = &This->input_pin->pin.IMemInputPin_iface;
105         return S_OK;
106     }
107 
108     ERR("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ret_iface);
109     return E_NOINTERFACE;
110 }
111 
112 static ULONG WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_AddRef(IAMMediaStream *iface)
113 {
114     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
115     ULONG ref = InterlockedIncrement(&This->ref);
116 
117     TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
118 
119     return ref;
120 }
121 
122 static ULONG WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_Release(IAMMediaStream *iface)
123 {
124     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
125     ULONG ref = InterlockedDecrement(&This->ref);
126 
127     TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
128 
129     if (!ref)
130     {
131         BaseInputPin_Destroy((BaseInputPin *)This->input_pin);
132         DeleteCriticalSection(&This->critical_section);
133         if (This->ddraw)
134             IDirectDraw7_Release(This->ddraw);
135         HeapFree(GetProcessHeap(), 0, This);
136     }
137 
138     return ref;
139 }
140 
141 /*** IMediaStream methods ***/
142 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_GetMultiMediaStream(IAMMediaStream *iface,
143         IMultiMediaStream** multi_media_stream)
144 {
145     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
146 
147     TRACE("(%p/%p)->(%p)\n", This, iface, multi_media_stream);
148 
149     if (!multi_media_stream)
150         return E_POINTER;
151 
152     IMultiMediaStream_AddRef(This->parent);
153     *multi_media_stream = This->parent;
154 
155     return S_OK;
156 }
157 
158 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_GetInformation(IAMMediaStream *iface,
159         MSPID *purpose_id, STREAM_TYPE *type)
160 {
161     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
162 
163     TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
164 
165     if (purpose_id)
166         *purpose_id = This->purpose_id;
167     if (type)
168         *type = This->stream_type;
169 
170     return S_OK;
171 }
172 
173 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_SetSameFormat(IAMMediaStream *iface,
174         IMediaStream *pStreamThatHasDesiredFormat, DWORD flags)
175 {
176     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
177 
178     FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, flags);
179 
180     return S_FALSE;
181 }
182 
183 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_AllocateSample(IAMMediaStream *iface,
184         DWORD flags, IStreamSample **sample)
185 {
186     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
187 
188     FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, flags, sample);
189 
190     return S_FALSE;
191 }
192 
193 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_CreateSharedSample(IAMMediaStream *iface,
194         IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
195 {
196     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
197 
198     FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, existing_sample, flags, sample);
199 
200     return S_FALSE;
201 }
202 
203 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
204 {
205     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
206 
207     FIXME("(%p/%p)->(%x) stub!\n", This, iface, flags);
208 
209     return S_FALSE;
210 }
211 
212 /*** IAMMediaStream methods ***/
213 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_Initialize(IAMMediaStream *iface, IUnknown *source_object, DWORD flags,
214                                                     REFMSPID purpose_id, const STREAM_TYPE stream_type)
215 {
216     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
217 
218     FIXME("(%p/%p)->(%p,%x,%p,%u) stub!\n", This, iface, source_object, flags, purpose_id, stream_type);
219 
220     return S_FALSE;
221 }
222 
223 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_SetState(IAMMediaStream *iface, FILTER_STATE state)
224 {
225     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
226 
227     FIXME("(%p/%p)->(%u) stub!\n", This, iface, state);
228 
229     return S_FALSE;
230 }
231 
232 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *am_multi_media_stream)
233 {
234     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
235 
236     FIXME("(%p/%p)->(%p) stub!\n", This, iface, am_multi_media_stream);
237 
238     return S_FALSE;
239 }
240 
241 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *media_stream_filter)
242 {
243     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
244 
245     TRACE("(%p/%p)->(%p)\n", This, iface, media_stream_filter);
246 
247     This->input_pin->pin.pin.pinInfo.pFilter = (IBaseFilter *)media_stream_filter;
248 
249     return S_OK;
250 }
251 
252 static HRESULT WINAPI DirectDrawMediaStreamImpl_IAMMediaStream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *filtergraph)
253 {
254     DirectDrawMediaStreamImpl *This = impl_from_DirectDrawMediaStream_IAMMediaStream(iface);
255 
256     FIXME("(%p/%p)->(%p) stub!\n", This, iface, filtergraph);
257 
258     return S_FALSE;
259 }
260 
261 static const struct IAMMediaStreamVtbl DirectDrawMediaStreamImpl_IAMMediaStream_Vtbl =
262 {
263     /*** IUnknown methods ***/
264     DirectDrawMediaStreamImpl_IAMMediaStream_QueryInterface,
265     DirectDrawMediaStreamImpl_IAMMediaStream_AddRef,
266     DirectDrawMediaStreamImpl_IAMMediaStream_Release,
267     /*** IMediaStream methods ***/
268     DirectDrawMediaStreamImpl_IAMMediaStream_GetMultiMediaStream,
269     DirectDrawMediaStreamImpl_IAMMediaStream_GetInformation,
270     DirectDrawMediaStreamImpl_IAMMediaStream_SetSameFormat,
271     DirectDrawMediaStreamImpl_IAMMediaStream_AllocateSample,
272     DirectDrawMediaStreamImpl_IAMMediaStream_CreateSharedSample,
273     DirectDrawMediaStreamImpl_IAMMediaStream_SendEndOfStream,
274     /*** IAMMediaStream methods ***/
275     DirectDrawMediaStreamImpl_IAMMediaStream_Initialize,
276     DirectDrawMediaStreamImpl_IAMMediaStream_SetState,
277     DirectDrawMediaStreamImpl_IAMMediaStream_JoinAMMultiMediaStream,
278     DirectDrawMediaStreamImpl_IAMMediaStream_JoinFilter,
279     DirectDrawMediaStreamImpl_IAMMediaStream_JoinFilterGraph
280 };
281 
282 static inline DirectDrawMediaStreamImpl *impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream *iface)
283 {
284     return CONTAINING_RECORD(iface, DirectDrawMediaStreamImpl, IDirectDrawMediaStream_iface);
285 }
286 
287 /*** IUnknown methods ***/
288 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream *iface,
289         REFIID riid, void **ret_iface)
290 {
291     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
292     TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
293     return IAMMediaStream_QueryInterface(&This->IAMMediaStream_iface, riid, ret_iface);
294 }
295 
296 static ULONG WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream *iface)
297 {
298     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
299     TRACE("(%p/%p)\n", iface, This);
300     return IAMMediaStream_AddRef(&This->IAMMediaStream_iface);
301 }
302 
303 static ULONG WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_Release(IDirectDrawMediaStream *iface)
304 {
305     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
306     TRACE("(%p/%p)\n", iface, This);
307     return IAMMediaStream_Release(&This->IAMMediaStream_iface);
308 }
309 
310 /*** IMediaStream methods ***/
311 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream *iface,
312         IMultiMediaStream **multi_media_stream)
313 {
314     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
315 
316     TRACE("(%p/%p)->(%p)\n", This, iface, multi_media_stream);
317 
318     if (!multi_media_stream)
319         return E_POINTER;
320 
321     IMultiMediaStream_AddRef(This->parent);
322     *multi_media_stream = This->parent;
323 
324     return S_OK;
325 }
326 
327 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream *iface,
328         MSPID *purpose_id, STREAM_TYPE *type)
329 {
330     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
331 
332     TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
333 
334     if (purpose_id)
335         *purpose_id = This->purpose_id;
336     if (type)
337         *type = This->stream_type;
338 
339     return S_OK;
340 }
341 
342 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream *iface,
343         IMediaStream *pStreamThatHasDesiredFormat, DWORD dwFlags)
344 {
345     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
346 
347     FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, dwFlags);
348 
349     return S_FALSE;
350 }
351 
352 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream *iface,
353         DWORD dwFlags, IStreamSample **ppSample)
354 {
355     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
356 
357     FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, dwFlags, ppSample);
358 
359     return S_FALSE;
360 }
361 
362 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream *iface,
363         IStreamSample *pExistingSample, DWORD dwFlags, IStreamSample **ppSample)
364 {
365     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
366 
367     FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, pExistingSample, dwFlags, ppSample);
368 
369     return S_FALSE;
370 }
371 
372 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream *iface,
373         DWORD dwFlags)
374 {
375     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
376 
377     FIXME("(%p/%p)->(%x) stub!\n", This, iface, dwFlags);
378 
379     return S_FALSE;
380 }
381 
382 /*** IDirectDrawMediaStream methods ***/
383 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream *iface,
384         DDSURFACEDESC *current_format, IDirectDrawPalette **palette,
385         DDSURFACEDESC *desired_format, DWORD *flags)
386 {
387     FIXME("(%p)->(%p,%p,%p,%p) stub!\n", iface, current_format, palette, desired_format,
388             flags);
389 
390     return MS_E_NOSTREAM;
391 
392 }
393 
394 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream *iface,
395         const DDSURFACEDESC *pDDSurfaceDesc, IDirectDrawPalette *pDirectDrawPalette)
396 {
397     FIXME("(%p)->(%p,%p) stub!\n", iface, pDDSurfaceDesc, pDirectDrawPalette);
398 
399     return E_NOTIMPL;
400 }
401 
402 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream *iface,
403         IDirectDraw **ddraw)
404 {
405     DirectDrawMediaStreamImpl *This = impl_from_IDirectDrawMediaStream(iface);
406 
407     TRACE("(%p)->(%p)\n", iface, ddraw);
408 
409     *ddraw = NULL;
410     if (!This->ddraw)
411     {
412         HRESULT hr = DirectDrawCreateEx(NULL, (void**)&This->ddraw, &IID_IDirectDraw7, NULL);
413         if (FAILED(hr))
414             return hr;
415         IDirectDraw7_SetCooperativeLevel(This->ddraw, NULL, DDSCL_NORMAL);
416     }
417 
418     return IDirectDraw7_QueryInterface(This->ddraw, &IID_IDirectDraw, (void**)ddraw);
419 }
420 
421 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream *iface,
422         IDirectDraw *pDirectDraw)
423 {
424     FIXME("(%p)->(%p) stub!\n", iface, pDirectDraw);
425 
426     return E_NOTIMPL;
427 }
428 
429 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream *iface,
430         IDirectDrawSurface *surface, const RECT *rect, DWORD dwFlags,
431         IDirectDrawStreamSample **ppSample)
432 {
433     TRACE("(%p)->(%p,%s,%x,%p)\n", iface, surface, wine_dbgstr_rect(rect), dwFlags, ppSample);
434 
435     return ddrawstreamsample_create(iface, surface, rect, ppSample);
436 }
437 
438 static HRESULT WINAPI DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream *iface,
439         STREAM_TIME *pFrameTime)
440 {
441     FIXME("(%p)->(%p) stub!\n", iface, pFrameTime);
442 
443     return E_NOTIMPL;
444 }
445 
446 static const struct IDirectDrawMediaStreamVtbl DirectDrawMediaStreamImpl_IDirectDrawMediaStream_Vtbl =
447 {
448     /*** IUnknown methods ***/
449     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_QueryInterface,
450     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_AddRef,
451     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_Release,
452     /*** IMediaStream methods ***/
453     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetMultiMediaStream,
454     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetInformation,
455     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SetSameFormat,
456     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_AllocateSample,
457     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_CreateSharedSample,
458     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SendEndOfStream,
459     /*** IDirectDrawMediaStream methods ***/
460     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetFormat,
461     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SetFormat,
462     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetDirectDraw,
463     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_SetDirectDraw,
464     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_CreateSample,
465     DirectDrawMediaStreamImpl_IDirectDrawMediaStream_GetTimePerFrame
466 };
467 
468 static inline DirectDrawMediaStreamInputPin *impl_from_DirectDrawMediaStreamInputPin_IPin(IPin *iface)
469 {
470     return CONTAINING_RECORD(iface, DirectDrawMediaStreamInputPin, pin.pin.IPin_iface);
471 }
472 
473 /*** IUnknown methods ***/
474 static HRESULT WINAPI DirectDrawMediaStreamInputPin_IPin_QueryInterface(IPin *iface, REFIID riid, void **ret_iface)
475 {
476     DirectDrawMediaStreamInputPin *This = impl_from_DirectDrawMediaStreamInputPin_IPin(iface);
477 
478     return IAMMediaStream_QueryInterface(&This->parent->IAMMediaStream_iface, riid, ret_iface);
479 }
480 
481 static ULONG WINAPI DirectDrawMediaStreamInputPin_IPin_AddRef(IPin *iface)
482 {
483     DirectDrawMediaStreamInputPin *This = impl_from_DirectDrawMediaStreamInputPin_IPin(iface);
484 
485     return IAMMediaStream_AddRef(&This->parent->IAMMediaStream_iface);
486 }
487 
488 static ULONG WINAPI DirectDrawMediaStreamInputPin_IPin_Release(IPin *iface)
489 {
490     DirectDrawMediaStreamInputPin *This = impl_from_DirectDrawMediaStreamInputPin_IPin(iface);
491 
492     return IAMMediaStream_Release(&This->parent->IAMMediaStream_iface);
493 }
494 
495 static const IPinVtbl DirectDrawMediaStreamInputPin_IPin_Vtbl =
496 {
497     DirectDrawMediaStreamInputPin_IPin_QueryInterface,
498     DirectDrawMediaStreamInputPin_IPin_AddRef,
499     DirectDrawMediaStreamInputPin_IPin_Release,
500     BaseInputPinImpl_Connect,
501     BaseInputPinImpl_ReceiveConnection,
502     BasePinImpl_Disconnect,
503     BasePinImpl_ConnectedTo,
504     BasePinImpl_ConnectionMediaType,
505     BasePinImpl_QueryPinInfo,
506     BasePinImpl_QueryDirection,
507     BasePinImpl_QueryId,
508     BaseInputPinImpl_QueryAccept,
509     BasePinImpl_EnumMediaTypes,
510     BasePinImpl_QueryInternalConnections,
511     BaseInputPinImpl_EndOfStream,
512     BaseInputPinImpl_BeginFlush,
513     BaseInputPinImpl_EndFlush,
514     BaseInputPinImpl_NewSegment,
515 };
516 
517 static HRESULT WINAPI DirectDrawMediaStreamInputPin_CheckMediaType(BasePin *base, const AM_MEDIA_TYPE *media_type)
518 {
519     DirectDrawMediaStreamInputPin *This = impl_from_DirectDrawMediaStreamInputPin_IPin(&base->IPin_iface);
520 
521     TRACE("(%p)->(%p)\n", This, media_type);
522 
523     if (IsEqualGUID(&media_type->majortype, &MEDIATYPE_Video))
524     {
525         if (IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB1) ||
526             IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB4) ||
527             IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB8)  ||
528             IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB565) ||
529             IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB555) ||
530             IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB24) ||
531             IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB32))
532         {
533             TRACE("Video sub-type %s matches\n", debugstr_guid(&media_type->subtype));
534             return S_OK;
535         }
536     }
537 
538     return S_FALSE;
539 }
540 
541 static LONG WINAPI DirectDrawMediaStreamInputPin_GetMediaTypeVersion(BasePin *base)
542 {
543     return 0;
544 }
545 
546 static HRESULT WINAPI DirectDrawMediaStreamInputPin_GetMediaType(BasePin *base, int index, AM_MEDIA_TYPE *media_type)
547 {
548     DirectDrawMediaStreamInputPin *This = impl_from_DirectDrawMediaStreamInputPin_IPin(&base->IPin_iface);
549 
550     TRACE("(%p)->(%d,%p)\n", This, index, media_type);
551 
552     /* FIXME: Reset structure as we only fill majortype and minortype for now */
553     ZeroMemory(media_type, sizeof(*media_type));
554 
555     media_type->majortype = MEDIATYPE_Video;
556 
557     switch (index)
558     {
559         case 0:
560             media_type->subtype = MEDIASUBTYPE_RGB1;
561             break;
562         case 1:
563             media_type->subtype = MEDIASUBTYPE_RGB4;
564             break;
565         case 2:
566             media_type->subtype = MEDIASUBTYPE_RGB8;
567             break;
568         case 3:
569             media_type->subtype = MEDIASUBTYPE_RGB565;
570             break;
571         case 4:
572             media_type->subtype = MEDIASUBTYPE_RGB555;
573             break;
574         case 5:
575             media_type->subtype = MEDIASUBTYPE_RGB24;
576             break;
577         case 6:
578             media_type->subtype = MEDIASUBTYPE_RGB32;
579             break;
580         default:
581             return S_FALSE;
582     }
583 
584     return S_OK;
585 }
586 
587 static HRESULT WINAPI DirectDrawMediaStreamInputPin_Receive(BaseInputPin *base, IMediaSample *sample)
588 {
589     DirectDrawMediaStreamInputPin *This = impl_from_DirectDrawMediaStreamInputPin_IPin(&base->pin.IPin_iface);
590 
591     FIXME("(%p)->(%p) stub!\n", This, sample);
592 
593     return E_NOTIMPL;
594 }
595 
596 static const BaseInputPinFuncTable DirectDrawMediaStreamInputPin_FuncTable =
597 {
598     {
599         DirectDrawMediaStreamInputPin_CheckMediaType,
600         NULL,
601         DirectDrawMediaStreamInputPin_GetMediaTypeVersion,
602         DirectDrawMediaStreamInputPin_GetMediaType,
603     },
604     DirectDrawMediaStreamInputPin_Receive,
605 };
606 
607 HRESULT ddrawmediastream_create(IMultiMediaStream *parent, const MSPID *purpose_id,
608         STREAM_TYPE stream_type, IAMMediaStream **media_stream)
609 {
610     DirectDrawMediaStreamImpl *object;
611     PIN_INFO pin_info;
612     HRESULT hr;
613 
614     TRACE("(%p,%s,%p)\n", parent, debugstr_guid(purpose_id), media_stream);
615 
616     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectDrawMediaStreamImpl));
617     if (!object)
618         return E_OUTOFMEMORY;
619 
620     object->IAMMediaStream_iface.lpVtbl = &DirectDrawMediaStreamImpl_IAMMediaStream_Vtbl;
621     object->IDirectDrawMediaStream_iface.lpVtbl = &DirectDrawMediaStreamImpl_IDirectDrawMediaStream_Vtbl;
622     object->ref = 1;
623 
624     InitializeCriticalSection(&object->critical_section);
625 
626     pin_info.pFilter = NULL;
627     pin_info.dir = PINDIR_INPUT;
628     pin_info.achName[0] = 'I';
629     StringFromGUID2(purpose_id, pin_info.achName + 1, MAX_PIN_NAME - 1);
630     hr = BaseInputPin_Construct(&DirectDrawMediaStreamInputPin_IPin_Vtbl,
631         sizeof(DirectDrawMediaStreamInputPin), &pin_info, &DirectDrawMediaStreamInputPin_FuncTable,
632         &object->critical_section, NULL, (IPin **)&object->input_pin);
633     if (FAILED(hr))
634         goto out_object;
635 
636     object->input_pin->parent = object;
637 
638     object->parent = parent;
639     object->purpose_id = *purpose_id;
640     object->stream_type = stream_type;
641 
642     *media_stream = &object->IAMMediaStream_iface;
643 
644     return S_OK;
645 
646 out_object:
647     HeapFree(GetProcessHeap(), 0, object);
648 
649     return hr;
650 }
651 
652 struct AudioMediaStreamImpl;
653 
654 typedef struct {
655     BaseInputPin pin;
656     struct AudioMediaStreamImpl *parent;
657 } AudioMediaStreamInputPin;
658 
659 typedef struct AudioMediaStreamImpl {
660     IAMMediaStream IAMMediaStream_iface;
661     IAudioMediaStream IAudioMediaStream_iface;
662     LONG ref;
663     IMultiMediaStream* parent;
664     MSPID purpose_id;
665     STREAM_TYPE stream_type;
666     AudioMediaStreamInputPin *input_pin;
667     CRITICAL_SECTION critical_section;
668 } AudioMediaStreamImpl;
669 
670 static inline AudioMediaStreamImpl *impl_from_AudioMediaStream_IAMMediaStream(IAMMediaStream *iface)
671 {
672     return CONTAINING_RECORD(iface, AudioMediaStreamImpl, IAMMediaStream_iface);
673 }
674 
675 /*** IUnknown methods ***/
676 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_QueryInterface(IAMMediaStream *iface,
677                                                         REFIID riid, void **ret_iface)
678 {
679     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
680 
681     TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
682 
683     if (IsEqualGUID(riid, &IID_IUnknown) ||
684         IsEqualGUID(riid, &IID_IMediaStream) ||
685         IsEqualGUID(riid, &IID_IAMMediaStream))
686     {
687         IAMMediaStream_AddRef(iface);
688         *ret_iface = iface;
689         return S_OK;
690     }
691     else if (IsEqualGUID(riid, &IID_IAudioMediaStream))
692     {
693         IAMMediaStream_AddRef(iface);
694         *ret_iface = &This->IAudioMediaStream_iface;
695         return S_OK;
696     }
697     else if (IsEqualGUID(riid, &IID_IPin))
698     {
699         IAMMediaStream_AddRef(iface);
700         *ret_iface = &This->input_pin->pin.pin.IPin_iface;
701         return S_OK;
702     }
703     else if (IsEqualGUID(riid, &IID_IMemInputPin))
704     {
705         IAMMediaStream_AddRef(iface);
706         *ret_iface = &This->input_pin->pin.IMemInputPin_iface;
707         return S_OK;
708     }
709 
710     ERR("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ret_iface);
711     return E_NOINTERFACE;
712 }
713 
714 static ULONG WINAPI AudioMediaStreamImpl_IAMMediaStream_AddRef(IAMMediaStream *iface)
715 {
716     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
717     ULONG ref = InterlockedIncrement(&This->ref);
718 
719     TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
720 
721     return ref;
722 }
723 
724 static ULONG WINAPI AudioMediaStreamImpl_IAMMediaStream_Release(IAMMediaStream *iface)
725 {
726     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
727     ULONG ref = InterlockedDecrement(&This->ref);
728 
729     TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
730 
731     if (!ref)
732     {
733         BaseInputPin_Destroy((BaseInputPin *)This->input_pin);
734         DeleteCriticalSection(&This->critical_section);
735         HeapFree(GetProcessHeap(), 0, This);
736     }
737 
738     return ref;
739 }
740 
741 /*** IMediaStream methods ***/
742 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_GetMultiMediaStream(IAMMediaStream *iface,
743         IMultiMediaStream** multi_media_stream)
744 {
745     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
746 
747     TRACE("(%p/%p)->(%p)\n", This, iface, multi_media_stream);
748 
749     if (!multi_media_stream)
750         return E_POINTER;
751 
752     IMultiMediaStream_AddRef(This->parent);
753     *multi_media_stream = This->parent;
754 
755     return S_OK;
756 }
757 
758 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_GetInformation(IAMMediaStream *iface,
759         MSPID *purpose_id, STREAM_TYPE *type)
760 {
761     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
762 
763     TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
764 
765     if (purpose_id)
766         *purpose_id = This->purpose_id;
767     if (type)
768         *type = This->stream_type;
769 
770     return S_OK;
771 }
772 
773 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_SetSameFormat(IAMMediaStream *iface,
774         IMediaStream *pStreamThatHasDesiredFormat, DWORD flags)
775 {
776     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
777 
778     FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, flags);
779 
780     return S_FALSE;
781 }
782 
783 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_AllocateSample(IAMMediaStream *iface,
784         DWORD flags, IStreamSample **sample)
785 {
786     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
787 
788     FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, flags, sample);
789 
790     return S_FALSE;
791 }
792 
793 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_CreateSharedSample(IAMMediaStream *iface,
794         IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
795 {
796     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
797 
798     FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, existing_sample, flags, sample);
799 
800     return S_FALSE;
801 }
802 
803 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
804 {
805     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
806 
807     FIXME("(%p/%p)->(%x) stub!\n", This, iface, flags);
808 
809     return S_FALSE;
810 }
811 
812 /*** IAMMediaStream methods ***/
813 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_Initialize(IAMMediaStream *iface, IUnknown *source_object, DWORD flags,
814                                                     REFMSPID purpose_id, const STREAM_TYPE stream_type)
815 {
816     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
817 
818     FIXME("(%p/%p)->(%p,%x,%p,%u) stub!\n", This, iface, source_object, flags, purpose_id, stream_type);
819 
820     return S_FALSE;
821 }
822 
823 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_SetState(IAMMediaStream *iface, FILTER_STATE state)
824 {
825     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
826 
827     FIXME("(%p/%p)->(%u) stub!\n", This, iface, state);
828 
829     return S_FALSE;
830 }
831 
832 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *am_multi_media_stream)
833 {
834     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
835 
836     FIXME("(%p/%p)->(%p) stub!\n", This, iface, am_multi_media_stream);
837 
838     return S_FALSE;
839 }
840 
841 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *media_stream_filter)
842 {
843     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
844 
845     TRACE("(%p/%p)->(%p)\n", This, iface, media_stream_filter);
846 
847     This->input_pin->pin.pin.pinInfo.pFilter = (IBaseFilter *)media_stream_filter;
848 
849     return S_OK;
850 }
851 
852 static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *filtergraph)
853 {
854     AudioMediaStreamImpl *This = impl_from_AudioMediaStream_IAMMediaStream(iface);
855 
856     FIXME("(%p/%p)->(%p) stub!\n", This, iface, filtergraph);
857 
858     return S_FALSE;
859 }
860 
861 static const struct IAMMediaStreamVtbl AudioMediaStreamImpl_IAMMediaStream_Vtbl =
862 {
863     /*** IUnknown methods ***/
864     AudioMediaStreamImpl_IAMMediaStream_QueryInterface,
865     AudioMediaStreamImpl_IAMMediaStream_AddRef,
866     AudioMediaStreamImpl_IAMMediaStream_Release,
867     /*** IMediaStream methods ***/
868     AudioMediaStreamImpl_IAMMediaStream_GetMultiMediaStream,
869     AudioMediaStreamImpl_IAMMediaStream_GetInformation,
870     AudioMediaStreamImpl_IAMMediaStream_SetSameFormat,
871     AudioMediaStreamImpl_IAMMediaStream_AllocateSample,
872     AudioMediaStreamImpl_IAMMediaStream_CreateSharedSample,
873     AudioMediaStreamImpl_IAMMediaStream_SendEndOfStream,
874     /*** IAMMediaStream methods ***/
875     AudioMediaStreamImpl_IAMMediaStream_Initialize,
876     AudioMediaStreamImpl_IAMMediaStream_SetState,
877     AudioMediaStreamImpl_IAMMediaStream_JoinAMMultiMediaStream,
878     AudioMediaStreamImpl_IAMMediaStream_JoinFilter,
879     AudioMediaStreamImpl_IAMMediaStream_JoinFilterGraph
880 };
881 
882 static inline AudioMediaStreamImpl *impl_from_IAudioMediaStream(IAudioMediaStream *iface)
883 {
884     return CONTAINING_RECORD(iface, AudioMediaStreamImpl, IAudioMediaStream_iface);
885 }
886 
887 /*** IUnknown methods ***/
888 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_QueryInterface(IAudioMediaStream *iface,
889         REFIID riid, void **ret_iface)
890 {
891     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
892     TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
893     return IAMMediaStream_QueryInterface(&This->IAMMediaStream_iface, riid, ret_iface);
894 }
895 
896 static ULONG WINAPI AudioMediaStreamImpl_IAudioMediaStream_AddRef(IAudioMediaStream *iface)
897 {
898     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
899     TRACE("(%p/%p)\n", iface, This);
900     return IAMMediaStream_AddRef(&This->IAMMediaStream_iface);
901 }
902 
903 static ULONG WINAPI AudioMediaStreamImpl_IAudioMediaStream_Release(IAudioMediaStream *iface)
904 {
905     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
906     TRACE("(%p/%p)\n", iface, This);
907     return IAMMediaStream_Release(&This->IAMMediaStream_iface);
908 }
909 
910 /*** IMediaStream methods ***/
911 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_GetMultiMediaStream(IAudioMediaStream *iface,
912         IMultiMediaStream **multi_media_stream)
913 {
914     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
915 
916     TRACE("(%p/%p)->(%p)\n", iface, This, multi_media_stream);
917 
918     if (!multi_media_stream)
919         return E_POINTER;
920 
921     IMultiMediaStream_AddRef(This->parent);
922     *multi_media_stream = This->parent;
923 
924     return S_OK;
925 }
926 
927 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_GetInformation(IAudioMediaStream *iface,
928         MSPID *purpose_id, STREAM_TYPE *type)
929 {
930     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
931 
932     TRACE("(%p/%p)->(%p,%p)\n", iface, This, purpose_id, type);
933 
934     if (purpose_id)
935         *purpose_id = This->purpose_id;
936     if (type)
937         *type = This->stream_type;
938 
939     return S_OK;
940 }
941 
942 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_SetSameFormat(IAudioMediaStream *iface,
943         IMediaStream *stream_format, DWORD flags)
944 {
945     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
946 
947     FIXME("(%p/%p)->(%p,%x) stub!\n", iface, This, stream_format, flags);
948 
949     return S_FALSE;
950 }
951 
952 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_AllocateSample(IAudioMediaStream *iface,
953         DWORD flags, IStreamSample **sample)
954 {
955     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
956 
957     FIXME("(%p/%p)->(%x,%p) stub!\n", iface, This, flags, sample);
958 
959     return S_FALSE;
960 }
961 
962 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_CreateSharedSample(IAudioMediaStream *iface,
963         IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
964 {
965     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
966 
967     FIXME("(%p/%p)->(%p,%x,%p) stub!\n", iface, This, existing_sample, flags, sample);
968 
969     return S_FALSE;
970 }
971 
972 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_SendEndOfStream(IAudioMediaStream *iface,
973         DWORD flags)
974 {
975     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
976 
977     FIXME("(%p/%p)->(%x) stub!\n", iface, This, flags);
978 
979     return S_FALSE;
980 }
981 
982 /*** IAudioMediaStream methods ***/
983 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_GetFormat(IAudioMediaStream *iface, WAVEFORMATEX *wave_format_current)
984 {
985     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
986 
987     FIXME("(%p/%p)->(%p) stub!\n", iface, This, wave_format_current);
988 
989     if (!wave_format_current)
990         return E_POINTER;
991 
992     return MS_E_NOSTREAM;
993 
994 }
995 
996 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_SetFormat(IAudioMediaStream *iface, const WAVEFORMATEX *wave_format)
997 {
998     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
999 
1000     FIXME("(%p/%p)->(%p) stub!\n", iface, This, wave_format);
1001 
1002     return E_NOTIMPL;
1003 }
1004 
1005 static HRESULT WINAPI AudioMediaStreamImpl_IAudioMediaStream_CreateSample(IAudioMediaStream *iface, IAudioData *audio_data,
1006                                                          DWORD flags, IAudioStreamSample **sample)
1007 {
1008     AudioMediaStreamImpl *This = impl_from_IAudioMediaStream(iface);
1009 
1010     TRACE("(%p/%p)->(%p,%u,%p)\n", iface, This, audio_data, flags, sample);
1011 
1012     if (!audio_data)
1013         return E_POINTER;
1014 
1015     return audiostreamsample_create(iface, audio_data, sample);
1016 }
1017 
1018 static const struct IAudioMediaStreamVtbl AudioMediaStreamImpl_IAudioMediaStream_Vtbl =
1019 {
1020     /*** IUnknown methods ***/
1021     AudioMediaStreamImpl_IAudioMediaStream_QueryInterface,
1022     AudioMediaStreamImpl_IAudioMediaStream_AddRef,
1023     AudioMediaStreamImpl_IAudioMediaStream_Release,
1024     /*** IMediaStream methods ***/
1025     AudioMediaStreamImpl_IAudioMediaStream_GetMultiMediaStream,
1026     AudioMediaStreamImpl_IAudioMediaStream_GetInformation,
1027     AudioMediaStreamImpl_IAudioMediaStream_SetSameFormat,
1028     AudioMediaStreamImpl_IAudioMediaStream_AllocateSample,
1029     AudioMediaStreamImpl_IAudioMediaStream_CreateSharedSample,
1030     AudioMediaStreamImpl_IAudioMediaStream_SendEndOfStream,
1031     /*** IAudioMediaStream methods ***/
1032     AudioMediaStreamImpl_IAudioMediaStream_GetFormat,
1033     AudioMediaStreamImpl_IAudioMediaStream_SetFormat,
1034     AudioMediaStreamImpl_IAudioMediaStream_CreateSample
1035 };
1036 
1037 static inline AudioMediaStreamInputPin *impl_from_AudioMediaStreamInputPin_IPin(IPin *iface)
1038 {
1039     return CONTAINING_RECORD(iface, AudioMediaStreamInputPin, pin.pin.IPin_iface);
1040 }
1041 
1042 /*** IUnknown methods ***/
1043 static HRESULT WINAPI AudioMediaStreamInputPin_IPin_QueryInterface(IPin *iface, REFIID riid, void **ret_iface)
1044 {
1045     AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(iface);
1046 
1047     return IAMMediaStream_QueryInterface(&This->parent->IAMMediaStream_iface, riid, ret_iface);
1048 }
1049 
1050 static ULONG WINAPI AudioMediaStreamInputPin_IPin_AddRef(IPin *iface)
1051 {
1052     AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(iface);
1053 
1054     return IAMMediaStream_AddRef(&This->parent->IAMMediaStream_iface);
1055 }
1056 
1057 static ULONG WINAPI AudioMediaStreamInputPin_IPin_Release(IPin *iface)
1058 {
1059     AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(iface);
1060 
1061     return IAMMediaStream_Release(&This->parent->IAMMediaStream_iface);
1062 }
1063 
1064 static const IPinVtbl AudioMediaStreamInputPin_IPin_Vtbl =
1065 {
1066     AudioMediaStreamInputPin_IPin_QueryInterface,
1067     AudioMediaStreamInputPin_IPin_AddRef,
1068     AudioMediaStreamInputPin_IPin_Release,
1069     BaseInputPinImpl_Connect,
1070     BaseInputPinImpl_ReceiveConnection,
1071     BasePinImpl_Disconnect,
1072     BasePinImpl_ConnectedTo,
1073     BasePinImpl_ConnectionMediaType,
1074     BasePinImpl_QueryPinInfo,
1075     BasePinImpl_QueryDirection,
1076     BasePinImpl_QueryId,
1077     BaseInputPinImpl_QueryAccept,
1078     BasePinImpl_EnumMediaTypes,
1079     BasePinImpl_QueryInternalConnections,
1080     BaseInputPinImpl_EndOfStream,
1081     BaseInputPinImpl_BeginFlush,
1082     BaseInputPinImpl_EndFlush,
1083     BaseInputPinImpl_NewSegment,
1084 };
1085 
1086 static HRESULT WINAPI AudioMediaStreamInputPin_CheckMediaType(BasePin *base, const AM_MEDIA_TYPE *media_type)
1087 {
1088     AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(&base->IPin_iface);
1089 
1090     TRACE("(%p)->(%p)\n", This, media_type);
1091 
1092     if (IsEqualGUID(&media_type->majortype, &MEDIATYPE_Audio))
1093     {
1094         if (IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_PCM))
1095         {
1096             TRACE("Audio sub-type %s matches\n", debugstr_guid(&media_type->subtype));
1097             return S_OK;
1098         }
1099     }
1100 
1101     return S_OK;
1102 }
1103 
1104 static LONG WINAPI AudioMediaStreamInputPin_GetMediaTypeVersion(BasePin *base)
1105 {
1106     return 0;
1107 }
1108 
1109 static HRESULT WINAPI AudioMediaStreamInputPin_GetMediaType(BasePin *base, int index, AM_MEDIA_TYPE *media_type)
1110 {
1111     AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(&base->IPin_iface);
1112 
1113     TRACE("(%p)->(%d,%p)\n", This, index, media_type);
1114 
1115     /* FIXME: Reset structure as we only fill majortype and minortype for now */
1116     ZeroMemory(media_type, sizeof(*media_type));
1117 
1118     if (index)
1119         return S_FALSE;
1120 
1121     media_type->majortype = MEDIATYPE_Audio;
1122     media_type->subtype = MEDIASUBTYPE_PCM;
1123 
1124     return S_OK;
1125 }
1126 
1127 static HRESULT WINAPI AudioMediaStreamInputPin_Receive(BaseInputPin *base, IMediaSample *sample)
1128 {
1129     AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(&base->pin.IPin_iface);
1130 
1131     FIXME("(%p)->(%p) stub!\n", This, sample);
1132 
1133     return E_NOTIMPL;
1134 }
1135 
1136 static const BaseInputPinFuncTable AudioMediaStreamInputPin_FuncTable =
1137 {
1138     {
1139         AudioMediaStreamInputPin_CheckMediaType,
1140         NULL,
1141         AudioMediaStreamInputPin_GetMediaTypeVersion,
1142         AudioMediaStreamInputPin_GetMediaType,
1143     },
1144     AudioMediaStreamInputPin_Receive,
1145 };
1146 
1147 HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_id,
1148         STREAM_TYPE stream_type, IAMMediaStream **media_stream)
1149 {
1150     AudioMediaStreamImpl *object;
1151     PIN_INFO pin_info;
1152     HRESULT hr;
1153 
1154     TRACE("(%p,%s,%p)\n", parent, debugstr_guid(purpose_id), media_stream);
1155 
1156     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AudioMediaStreamImpl));
1157     if (!object)
1158         return E_OUTOFMEMORY;
1159 
1160     object->IAMMediaStream_iface.lpVtbl = &AudioMediaStreamImpl_IAMMediaStream_Vtbl;
1161     object->IAudioMediaStream_iface.lpVtbl = &AudioMediaStreamImpl_IAudioMediaStream_Vtbl;
1162     object->ref = 1;
1163 
1164     InitializeCriticalSection(&object->critical_section);
1165 
1166     pin_info.pFilter = NULL;
1167     pin_info.dir = PINDIR_INPUT;
1168     pin_info.achName[0] = 'I';
1169     StringFromGUID2(purpose_id, pin_info.achName + 1, MAX_PIN_NAME - 1);
1170     hr = BaseInputPin_Construct(&AudioMediaStreamInputPin_IPin_Vtbl,
1171         sizeof(AudioMediaStreamInputPin), &pin_info, &AudioMediaStreamInputPin_FuncTable,
1172         &object->critical_section, NULL, (IPin **)&object->input_pin);
1173     if (FAILED(hr))
1174         goto out_object;
1175 
1176     object->input_pin->parent = object;
1177 
1178     object->parent = parent;
1179     object->purpose_id = *purpose_id;
1180     object->stream_type = stream_type;
1181 
1182     *media_stream = &object->IAMMediaStream_iface;
1183 
1184     return S_OK;
1185 
1186 out_object:
1187     HeapFree(GetProcessHeap(), 0, object);
1188 
1189     return hr;
1190 }
1191 
1192 typedef struct {
1193     IDirectDrawStreamSample IDirectDrawStreamSample_iface;
1194     LONG ref;
1195     IMediaStream *parent;
1196     IDirectDrawSurface *surface;
1197     RECT rect;
1198 } IDirectDrawStreamSampleImpl;
1199 
1200 static inline IDirectDrawStreamSampleImpl *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface)
1201 {
1202     return CONTAINING_RECORD(iface, IDirectDrawStreamSampleImpl, IDirectDrawStreamSample_iface);
1203 }
1204 
1205 /*** IUnknown methods ***/
1206 static HRESULT WINAPI IDirectDrawStreamSampleImpl_QueryInterface(IDirectDrawStreamSample *iface,
1207         REFIID riid, void **ret_iface)
1208 {
1209     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface);
1210 
1211     if (IsEqualGUID(riid, &IID_IUnknown) ||
1212         IsEqualGUID(riid, &IID_IStreamSample) ||
1213         IsEqualGUID(riid, &IID_IDirectDrawStreamSample))
1214     {
1215         IDirectDrawStreamSample_AddRef(iface);
1216         *ret_iface = iface;
1217         return S_OK;
1218     }
1219 
1220     *ret_iface = NULL;
1221 
1222     ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
1223     return E_NOINTERFACE;
1224 }
1225 
1226 static ULONG WINAPI IDirectDrawStreamSampleImpl_AddRef(IDirectDrawStreamSample *iface)
1227 {
1228     IDirectDrawStreamSampleImpl *This = impl_from_IDirectDrawStreamSample(iface);
1229     ULONG ref = InterlockedIncrement(&This->ref);
1230 
1231     TRACE("(%p)->(): new ref = %u\n", iface, ref);
1232 
1233     return ref;
1234 }
1235 
1236 static ULONG WINAPI IDirectDrawStreamSampleImpl_Release(IDirectDrawStreamSample *iface)
1237 {
1238     IDirectDrawStreamSampleImpl *This = impl_from_IDirectDrawStreamSample(iface);
1239     ULONG ref = InterlockedDecrement(&This->ref);
1240 
1241     TRACE("(%p)->(): new ref = %u\n", iface, ref);
1242 
1243     if (!ref)
1244     {
1245         if (This->surface)
1246             IDirectDrawSurface_Release(This->surface);
1247         IMediaStream_Release(This->parent);
1248         HeapFree(GetProcessHeap(), 0, This);
1249     }
1250 
1251     return ref;
1252 }
1253 
1254 /*** IStreamSample methods ***/
1255 static HRESULT WINAPI IDirectDrawStreamSampleImpl_GetMediaStream(IDirectDrawStreamSample *iface, IMediaStream **media_stream)
1256 {
1257     FIXME("(%p)->(%p): stub\n", iface, media_stream);
1258 
1259     return E_NOTIMPL;
1260 }
1261 
1262 static HRESULT WINAPI IDirectDrawStreamSampleImpl_GetSampleTimes(IDirectDrawStreamSample *iface, STREAM_TIME *start_time,
1263                                                                  STREAM_TIME *end_time, STREAM_TIME *current_time)
1264 {
1265     FIXME("(%p)->(%p,%p,%p): stub\n", iface, start_time, end_time, current_time);
1266 
1267     return E_NOTIMPL;
1268 }
1269 
1270 static HRESULT WINAPI IDirectDrawStreamSampleImpl_SetSampleTimes(IDirectDrawStreamSample *iface, const STREAM_TIME *start_time,
1271                                                                  const STREAM_TIME *end_time)
1272 {
1273     FIXME("(%p)->(%p,%p): stub\n", iface, start_time, end_time);
1274 
1275     return E_NOTIMPL;
1276 }
1277 
1278 static HRESULT WINAPI IDirectDrawStreamSampleImpl_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event,
1279                                                          PAPCFUNC func_APC, DWORD APC_data)
1280 {
1281     FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC, APC_data);
1282 
1283     return S_OK;
1284 }
1285 
1286 static HRESULT WINAPI IDirectDrawStreamSampleImpl_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)
1287 {
1288     FIXME("(%p)->(%x,%u): stub\n", iface, flags, milliseconds);
1289 
1290     return E_NOTIMPL;
1291 }
1292 
1293 /*** IDirectDrawStreamSample methods ***/
1294 static HRESULT WINAPI IDirectDrawStreamSampleImpl_GetSurface(IDirectDrawStreamSample *iface, IDirectDrawSurface **ddraw_surface,
1295                                                              RECT *rect)
1296 {
1297     IDirectDrawStreamSampleImpl *This = impl_from_IDirectDrawStreamSample(iface);
1298 
1299     TRACE("(%p)->(%p,%p)\n", iface, ddraw_surface, rect);
1300 
1301     if (ddraw_surface)
1302     {
1303         *ddraw_surface = This->surface;
1304         if (*ddraw_surface)
1305             IDirectDrawSurface_AddRef(*ddraw_surface);
1306     }
1307 
1308     if (rect)
1309         *rect = This->rect;
1310 
1311     return S_OK;
1312 }
1313 
1314 static HRESULT WINAPI IDirectDrawStreamSampleImpl_SetRect(IDirectDrawStreamSample *iface, const RECT *rect)
1315 {
1316     FIXME("(%p)->(%p): stub\n", iface, rect);
1317 
1318     return E_NOTIMPL;
1319 }
1320 
1321 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl =
1322 {
1323     /*** IUnknown methods ***/
1324     IDirectDrawStreamSampleImpl_QueryInterface,
1325     IDirectDrawStreamSampleImpl_AddRef,
1326     IDirectDrawStreamSampleImpl_Release,
1327     /*** IStreamSample methods ***/
1328     IDirectDrawStreamSampleImpl_GetMediaStream,
1329     IDirectDrawStreamSampleImpl_GetSampleTimes,
1330     IDirectDrawStreamSampleImpl_SetSampleTimes,
1331     IDirectDrawStreamSampleImpl_Update,
1332     IDirectDrawStreamSampleImpl_CompletionStatus,
1333     /*** IDirectDrawStreamSample methods ***/
1334     IDirectDrawStreamSampleImpl_GetSurface,
1335     IDirectDrawStreamSampleImpl_SetRect
1336 };
1337 
1338 static HRESULT ddrawstreamsample_create(IDirectDrawMediaStream *parent, IDirectDrawSurface *surface,
1339     const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample)
1340 {
1341     IDirectDrawStreamSampleImpl *object;
1342     HRESULT hr;
1343 
1344     TRACE("(%p)\n", ddraw_stream_sample);
1345 
1346     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1347     if (!object)
1348         return E_OUTOFMEMORY;
1349 
1350     object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl;
1351     object->ref = 1;
1352     object->parent = (IMediaStream*)parent;
1353     IMediaStream_AddRef(object->parent);
1354 
1355     if (surface)
1356     {
1357         object->surface = surface;
1358         IDirectDrawSurface_AddRef(surface);
1359     }
1360     else
1361     {
1362         DDSURFACEDESC desc;
1363         IDirectDraw *ddraw;
1364 
1365         hr = IDirectDrawMediaStream_GetDirectDraw(parent, &ddraw);
1366         if (FAILED(hr))
1367         {
1368             IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1369             return hr;
1370         }
1371 
1372         desc.dwSize = sizeof(desc);
1373         desc.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
1374         desc.dwHeight = 100;
1375         desc.dwWidth = 100;
1376         desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
1377         desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1378         desc.ddpfPixelFormat.dwRGBBitCount = 32;
1379         desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
1380         desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
1381         desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
1382         desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
1383         desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN;
1384         desc.lpSurface = NULL;
1385 
1386         hr = IDirectDraw_CreateSurface(ddraw, &desc, &object->surface, NULL);
1387         IDirectDraw_Release(ddraw);
1388         if (FAILED(hr))
1389         {
1390             ERR("failed to create surface, 0x%08x\n", hr);
1391             IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1392             return hr;
1393         }
1394     }
1395 
1396     if (rect)
1397         object->rect = *rect;
1398     else if (object->surface)
1399     {
1400         DDSURFACEDESC desc = { sizeof(desc) };
1401         hr = IDirectDrawSurface_GetSurfaceDesc(object->surface, &desc);
1402         if (hr == S_OK)
1403             SetRect(&object->rect, 0, 0, desc.dwWidth, desc.dwHeight);
1404     }
1405 
1406     *ddraw_stream_sample = &object->IDirectDrawStreamSample_iface;
1407 
1408     return S_OK;
1409 }
1410 
1411 typedef struct {
1412     IAudioStreamSample IAudioStreamSample_iface;
1413     LONG ref;
1414     IMediaStream *parent;
1415     IAudioData *audio_data;
1416 } IAudioStreamSampleImpl;
1417 
1418 static inline IAudioStreamSampleImpl *impl_from_IAudioStreamSample(IAudioStreamSample *iface)
1419 {
1420     return CONTAINING_RECORD(iface, IAudioStreamSampleImpl, IAudioStreamSample_iface);
1421 }
1422 
1423 /*** IUnknown methods ***/
1424 static HRESULT WINAPI IAudioStreamSampleImpl_QueryInterface(IAudioStreamSample *iface,
1425         REFIID riid, void **ret_iface)
1426 {
1427     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface);
1428 
1429     if (IsEqualGUID(riid, &IID_IUnknown) ||
1430         IsEqualGUID(riid, &IID_IStreamSample) ||
1431         IsEqualGUID(riid, &IID_IAudioStreamSample))
1432     {
1433         IAudioStreamSample_AddRef(iface);
1434         *ret_iface = iface;
1435         return S_OK;
1436     }
1437 
1438     *ret_iface = NULL;
1439 
1440     ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
1441     return E_NOINTERFACE;
1442 }
1443 
1444 static ULONG WINAPI IAudioStreamSampleImpl_AddRef(IAudioStreamSample *iface)
1445 {
1446     IAudioStreamSampleImpl *This = impl_from_IAudioStreamSample(iface);
1447     ULONG ref = InterlockedIncrement(&This->ref);
1448 
1449     TRACE("(%p)->(): new ref = %u\n", iface, ref);
1450 
1451     return ref;
1452 }
1453 
1454 static ULONG WINAPI IAudioStreamSampleImpl_Release(IAudioStreamSample *iface)
1455 {
1456     IAudioStreamSampleImpl *This = impl_from_IAudioStreamSample(iface);
1457     ULONG ref = InterlockedDecrement(&This->ref);
1458 
1459     TRACE("(%p)->(): new ref = %u\n", iface, ref);
1460 
1461     if (!ref)
1462         HeapFree(GetProcessHeap(), 0, This);
1463 
1464     return ref;
1465 }
1466 
1467 /*** IStreamSample methods ***/
1468 static HRESULT WINAPI IAudioStreamSampleImpl_GetMediaStream(IAudioStreamSample *iface, IMediaStream **media_stream)
1469 {
1470     FIXME("(%p)->(%p): stub\n", iface, media_stream);
1471 
1472     return E_NOTIMPL;
1473 }
1474 
1475 static HRESULT WINAPI IAudioStreamSampleImpl_GetSampleTimes(IAudioStreamSample *iface, STREAM_TIME *start_time,
1476                                                                  STREAM_TIME *end_time, STREAM_TIME *current_time)
1477 {
1478     FIXME("(%p)->(%p,%p,%p): stub\n", iface, start_time, end_time, current_time);
1479 
1480     return E_NOTIMPL;
1481 }
1482 
1483 static HRESULT WINAPI IAudioStreamSampleImpl_SetSampleTimes(IAudioStreamSample *iface, const STREAM_TIME *start_time,
1484                                                                  const STREAM_TIME *end_time)
1485 {
1486     FIXME("(%p)->(%p,%p): stub\n", iface, start_time, end_time);
1487 
1488     return E_NOTIMPL;
1489 }
1490 
1491 static HRESULT WINAPI IAudioStreamSampleImpl_Update(IAudioStreamSample *iface, DWORD flags, HANDLE event,
1492                                                          PAPCFUNC func_APC, DWORD APC_data)
1493 {
1494     FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC, APC_data);
1495 
1496     return E_NOTIMPL;
1497 }
1498 
1499 static HRESULT WINAPI IAudioStreamSampleImpl_CompletionStatus(IAudioStreamSample *iface, DWORD flags, DWORD milliseconds)
1500 {
1501     FIXME("(%p)->(%x,%u): stub\n", iface, flags, milliseconds);
1502 
1503     return E_NOTIMPL;
1504 }
1505 
1506 /*** IAudioStreamSample methods ***/
1507 static HRESULT WINAPI IAudioStreamSampleImpl_GetAudioData(IAudioStreamSample *iface, IAudioData **audio_data)
1508 {
1509     FIXME("(%p)->(%p): stub\n", iface, audio_data);
1510 
1511     return E_NOTIMPL;
1512 }
1513 
1514 static const struct IAudioStreamSampleVtbl AudioStreamSample_Vtbl =
1515 {
1516     /*** IUnknown methods ***/
1517     IAudioStreamSampleImpl_QueryInterface,
1518     IAudioStreamSampleImpl_AddRef,
1519     IAudioStreamSampleImpl_Release,
1520     /*** IStreamSample methods ***/
1521     IAudioStreamSampleImpl_GetMediaStream,
1522     IAudioStreamSampleImpl_GetSampleTimes,
1523     IAudioStreamSampleImpl_SetSampleTimes,
1524     IAudioStreamSampleImpl_Update,
1525     IAudioStreamSampleImpl_CompletionStatus,
1526     /*** IAudioStreamSample methods ***/
1527     IAudioStreamSampleImpl_GetAudioData
1528 };
1529 
1530 static HRESULT audiostreamsample_create(IAudioMediaStream *parent, IAudioData *audio_data, IAudioStreamSample **audio_stream_sample)
1531 {
1532     IAudioStreamSampleImpl *object;
1533 
1534     TRACE("(%p)\n", audio_stream_sample);
1535 
1536     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAudioStreamSampleImpl));
1537     if (!object)
1538         return E_OUTOFMEMORY;
1539 
1540     object->IAudioStreamSample_iface.lpVtbl = &AudioStreamSample_Vtbl;
1541     object->ref = 1;
1542     object->parent = (IMediaStream*)parent;
1543     object->audio_data = audio_data;
1544 
1545     *audio_stream_sample = (IAudioStreamSample*)&object->IAudioStreamSample_iface;
1546 
1547     return S_OK;
1548 }
1549