ntdll: Add a helper for platform-specific threading initialization.
[wine.git] / dlls / amstream / ddrawstream.c
blob9c552f1a03f702224c17477f23e77ffcc559b8a3
1 /*
2 * Primary DirectDraw video stream
4 * Copyright 2005, 2008, 2012 Christian Costa
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.
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.
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
21 #define NONAMELESSUNION
22 #define COBJMACROS
23 #include "amstream_private.h"
24 #include "wine/debug.h"
25 #include "wine/strmbase.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
29 static const WCHAR sink_id[] = L"I{A35FF56A-9FDA-11D0-8FDF-00C04FD9189D}";
31 static HRESULT ddrawstreamsample_create(IDirectDrawMediaStream *parent, IDirectDrawSurface *surface,
32 const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
34 struct ddraw_stream
36 IAMMediaStream IAMMediaStream_iface;
37 IDirectDrawMediaStream IDirectDrawMediaStream_iface;
38 IMemInputPin IMemInputPin_iface;
39 IPin IPin_iface;
40 LONG ref;
42 IMultiMediaStream* parent;
43 MSPID purpose_id;
44 STREAM_TYPE stream_type;
45 IDirectDraw7 *ddraw;
46 CRITICAL_SECTION cs;
47 IMediaStreamFilter *filter;
49 IPin *peer;
50 IMemAllocator *allocator;
51 AM_MEDIA_TYPE mt;
54 static inline struct ddraw_stream *impl_from_IAMMediaStream(IAMMediaStream *iface)
56 return CONTAINING_RECORD(iface, struct ddraw_stream, IAMMediaStream_iface);
59 /*** IUnknown methods ***/
60 static HRESULT WINAPI ddraw_IAMMediaStream_QueryInterface(IAMMediaStream *iface,
61 REFIID riid, void **ret_iface)
63 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
65 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
67 if (IsEqualGUID(riid, &IID_IUnknown) ||
68 IsEqualGUID(riid, &IID_IMediaStream) ||
69 IsEqualGUID(riid, &IID_IAMMediaStream))
71 IAMMediaStream_AddRef(iface);
72 *ret_iface = iface;
73 return S_OK;
75 else if (IsEqualGUID(riid, &IID_IDirectDrawMediaStream))
77 IAMMediaStream_AddRef(iface);
78 *ret_iface = &This->IDirectDrawMediaStream_iface;
79 return S_OK;
81 else if (IsEqualGUID(riid, &IID_IPin))
83 IAMMediaStream_AddRef(iface);
84 *ret_iface = &This->IPin_iface;
85 return S_OK;
87 else if (IsEqualGUID(riid, &IID_IMemInputPin))
89 IAMMediaStream_AddRef(iface);
90 *ret_iface = &This->IMemInputPin_iface;
91 return S_OK;
94 ERR("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ret_iface);
95 return E_NOINTERFACE;
98 static ULONG WINAPI ddraw_IAMMediaStream_AddRef(IAMMediaStream *iface)
100 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
101 ULONG ref = InterlockedIncrement(&This->ref);
103 TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
105 return ref;
108 static ULONG WINAPI ddraw_IAMMediaStream_Release(IAMMediaStream *iface)
110 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
111 ULONG ref = InterlockedDecrement(&This->ref);
113 TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
115 if (!ref)
117 DeleteCriticalSection(&This->cs);
118 if (This->ddraw)
119 IDirectDraw7_Release(This->ddraw);
120 HeapFree(GetProcessHeap(), 0, This);
123 return ref;
126 /*** IMediaStream methods ***/
127 static HRESULT WINAPI ddraw_IAMMediaStream_GetMultiMediaStream(IAMMediaStream *iface,
128 IMultiMediaStream** multi_media_stream)
130 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
132 TRACE("(%p/%p)->(%p)\n", This, iface, multi_media_stream);
134 if (!multi_media_stream)
135 return E_POINTER;
137 IMultiMediaStream_AddRef(This->parent);
138 *multi_media_stream = This->parent;
140 return S_OK;
143 static HRESULT WINAPI ddraw_IAMMediaStream_GetInformation(IAMMediaStream *iface,
144 MSPID *purpose_id, STREAM_TYPE *type)
146 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
148 TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
150 if (purpose_id)
151 *purpose_id = This->purpose_id;
152 if (type)
153 *type = This->stream_type;
155 return S_OK;
158 static HRESULT WINAPI ddraw_IAMMediaStream_SetSameFormat(IAMMediaStream *iface,
159 IMediaStream *pStreamThatHasDesiredFormat, DWORD flags)
161 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
163 FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, flags);
165 return S_FALSE;
168 static HRESULT WINAPI ddraw_IAMMediaStream_AllocateSample(IAMMediaStream *iface,
169 DWORD flags, IStreamSample **sample)
171 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
173 FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, flags, sample);
175 return S_FALSE;
178 static HRESULT WINAPI ddraw_IAMMediaStream_CreateSharedSample(IAMMediaStream *iface,
179 IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
181 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
183 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, existing_sample, flags, sample);
185 return S_FALSE;
188 static HRESULT WINAPI ddraw_IAMMediaStream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
190 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
192 FIXME("(%p/%p)->(%x) stub!\n", This, iface, flags);
194 return S_FALSE;
197 /*** IAMMediaStream methods ***/
198 static HRESULT WINAPI ddraw_IAMMediaStream_Initialize(IAMMediaStream *iface, IUnknown *source_object, DWORD flags,
199 REFMSPID purpose_id, const STREAM_TYPE stream_type)
201 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
203 FIXME("(%p/%p)->(%p,%x,%p,%u) stub!\n", This, iface, source_object, flags, purpose_id, stream_type);
205 return S_FALSE;
208 static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTER_STATE state)
210 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
212 FIXME("(%p/%p)->(%u) stub!\n", This, iface, state);
214 return S_FALSE;
217 static HRESULT WINAPI ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *am_multi_media_stream)
219 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
221 FIXME("(%p/%p)->(%p) stub!\n", This, iface, am_multi_media_stream);
223 return S_FALSE;
226 static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
228 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
230 TRACE("iface %p, filter %p.\n", iface, filter);
232 stream->filter = filter;
234 return S_OK;
237 static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *filtergraph)
239 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
241 FIXME("(%p/%p)->(%p) stub!\n", This, iface, filtergraph);
243 return S_FALSE;
246 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl =
248 /*** IUnknown methods ***/
249 ddraw_IAMMediaStream_QueryInterface,
250 ddraw_IAMMediaStream_AddRef,
251 ddraw_IAMMediaStream_Release,
252 /*** IMediaStream methods ***/
253 ddraw_IAMMediaStream_GetMultiMediaStream,
254 ddraw_IAMMediaStream_GetInformation,
255 ddraw_IAMMediaStream_SetSameFormat,
256 ddraw_IAMMediaStream_AllocateSample,
257 ddraw_IAMMediaStream_CreateSharedSample,
258 ddraw_IAMMediaStream_SendEndOfStream,
259 /*** IAMMediaStream methods ***/
260 ddraw_IAMMediaStream_Initialize,
261 ddraw_IAMMediaStream_SetState,
262 ddraw_IAMMediaStream_JoinAMMultiMediaStream,
263 ddraw_IAMMediaStream_JoinFilter,
264 ddraw_IAMMediaStream_JoinFilterGraph
267 static inline struct ddraw_stream *impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream *iface)
269 return CONTAINING_RECORD(iface, struct ddraw_stream, IDirectDrawMediaStream_iface);
272 /*** IUnknown methods ***/
273 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream *iface,
274 REFIID riid, void **ret_iface)
276 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
277 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
278 return IAMMediaStream_QueryInterface(&This->IAMMediaStream_iface, riid, ret_iface);
281 static ULONG WINAPI ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream *iface)
283 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
284 TRACE("(%p/%p)\n", iface, This);
285 return IAMMediaStream_AddRef(&This->IAMMediaStream_iface);
288 static ULONG WINAPI ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream *iface)
290 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
291 TRACE("(%p/%p)\n", iface, This);
292 return IAMMediaStream_Release(&This->IAMMediaStream_iface);
295 /*** IMediaStream methods ***/
296 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream *iface,
297 IMultiMediaStream **multi_media_stream)
299 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
301 TRACE("(%p/%p)->(%p)\n", This, iface, multi_media_stream);
303 if (!multi_media_stream)
304 return E_POINTER;
306 IMultiMediaStream_AddRef(This->parent);
307 *multi_media_stream = This->parent;
309 return S_OK;
312 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream *iface,
313 MSPID *purpose_id, STREAM_TYPE *type)
315 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
317 TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
319 if (purpose_id)
320 *purpose_id = This->purpose_id;
321 if (type)
322 *type = This->stream_type;
324 return S_OK;
327 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream *iface,
328 IMediaStream *pStreamThatHasDesiredFormat, DWORD dwFlags)
330 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
332 FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, dwFlags);
334 return S_FALSE;
337 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream *iface,
338 DWORD dwFlags, IStreamSample **ppSample)
340 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
342 FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, dwFlags, ppSample);
344 return S_FALSE;
347 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream *iface,
348 IStreamSample *pExistingSample, DWORD dwFlags, IStreamSample **ppSample)
350 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
352 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, pExistingSample, dwFlags, ppSample);
354 return S_FALSE;
357 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream *iface,
358 DWORD dwFlags)
360 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
362 FIXME("(%p/%p)->(%x) stub!\n", This, iface, dwFlags);
364 return S_FALSE;
367 /*** IDirectDrawMediaStream methods ***/
368 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream *iface,
369 DDSURFACEDESC *current_format, IDirectDrawPalette **palette,
370 DDSURFACEDESC *desired_format, DWORD *flags)
372 FIXME("(%p)->(%p,%p,%p,%p) stub!\n", iface, current_format, palette, desired_format,
373 flags);
375 return MS_E_NOSTREAM;
379 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream *iface,
380 const DDSURFACEDESC *pDDSurfaceDesc, IDirectDrawPalette *pDirectDrawPalette)
382 FIXME("(%p)->(%p,%p) stub!\n", iface, pDDSurfaceDesc, pDirectDrawPalette);
384 return E_NOTIMPL;
387 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream *iface,
388 IDirectDraw **ddraw)
390 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
392 TRACE("(%p)->(%p)\n", iface, ddraw);
394 *ddraw = NULL;
395 if (!This->ddraw)
397 HRESULT hr = DirectDrawCreateEx(NULL, (void**)&This->ddraw, &IID_IDirectDraw7, NULL);
398 if (FAILED(hr))
399 return hr;
400 IDirectDraw7_SetCooperativeLevel(This->ddraw, NULL, DDSCL_NORMAL);
403 return IDirectDraw7_QueryInterface(This->ddraw, &IID_IDirectDraw, (void**)ddraw);
406 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream *iface,
407 IDirectDraw *pDirectDraw)
409 FIXME("(%p)->(%p) stub!\n", iface, pDirectDraw);
411 return E_NOTIMPL;
414 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream *iface,
415 IDirectDrawSurface *surface, const RECT *rect, DWORD dwFlags,
416 IDirectDrawStreamSample **ppSample)
418 TRACE("(%p)->(%p,%s,%x,%p)\n", iface, surface, wine_dbgstr_rect(rect), dwFlags, ppSample);
420 return ddrawstreamsample_create(iface, surface, rect, ppSample);
423 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream *iface,
424 STREAM_TIME *pFrameTime)
426 FIXME("(%p)->(%p) stub!\n", iface, pFrameTime);
428 return E_NOTIMPL;
431 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl =
433 /*** IUnknown methods ***/
434 ddraw_IDirectDrawMediaStream_QueryInterface,
435 ddraw_IDirectDrawMediaStream_AddRef,
436 ddraw_IDirectDrawMediaStream_Release,
437 /*** IMediaStream methods ***/
438 ddraw_IDirectDrawMediaStream_GetMultiMediaStream,
439 ddraw_IDirectDrawMediaStream_GetInformation,
440 ddraw_IDirectDrawMediaStream_SetSameFormat,
441 ddraw_IDirectDrawMediaStream_AllocateSample,
442 ddraw_IDirectDrawMediaStream_CreateSharedSample,
443 ddraw_IDirectDrawMediaStream_SendEndOfStream,
444 /*** IDirectDrawMediaStream methods ***/
445 ddraw_IDirectDrawMediaStream_GetFormat,
446 ddraw_IDirectDrawMediaStream_SetFormat,
447 ddraw_IDirectDrawMediaStream_GetDirectDraw,
448 ddraw_IDirectDrawMediaStream_SetDirectDraw,
449 ddraw_IDirectDrawMediaStream_CreateSample,
450 ddraw_IDirectDrawMediaStream_GetTimePerFrame
453 struct enum_media_types
455 IEnumMediaTypes IEnumMediaTypes_iface;
456 LONG refcount;
457 unsigned int index;
460 static const IEnumMediaTypesVtbl enum_media_types_vtbl;
462 static struct enum_media_types *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
464 return CONTAINING_RECORD(iface, struct enum_media_types, IEnumMediaTypes_iface);
467 static HRESULT WINAPI enum_media_types_QueryInterface(IEnumMediaTypes *iface, REFIID iid, void **out)
469 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
471 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumMediaTypes))
473 IEnumMediaTypes_AddRef(iface);
474 *out = iface;
475 return S_OK;
478 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
479 *out = NULL;
480 return E_NOINTERFACE;
483 static ULONG WINAPI enum_media_types_AddRef(IEnumMediaTypes *iface)
485 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
486 ULONG refcount = InterlockedIncrement(&enum_media_types->refcount);
487 TRACE("%p increasing refcount to %u.\n", enum_media_types, refcount);
488 return refcount;
491 static ULONG WINAPI enum_media_types_Release(IEnumMediaTypes *iface)
493 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
494 ULONG refcount = InterlockedDecrement(&enum_media_types->refcount);
495 TRACE("%p decreasing refcount to %u.\n", enum_media_types, refcount);
496 if (!refcount)
497 heap_free(enum_media_types);
498 return refcount;
501 static HRESULT WINAPI enum_media_types_Next(IEnumMediaTypes *iface, ULONG count, AM_MEDIA_TYPE **mts, ULONG *ret_count)
503 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
505 TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface, count, mts, ret_count);
507 if (!ret_count)
508 return E_POINTER;
510 if (count && !enum_media_types->index)
512 mts[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
513 memset(mts[0], 0, sizeof(AM_MEDIA_TYPE));
514 mts[0]->majortype = MEDIATYPE_Video;
515 mts[0]->subtype = MEDIASUBTYPE_RGB8;
516 mts[0]->bFixedSizeSamples = TRUE;
517 mts[0]->lSampleSize = 10000;
518 ++enum_media_types->index;
519 *ret_count = 1;
520 return count == 1 ? S_OK : S_FALSE;
523 *ret_count = 0;
524 return count ? S_FALSE : S_OK;
527 static HRESULT WINAPI enum_media_types_Skip(IEnumMediaTypes *iface, ULONG count)
529 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
531 TRACE("iface %p, count %u.\n", iface, count);
533 enum_media_types->index += count;
535 return S_OK;
538 static HRESULT WINAPI enum_media_types_Reset(IEnumMediaTypes *iface)
540 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
542 TRACE("iface %p.\n", iface);
544 enum_media_types->index = 0;
545 return S_OK;
548 static HRESULT WINAPI enum_media_types_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **out)
550 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
551 struct enum_media_types *object;
553 TRACE("iface %p, out %p.\n", iface, out);
555 if (!(object = heap_alloc(sizeof(*object))))
556 return E_OUTOFMEMORY;
558 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
559 object->refcount = 1;
560 object->index = enum_media_types->index;
562 *out = &object->IEnumMediaTypes_iface;
563 return S_OK;
566 static const IEnumMediaTypesVtbl enum_media_types_vtbl =
568 enum_media_types_QueryInterface,
569 enum_media_types_AddRef,
570 enum_media_types_Release,
571 enum_media_types_Next,
572 enum_media_types_Skip,
573 enum_media_types_Reset,
574 enum_media_types_Clone,
577 static inline struct ddraw_stream *impl_from_IPin(IPin *iface)
579 return CONTAINING_RECORD(iface, struct ddraw_stream, IPin_iface);
582 static HRESULT WINAPI ddraw_sink_QueryInterface(IPin *iface, REFIID iid, void **out)
584 struct ddraw_stream *stream = impl_from_IPin(iface);
585 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
588 static ULONG WINAPI ddraw_sink_AddRef(IPin *iface)
590 struct ddraw_stream *stream = impl_from_IPin(iface);
591 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
594 static ULONG WINAPI ddraw_sink_Release(IPin *iface)
596 struct ddraw_stream *stream = impl_from_IPin(iface);
597 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
600 static HRESULT WINAPI ddraw_sink_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
602 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface, peer, mt);
603 return E_UNEXPECTED;
606 static BOOL check_media_type(const AM_MEDIA_TYPE *media_type)
608 if (IsEqualGUID(&media_type->majortype, &MEDIATYPE_Video))
610 if (IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB1) ||
611 IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB4) ||
612 IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB8) ||
613 IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB565) ||
614 IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB555) ||
615 IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB24) ||
616 IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_RGB32))
618 TRACE("Video sub-type %s matches\n", debugstr_guid(&media_type->subtype));
619 return TRUE;
623 return FALSE;
626 static HRESULT WINAPI ddraw_sink_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
628 struct ddraw_stream *stream = impl_from_IPin(iface);
629 PIN_DIRECTION dir;
631 TRACE("stream %p, peer %p, mt %p.\n", stream, peer, mt);
633 EnterCriticalSection(&stream->cs);
635 if (stream->peer)
637 LeaveCriticalSection(&stream->cs);
638 return VFW_E_ALREADY_CONNECTED;
641 if (!check_media_type(mt))
643 LeaveCriticalSection(&stream->cs);
644 return VFW_E_TYPE_NOT_ACCEPTED;
647 IPin_QueryDirection(peer, &dir);
648 if (dir != PINDIR_OUTPUT)
650 WARN("Rejecting connection from input pin.\n");
651 LeaveCriticalSection(&stream->cs);
652 return VFW_E_INVALID_DIRECTION;
655 CopyMediaType(&stream->mt, mt);
656 IPin_AddRef(stream->peer = peer);
658 LeaveCriticalSection(&stream->cs);
660 return S_OK;
663 static HRESULT WINAPI ddraw_sink_Disconnect(IPin *iface)
665 struct ddraw_stream *stream = impl_from_IPin(iface);
667 TRACE("stream %p.\n", stream);
669 EnterCriticalSection(&stream->cs);
671 if (!stream->peer)
673 LeaveCriticalSection(&stream->cs);
674 return S_FALSE;
677 IPin_Release(stream->peer);
678 stream->peer = NULL;
679 FreeMediaType(&stream->mt);
680 memset(&stream->mt, 0, sizeof(AM_MEDIA_TYPE));
682 LeaveCriticalSection(&stream->cs);
684 return S_OK;
687 static HRESULT WINAPI ddraw_sink_ConnectedTo(IPin *iface, IPin **peer)
689 struct ddraw_stream *stream = impl_from_IPin(iface);
690 HRESULT hr;
692 TRACE("stream %p, peer %p.\n", stream, peer);
694 EnterCriticalSection(&stream->cs);
696 if (stream->peer)
698 IPin_AddRef(*peer = stream->peer);
699 hr = S_OK;
701 else
703 *peer = NULL;
704 hr = VFW_E_NOT_CONNECTED;
707 LeaveCriticalSection(&stream->cs);
709 return hr;
712 static HRESULT WINAPI ddraw_sink_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
714 struct ddraw_stream *stream = impl_from_IPin(iface);
715 HRESULT hr;
717 TRACE("stream %p, mt %p.\n", stream, mt);
719 EnterCriticalSection(&stream->cs);
721 if (stream->peer)
723 CopyMediaType(mt, &stream->mt);
724 hr = S_OK;
726 else
728 memset(mt, 0, sizeof(AM_MEDIA_TYPE));
729 hr = VFW_E_NOT_CONNECTED;
732 LeaveCriticalSection(&stream->cs);
734 return hr;
737 static HRESULT WINAPI ddraw_sink_QueryPinInfo(IPin *iface, PIN_INFO *info)
739 struct ddraw_stream *stream = impl_from_IPin(iface);
741 TRACE("stream %p, info %p.\n", stream, info);
743 IBaseFilter_AddRef(info->pFilter = (IBaseFilter *)stream->filter);
744 info->dir = PINDIR_INPUT;
745 wcscpy(info->achName, sink_id);
747 return S_OK;
750 static HRESULT WINAPI ddraw_sink_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
752 TRACE("iface %p, dir %p.\n", iface, dir);
753 *dir = PINDIR_INPUT;
754 return S_OK;
757 static HRESULT WINAPI ddraw_sink_QueryId(IPin *iface, WCHAR **id)
759 TRACE("iface %p, id %p.\n", iface, id);
761 if (!(*id = CoTaskMemAlloc(sizeof(sink_id))))
762 return E_OUTOFMEMORY;
764 wcscpy(*id, sink_id);
766 return S_OK;
769 static HRESULT WINAPI ddraw_sink_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
771 TRACE("iface %p, mt %p.\n", iface, mt);
772 return check_media_type(mt) ? S_OK : S_FALSE;
775 static HRESULT WINAPI ddraw_sink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types)
777 struct enum_media_types *object;
779 TRACE("iface %p, enum_media_types %p.\n", iface, enum_media_types);
781 if (!enum_media_types)
782 return E_POINTER;
784 if (!(object = heap_alloc(sizeof(*object))))
785 return E_OUTOFMEMORY;
787 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
788 object->refcount = 1;
789 object->index = 0;
791 *enum_media_types = &object->IEnumMediaTypes_iface;
792 return S_OK;
795 static HRESULT WINAPI ddraw_sink_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
797 TRACE("iface %p, pins %p, count %p.\n", iface, pins, count);
798 return E_NOTIMPL;
801 static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
803 FIXME("iface %p, stub!\n", iface);
804 return E_NOTIMPL;
807 static HRESULT WINAPI ddraw_sink_BeginFlush(IPin *iface)
809 FIXME("iface %p, stub!\n", iface);
810 return E_NOTIMPL;
813 static HRESULT WINAPI ddraw_sink_EndFlush(IPin *iface)
815 FIXME("iface %p, stub!\n", iface);
816 return E_NOTIMPL;
819 static HRESULT WINAPI ddraw_sink_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
821 FIXME("iface %p, start %s, stop %s, rate %0.16e, stub!\n",
822 iface, wine_dbgstr_longlong(start), wine_dbgstr_longlong(stop), rate);
823 return E_NOTIMPL;
826 static const IPinVtbl ddraw_sink_vtbl =
828 ddraw_sink_QueryInterface,
829 ddraw_sink_AddRef,
830 ddraw_sink_Release,
831 ddraw_sink_Connect,
832 ddraw_sink_ReceiveConnection,
833 ddraw_sink_Disconnect,
834 ddraw_sink_ConnectedTo,
835 ddraw_sink_ConnectionMediaType,
836 ddraw_sink_QueryPinInfo,
837 ddraw_sink_QueryDirection,
838 ddraw_sink_QueryId,
839 ddraw_sink_QueryAccept,
840 ddraw_sink_EnumMediaTypes,
841 ddraw_sink_QueryInternalConnections,
842 ddraw_sink_EndOfStream,
843 ddraw_sink_BeginFlush,
844 ddraw_sink_EndFlush,
845 ddraw_sink_NewSegment,
848 static inline struct ddraw_stream *impl_from_IMemInputPin(IMemInputPin *iface)
850 return CONTAINING_RECORD(iface, struct ddraw_stream, IMemInputPin_iface);
853 static HRESULT WINAPI ddraw_meminput_QueryInterface(IMemInputPin *iface, REFIID iid, void **out)
855 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
856 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
859 static ULONG WINAPI ddraw_meminput_AddRef(IMemInputPin *iface)
861 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
862 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
865 static ULONG WINAPI ddraw_meminput_Release(IMemInputPin *iface)
867 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
868 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
871 static HRESULT WINAPI ddraw_meminput_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
873 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
875 TRACE("stream %p, allocator %p.\n", stream, allocator);
877 if (stream->allocator)
879 IMemAllocator_AddRef(*allocator = stream->allocator);
880 return S_OK;
883 *allocator = NULL;
884 return VFW_E_NO_ALLOCATOR;
887 static HRESULT WINAPI ddraw_meminput_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readonly)
889 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
891 TRACE("stream %p, allocator %p, readonly %d.\n", stream, allocator, readonly);
893 if (!allocator)
894 return E_POINTER;
896 if (allocator)
897 IMemAllocator_AddRef(allocator);
898 if (stream->allocator)
899 IMemAllocator_Release(stream->allocator);
900 stream->allocator = allocator;
902 return S_OK;
905 static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
907 TRACE("iface %p, props %p.\n", iface, props);
908 return E_NOTIMPL;
911 static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample)
913 FIXME("iface %p, sample %p, stub!\n", iface, sample);
914 return E_NOTIMPL;
917 static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface,
918 IMediaSample **samples, LONG count, LONG *processed)
920 FIXME("iface %p, samples %p, count %u, processed %p, stub!\n", iface, samples, count, processed);
921 return E_NOTIMPL;
924 static HRESULT WINAPI ddraw_meminput_ReceiveCanBlock(IMemInputPin *iface)
926 TRACE("iface %p.\n", iface);
927 return S_OK;
930 static const IMemInputPinVtbl ddraw_meminput_vtbl =
932 ddraw_meminput_QueryInterface,
933 ddraw_meminput_AddRef,
934 ddraw_meminput_Release,
935 ddraw_meminput_GetAllocator,
936 ddraw_meminput_NotifyAllocator,
937 ddraw_meminput_GetAllocatorRequirements,
938 ddraw_meminput_Receive,
939 ddraw_meminput_ReceiveMultiple,
940 ddraw_meminput_ReceiveCanBlock,
943 HRESULT ddraw_stream_create(IMultiMediaStream *parent, const MSPID *purpose_id,
944 IUnknown *stream_object, STREAM_TYPE stream_type, IAMMediaStream **media_stream)
946 struct ddraw_stream *object;
947 HRESULT hr;
949 TRACE("(%p,%s,%p,%p)\n", parent, debugstr_guid(purpose_id), stream_object, media_stream);
951 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
952 if (!object)
953 return E_OUTOFMEMORY;
955 object->IAMMediaStream_iface.lpVtbl = &ddraw_IAMMediaStream_vtbl;
956 object->IDirectDrawMediaStream_iface.lpVtbl = &ddraw_IDirectDrawMediaStream_Vtbl;
957 object->IMemInputPin_iface.lpVtbl = &ddraw_meminput_vtbl;
958 object->IPin_iface.lpVtbl = &ddraw_sink_vtbl;
959 object->ref = 1;
961 InitializeCriticalSection(&object->cs);
963 object->parent = parent;
964 object->purpose_id = *purpose_id;
965 object->stream_type = stream_type;
967 if (stream_object
968 && FAILED(hr = IUnknown_QueryInterface(stream_object, &IID_IDirectDraw7, (void **)&object->ddraw)))
969 FIXME("Stream object doesn't implement IDirectDraw7 interface, hr %#x.\n", hr);
971 *media_stream = &object->IAMMediaStream_iface;
973 return S_OK;
976 typedef struct {
977 IDirectDrawStreamSample IDirectDrawStreamSample_iface;
978 LONG ref;
979 IMediaStream *parent;
980 IDirectDrawSurface *surface;
981 RECT rect;
982 } IDirectDrawStreamSampleImpl;
984 static inline IDirectDrawStreamSampleImpl *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface)
986 return CONTAINING_RECORD(iface, IDirectDrawStreamSampleImpl, IDirectDrawStreamSample_iface);
989 /*** IUnknown methods ***/
990 static HRESULT WINAPI IDirectDrawStreamSampleImpl_QueryInterface(IDirectDrawStreamSample *iface,
991 REFIID riid, void **ret_iface)
993 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface);
995 if (IsEqualGUID(riid, &IID_IUnknown) ||
996 IsEqualGUID(riid, &IID_IStreamSample) ||
997 IsEqualGUID(riid, &IID_IDirectDrawStreamSample))
999 IDirectDrawStreamSample_AddRef(iface);
1000 *ret_iface = iface;
1001 return S_OK;
1004 *ret_iface = NULL;
1006 ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
1007 return E_NOINTERFACE;
1010 static ULONG WINAPI IDirectDrawStreamSampleImpl_AddRef(IDirectDrawStreamSample *iface)
1012 IDirectDrawStreamSampleImpl *This = impl_from_IDirectDrawStreamSample(iface);
1013 ULONG ref = InterlockedIncrement(&This->ref);
1015 TRACE("(%p)->(): new ref = %u\n", iface, ref);
1017 return ref;
1020 static ULONG WINAPI IDirectDrawStreamSampleImpl_Release(IDirectDrawStreamSample *iface)
1022 IDirectDrawStreamSampleImpl *This = impl_from_IDirectDrawStreamSample(iface);
1023 ULONG ref = InterlockedDecrement(&This->ref);
1025 TRACE("(%p)->(): new ref = %u\n", iface, ref);
1027 if (!ref)
1029 if (This->surface)
1030 IDirectDrawSurface_Release(This->surface);
1031 IMediaStream_Release(This->parent);
1032 HeapFree(GetProcessHeap(), 0, This);
1035 return ref;
1038 /*** IStreamSample methods ***/
1039 static HRESULT WINAPI IDirectDrawStreamSampleImpl_GetMediaStream(IDirectDrawStreamSample *iface, IMediaStream **media_stream)
1041 FIXME("(%p)->(%p): stub\n", iface, media_stream);
1043 return E_NOTIMPL;
1046 static HRESULT WINAPI IDirectDrawStreamSampleImpl_GetSampleTimes(IDirectDrawStreamSample *iface, STREAM_TIME *start_time,
1047 STREAM_TIME *end_time, STREAM_TIME *current_time)
1049 FIXME("(%p)->(%p,%p,%p): stub\n", iface, start_time, end_time, current_time);
1051 return E_NOTIMPL;
1054 static HRESULT WINAPI IDirectDrawStreamSampleImpl_SetSampleTimes(IDirectDrawStreamSample *iface, const STREAM_TIME *start_time,
1055 const STREAM_TIME *end_time)
1057 FIXME("(%p)->(%p,%p): stub\n", iface, start_time, end_time);
1059 return E_NOTIMPL;
1062 static HRESULT WINAPI IDirectDrawStreamSampleImpl_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event,
1063 PAPCFUNC func_APC, DWORD APC_data)
1065 FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC, APC_data);
1067 return S_OK;
1070 static HRESULT WINAPI IDirectDrawStreamSampleImpl_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)
1072 FIXME("(%p)->(%x,%u): stub\n", iface, flags, milliseconds);
1074 return E_NOTIMPL;
1077 /*** IDirectDrawStreamSample methods ***/
1078 static HRESULT WINAPI IDirectDrawStreamSampleImpl_GetSurface(IDirectDrawStreamSample *iface, IDirectDrawSurface **ddraw_surface,
1079 RECT *rect)
1081 IDirectDrawStreamSampleImpl *This = impl_from_IDirectDrawStreamSample(iface);
1083 TRACE("(%p)->(%p,%p)\n", iface, ddraw_surface, rect);
1085 if (ddraw_surface)
1087 *ddraw_surface = This->surface;
1088 if (*ddraw_surface)
1089 IDirectDrawSurface_AddRef(*ddraw_surface);
1092 if (rect)
1093 *rect = This->rect;
1095 return S_OK;
1098 static HRESULT WINAPI IDirectDrawStreamSampleImpl_SetRect(IDirectDrawStreamSample *iface, const RECT *rect)
1100 FIXME("(%p)->(%p): stub\n", iface, rect);
1102 return E_NOTIMPL;
1105 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl =
1107 /*** IUnknown methods ***/
1108 IDirectDrawStreamSampleImpl_QueryInterface,
1109 IDirectDrawStreamSampleImpl_AddRef,
1110 IDirectDrawStreamSampleImpl_Release,
1111 /*** IStreamSample methods ***/
1112 IDirectDrawStreamSampleImpl_GetMediaStream,
1113 IDirectDrawStreamSampleImpl_GetSampleTimes,
1114 IDirectDrawStreamSampleImpl_SetSampleTimes,
1115 IDirectDrawStreamSampleImpl_Update,
1116 IDirectDrawStreamSampleImpl_CompletionStatus,
1117 /*** IDirectDrawStreamSample methods ***/
1118 IDirectDrawStreamSampleImpl_GetSurface,
1119 IDirectDrawStreamSampleImpl_SetRect
1122 static HRESULT ddrawstreamsample_create(IDirectDrawMediaStream *parent, IDirectDrawSurface *surface,
1123 const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample)
1125 IDirectDrawStreamSampleImpl *object;
1126 HRESULT hr;
1128 TRACE("(%p)\n", ddraw_stream_sample);
1130 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1131 if (!object)
1132 return E_OUTOFMEMORY;
1134 object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl;
1135 object->ref = 1;
1136 object->parent = (IMediaStream*)parent;
1137 IMediaStream_AddRef(object->parent);
1139 if (surface)
1141 object->surface = surface;
1142 IDirectDrawSurface_AddRef(surface);
1144 else
1146 DDSURFACEDESC desc;
1147 IDirectDraw *ddraw;
1149 hr = IDirectDrawMediaStream_GetDirectDraw(parent, &ddraw);
1150 if (FAILED(hr))
1152 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1153 return hr;
1156 desc.dwSize = sizeof(desc);
1157 desc.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
1158 desc.dwHeight = 100;
1159 desc.dwWidth = 100;
1160 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
1161 desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1162 desc.ddpfPixelFormat.u1.dwRGBBitCount = 32;
1163 desc.ddpfPixelFormat.u2.dwRBitMask = 0xff0000;
1164 desc.ddpfPixelFormat.u3.dwGBitMask = 0x00ff00;
1165 desc.ddpfPixelFormat.u4.dwBBitMask = 0x0000ff;
1166 desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask = 0;
1167 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN;
1168 desc.lpSurface = NULL;
1170 hr = IDirectDraw_CreateSurface(ddraw, &desc, &object->surface, NULL);
1171 IDirectDraw_Release(ddraw);
1172 if (FAILED(hr))
1174 ERR("failed to create surface, 0x%08x\n", hr);
1175 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1176 return hr;
1180 if (rect)
1181 object->rect = *rect;
1182 else if (object->surface)
1184 DDSURFACEDESC desc = { sizeof(desc) };
1185 hr = IDirectDrawSurface_GetSurfaceDesc(object->surface, &desc);
1186 if (hr == S_OK)
1187 SetRect(&object->rect, 0, 0, desc.dwWidth, desc.dwHeight);
1190 *ddraw_stream_sample = &object->IDirectDrawStreamSample_iface;
1192 return S_OK;