xactengine3_7: Add new dll.
[wine.git] / dlls / amstream / ddrawstream.c
blob4c94bacf52e77abb0d62d9ba5099d934106cd893
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 struct ddraw_stream
33 IAMMediaStream IAMMediaStream_iface;
34 IDirectDrawMediaStream IDirectDrawMediaStream_iface;
35 IMemInputPin IMemInputPin_iface;
36 IPin IPin_iface;
37 LONG ref;
38 LONG sample_refs;
40 IMultiMediaStream* parent;
41 MSPID purpose_id;
42 STREAM_TYPE stream_type;
43 IDirectDraw *ddraw;
44 CRITICAL_SECTION cs;
45 IMediaStreamFilter *filter;
47 IPin *peer;
48 IMemAllocator *allocator;
49 AM_MEDIA_TYPE mt;
52 static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
53 const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
55 static inline struct ddraw_stream *impl_from_IAMMediaStream(IAMMediaStream *iface)
57 return CONTAINING_RECORD(iface, struct ddraw_stream, IAMMediaStream_iface);
60 /*** IUnknown methods ***/
61 static HRESULT WINAPI ddraw_IAMMediaStream_QueryInterface(IAMMediaStream *iface,
62 REFIID riid, void **ret_iface)
64 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
66 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
68 if (IsEqualGUID(riid, &IID_IUnknown) ||
69 IsEqualGUID(riid, &IID_IMediaStream) ||
70 IsEqualGUID(riid, &IID_IAMMediaStream))
72 IAMMediaStream_AddRef(iface);
73 *ret_iface = iface;
74 return S_OK;
76 else if (IsEqualGUID(riid, &IID_IDirectDrawMediaStream))
78 IAMMediaStream_AddRef(iface);
79 *ret_iface = &This->IDirectDrawMediaStream_iface;
80 return S_OK;
82 else if (IsEqualGUID(riid, &IID_IPin))
84 IAMMediaStream_AddRef(iface);
85 *ret_iface = &This->IPin_iface;
86 return S_OK;
88 else if (IsEqualGUID(riid, &IID_IMemInputPin))
90 IAMMediaStream_AddRef(iface);
91 *ret_iface = &This->IMemInputPin_iface;
92 return S_OK;
95 ERR("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ret_iface);
96 return E_NOINTERFACE;
99 static ULONG WINAPI ddraw_IAMMediaStream_AddRef(IAMMediaStream *iface)
101 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
102 ULONG ref = InterlockedIncrement(&This->ref);
104 TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
106 return ref;
109 static ULONG WINAPI ddraw_IAMMediaStream_Release(IAMMediaStream *iface)
111 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
112 ULONG ref = InterlockedDecrement(&stream->ref);
114 TRACE("%p decreasing refcount to %u.\n", stream, ref);
116 if (!ref)
118 DeleteCriticalSection(&stream->cs);
119 if (stream->ddraw)
120 IDirectDraw_Release(stream->ddraw);
121 HeapFree(GetProcessHeap(), 0, stream);
124 return ref;
127 /*** IMediaStream methods ***/
128 static HRESULT WINAPI ddraw_IAMMediaStream_GetMultiMediaStream(IAMMediaStream *iface,
129 IMultiMediaStream **mmstream)
131 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
133 TRACE("stream %p, mmstream %p.\n", stream, mmstream);
135 if (!mmstream)
136 return E_POINTER;
138 if (stream->parent)
139 IMultiMediaStream_AddRef(stream->parent);
140 *mmstream = stream->parent;
141 return S_OK;
144 static HRESULT WINAPI ddraw_IAMMediaStream_GetInformation(IAMMediaStream *iface,
145 MSPID *purpose_id, STREAM_TYPE *type)
147 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
149 TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
151 if (purpose_id)
152 *purpose_id = This->purpose_id;
153 if (type)
154 *type = This->stream_type;
156 return S_OK;
159 static HRESULT WINAPI ddraw_IAMMediaStream_SetSameFormat(IAMMediaStream *iface,
160 IMediaStream *pStreamThatHasDesiredFormat, DWORD flags)
162 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
164 FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, flags);
166 return S_FALSE;
169 static HRESULT WINAPI ddraw_IAMMediaStream_AllocateSample(IAMMediaStream *iface,
170 DWORD flags, IStreamSample **sample)
172 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
174 FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, flags, sample);
176 return S_FALSE;
179 static HRESULT WINAPI ddraw_IAMMediaStream_CreateSharedSample(IAMMediaStream *iface,
180 IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
182 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
184 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, existing_sample, flags, sample);
186 return S_FALSE;
189 static HRESULT WINAPI ddraw_IAMMediaStream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
191 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
193 FIXME("(%p/%p)->(%x) stub!\n", This, iface, flags);
195 return S_FALSE;
198 /*** IAMMediaStream methods ***/
199 static HRESULT WINAPI ddraw_IAMMediaStream_Initialize(IAMMediaStream *iface, IUnknown *source_object, DWORD flags,
200 REFMSPID purpose_id, const STREAM_TYPE stream_type)
202 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
203 HRESULT hr;
205 TRACE("stream %p, source_object %p, flags %x, purpose_id %s, stream_type %u.\n", stream, source_object, flags,
206 debugstr_guid(purpose_id), stream_type);
208 if (!purpose_id)
209 return E_POINTER;
211 if (flags & AMMSF_CREATEPEER)
212 FIXME("AMMSF_CREATEPEER is not yet supported.\n");
214 stream->purpose_id = *purpose_id;
215 stream->stream_type = stream_type;
217 if (source_object
218 && FAILED(hr = IUnknown_QueryInterface(source_object, &IID_IDirectDraw, (void **)&stream->ddraw)))
219 FIXME("Stream object doesn't implement IDirectDraw interface, hr %#x.\n", hr);
221 if (!source_object)
223 if (FAILED(hr = DirectDrawCreate(NULL, &stream->ddraw, NULL)))
224 return hr;
225 IDirectDraw_SetCooperativeLevel(stream->ddraw, NULL, DDSCL_NORMAL);
228 return S_OK;
231 static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTER_STATE state)
233 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
235 FIXME("(%p/%p)->(%u) stub!\n", This, iface, state);
237 return S_FALSE;
240 static HRESULT WINAPI ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream)
242 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
244 TRACE("stream %p, mmstream %p.\n", stream, mmstream);
246 stream->parent = (IMultiMediaStream *)mmstream;
248 return S_OK;
251 static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
253 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
255 TRACE("iface %p, filter %p.\n", iface, filter);
257 stream->filter = filter;
259 return S_OK;
262 static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *filtergraph)
264 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
266 TRACE("stream %p, filtergraph %p.\n", stream, filtergraph);
268 return S_OK;
271 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl =
273 /*** IUnknown methods ***/
274 ddraw_IAMMediaStream_QueryInterface,
275 ddraw_IAMMediaStream_AddRef,
276 ddraw_IAMMediaStream_Release,
277 /*** IMediaStream methods ***/
278 ddraw_IAMMediaStream_GetMultiMediaStream,
279 ddraw_IAMMediaStream_GetInformation,
280 ddraw_IAMMediaStream_SetSameFormat,
281 ddraw_IAMMediaStream_AllocateSample,
282 ddraw_IAMMediaStream_CreateSharedSample,
283 ddraw_IAMMediaStream_SendEndOfStream,
284 /*** IAMMediaStream methods ***/
285 ddraw_IAMMediaStream_Initialize,
286 ddraw_IAMMediaStream_SetState,
287 ddraw_IAMMediaStream_JoinAMMultiMediaStream,
288 ddraw_IAMMediaStream_JoinFilter,
289 ddraw_IAMMediaStream_JoinFilterGraph
292 static inline struct ddraw_stream *impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream *iface)
294 return CONTAINING_RECORD(iface, struct ddraw_stream, IDirectDrawMediaStream_iface);
297 /*** IUnknown methods ***/
298 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream *iface,
299 REFIID riid, void **ret_iface)
301 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
302 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
303 return IAMMediaStream_QueryInterface(&This->IAMMediaStream_iface, riid, ret_iface);
306 static ULONG WINAPI ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream *iface)
308 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
309 TRACE("(%p/%p)\n", iface, This);
310 return IAMMediaStream_AddRef(&This->IAMMediaStream_iface);
313 static ULONG WINAPI ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream *iface)
315 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
316 TRACE("(%p/%p)\n", iface, This);
317 return IAMMediaStream_Release(&This->IAMMediaStream_iface);
320 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream *iface,
321 IMultiMediaStream **mmstream)
323 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
324 return IAMMediaStream_GetMultiMediaStream(&stream->IAMMediaStream_iface, mmstream);
327 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream *iface,
328 MSPID *purpose_id, STREAM_TYPE *type)
330 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
331 return IAMMediaStream_GetInformation(&stream->IAMMediaStream_iface, purpose_id, type);
334 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream *iface,
335 IMediaStream *other, DWORD flags)
337 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
338 return IAMMediaStream_SetSameFormat(&stream->IAMMediaStream_iface, other, flags);
341 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream *iface,
342 DWORD flags, IStreamSample **sample)
344 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
345 return IAMMediaStream_AllocateSample(&stream->IAMMediaStream_iface, flags, sample);
348 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream *iface,
349 IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
351 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
352 return IAMMediaStream_CreateSharedSample(&stream->IAMMediaStream_iface, existing_sample, flags, sample);
355 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream *iface, DWORD flags)
357 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
358 return IAMMediaStream_SendEndOfStream(&stream->IAMMediaStream_iface, flags);
361 /*** IDirectDrawMediaStream methods ***/
362 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream *iface,
363 DDSURFACEDESC *current_format, IDirectDrawPalette **palette,
364 DDSURFACEDESC *desired_format, DWORD *flags)
366 FIXME("(%p)->(%p,%p,%p,%p) stub!\n", iface, current_format, palette, desired_format,
367 flags);
369 return MS_E_NOSTREAM;
373 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream *iface,
374 const DDSURFACEDESC *pDDSurfaceDesc, IDirectDrawPalette *pDirectDrawPalette)
376 FIXME("(%p)->(%p,%p) stub!\n", iface, pDDSurfaceDesc, pDirectDrawPalette);
378 return E_NOTIMPL;
381 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream *iface,
382 IDirectDraw **ddraw)
384 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
386 TRACE("stream %p, ddraw %p.\n", stream, ddraw);
388 if (!ddraw)
389 return E_POINTER;
391 if (!stream->ddraw)
393 *ddraw = NULL;
394 return S_OK;
397 IDirectDraw_AddRef(stream->ddraw);
398 *ddraw = stream->ddraw;
400 return S_OK;
403 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream *iface,
404 IDirectDraw *ddraw)
406 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
408 TRACE("stream %p, ddraw %p.\n", stream, ddraw);
410 EnterCriticalSection(&stream->cs);
412 if (stream->sample_refs)
414 HRESULT hr = (stream->ddraw == ddraw) ? S_OK : MS_E_SAMPLEALLOC;
415 LeaveCriticalSection(&stream->cs);
416 return hr;
419 if (stream->ddraw)
420 IDirectDraw_Release(stream->ddraw);
422 if (ddraw)
424 IDirectDraw_AddRef(ddraw);
425 stream->ddraw = ddraw;
427 else
428 stream->ddraw = NULL;
430 LeaveCriticalSection(&stream->cs);
432 return S_OK;
435 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream *iface,
436 IDirectDrawSurface *surface, const RECT *rect, DWORD flags,
437 IDirectDrawStreamSample **sample)
439 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
440 HRESULT hr;
442 TRACE("stream %p, surface %p, rect %s, flags %#x, sample %p.\n",
443 stream, surface, wine_dbgstr_rect(rect), flags, sample);
445 EnterCriticalSection(&stream->cs);
446 hr = ddrawstreamsample_create(stream, surface, rect, sample);
447 LeaveCriticalSection(&stream->cs);
449 return hr;
452 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream *iface,
453 STREAM_TIME *pFrameTime)
455 FIXME("(%p)->(%p) stub!\n", iface, pFrameTime);
457 return E_NOTIMPL;
460 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl =
462 /*** IUnknown methods ***/
463 ddraw_IDirectDrawMediaStream_QueryInterface,
464 ddraw_IDirectDrawMediaStream_AddRef,
465 ddraw_IDirectDrawMediaStream_Release,
466 /*** IMediaStream methods ***/
467 ddraw_IDirectDrawMediaStream_GetMultiMediaStream,
468 ddraw_IDirectDrawMediaStream_GetInformation,
469 ddraw_IDirectDrawMediaStream_SetSameFormat,
470 ddraw_IDirectDrawMediaStream_AllocateSample,
471 ddraw_IDirectDrawMediaStream_CreateSharedSample,
472 ddraw_IDirectDrawMediaStream_SendEndOfStream,
473 /*** IDirectDrawMediaStream methods ***/
474 ddraw_IDirectDrawMediaStream_GetFormat,
475 ddraw_IDirectDrawMediaStream_SetFormat,
476 ddraw_IDirectDrawMediaStream_GetDirectDraw,
477 ddraw_IDirectDrawMediaStream_SetDirectDraw,
478 ddraw_IDirectDrawMediaStream_CreateSample,
479 ddraw_IDirectDrawMediaStream_GetTimePerFrame
482 struct enum_media_types
484 IEnumMediaTypes IEnumMediaTypes_iface;
485 LONG refcount;
486 unsigned int index;
489 static const IEnumMediaTypesVtbl enum_media_types_vtbl;
491 static struct enum_media_types *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
493 return CONTAINING_RECORD(iface, struct enum_media_types, IEnumMediaTypes_iface);
496 static HRESULT WINAPI enum_media_types_QueryInterface(IEnumMediaTypes *iface, REFIID iid, void **out)
498 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
500 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumMediaTypes))
502 IEnumMediaTypes_AddRef(iface);
503 *out = iface;
504 return S_OK;
507 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
508 *out = NULL;
509 return E_NOINTERFACE;
512 static ULONG WINAPI enum_media_types_AddRef(IEnumMediaTypes *iface)
514 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
515 ULONG refcount = InterlockedIncrement(&enum_media_types->refcount);
516 TRACE("%p increasing refcount to %u.\n", enum_media_types, refcount);
517 return refcount;
520 static ULONG WINAPI enum_media_types_Release(IEnumMediaTypes *iface)
522 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
523 ULONG refcount = InterlockedDecrement(&enum_media_types->refcount);
524 TRACE("%p decreasing refcount to %u.\n", enum_media_types, refcount);
525 if (!refcount)
526 heap_free(enum_media_types);
527 return refcount;
530 static HRESULT WINAPI enum_media_types_Next(IEnumMediaTypes *iface, ULONG count, AM_MEDIA_TYPE **mts, ULONG *ret_count)
532 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
534 TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface, count, mts, ret_count);
536 if (!ret_count)
537 return E_POINTER;
539 if (count && !enum_media_types->index)
541 mts[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
542 memset(mts[0], 0, sizeof(AM_MEDIA_TYPE));
543 mts[0]->majortype = MEDIATYPE_Video;
544 mts[0]->subtype = MEDIASUBTYPE_RGB8;
545 mts[0]->bFixedSizeSamples = TRUE;
546 mts[0]->lSampleSize = 10000;
547 ++enum_media_types->index;
548 *ret_count = 1;
549 return count == 1 ? S_OK : S_FALSE;
552 *ret_count = 0;
553 return count ? S_FALSE : S_OK;
556 static HRESULT WINAPI enum_media_types_Skip(IEnumMediaTypes *iface, ULONG count)
558 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
560 TRACE("iface %p, count %u.\n", iface, count);
562 enum_media_types->index += count;
564 return S_OK;
567 static HRESULT WINAPI enum_media_types_Reset(IEnumMediaTypes *iface)
569 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
571 TRACE("iface %p.\n", iface);
573 enum_media_types->index = 0;
574 return S_OK;
577 static HRESULT WINAPI enum_media_types_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **out)
579 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
580 struct enum_media_types *object;
582 TRACE("iface %p, out %p.\n", iface, out);
584 if (!(object = heap_alloc(sizeof(*object))))
585 return E_OUTOFMEMORY;
587 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
588 object->refcount = 1;
589 object->index = enum_media_types->index;
591 *out = &object->IEnumMediaTypes_iface;
592 return S_OK;
595 static const IEnumMediaTypesVtbl enum_media_types_vtbl =
597 enum_media_types_QueryInterface,
598 enum_media_types_AddRef,
599 enum_media_types_Release,
600 enum_media_types_Next,
601 enum_media_types_Skip,
602 enum_media_types_Reset,
603 enum_media_types_Clone,
606 static inline struct ddraw_stream *impl_from_IPin(IPin *iface)
608 return CONTAINING_RECORD(iface, struct ddraw_stream, IPin_iface);
611 static HRESULT WINAPI ddraw_sink_QueryInterface(IPin *iface, REFIID iid, void **out)
613 struct ddraw_stream *stream = impl_from_IPin(iface);
614 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
617 static ULONG WINAPI ddraw_sink_AddRef(IPin *iface)
619 struct ddraw_stream *stream = impl_from_IPin(iface);
620 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
623 static ULONG WINAPI ddraw_sink_Release(IPin *iface)
625 struct ddraw_stream *stream = impl_from_IPin(iface);
626 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
629 static HRESULT WINAPI ddraw_sink_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
631 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface, peer, mt);
632 return E_UNEXPECTED;
635 static HRESULT WINAPI ddraw_sink_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
637 struct ddraw_stream *stream = impl_from_IPin(iface);
638 PIN_DIRECTION dir;
640 TRACE("stream %p, peer %p, mt %p.\n", stream, peer, mt);
642 EnterCriticalSection(&stream->cs);
644 if (stream->peer)
646 LeaveCriticalSection(&stream->cs);
647 return VFW_E_ALREADY_CONNECTED;
650 if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)
651 || (!IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB8)
652 && !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB24)
653 && !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB32)
654 && !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB555)
655 && !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB565))
656 || !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
658 LeaveCriticalSection(&stream->cs);
659 return VFW_E_TYPE_NOT_ACCEPTED;
662 IPin_QueryDirection(peer, &dir);
663 if (dir != PINDIR_OUTPUT)
665 WARN("Rejecting connection from input pin.\n");
666 LeaveCriticalSection(&stream->cs);
667 return VFW_E_INVALID_DIRECTION;
670 CopyMediaType(&stream->mt, mt);
671 IPin_AddRef(stream->peer = peer);
673 LeaveCriticalSection(&stream->cs);
675 return S_OK;
678 static HRESULT WINAPI ddraw_sink_Disconnect(IPin *iface)
680 struct ddraw_stream *stream = impl_from_IPin(iface);
682 TRACE("stream %p.\n", stream);
684 EnterCriticalSection(&stream->cs);
686 if (!stream->peer)
688 LeaveCriticalSection(&stream->cs);
689 return S_FALSE;
692 IPin_Release(stream->peer);
693 stream->peer = NULL;
694 FreeMediaType(&stream->mt);
695 memset(&stream->mt, 0, sizeof(AM_MEDIA_TYPE));
697 LeaveCriticalSection(&stream->cs);
699 return S_OK;
702 static HRESULT WINAPI ddraw_sink_ConnectedTo(IPin *iface, IPin **peer)
704 struct ddraw_stream *stream = impl_from_IPin(iface);
705 HRESULT hr;
707 TRACE("stream %p, peer %p.\n", stream, peer);
709 EnterCriticalSection(&stream->cs);
711 if (stream->peer)
713 IPin_AddRef(*peer = stream->peer);
714 hr = S_OK;
716 else
718 *peer = NULL;
719 hr = VFW_E_NOT_CONNECTED;
722 LeaveCriticalSection(&stream->cs);
724 return hr;
727 static HRESULT WINAPI ddraw_sink_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
729 struct ddraw_stream *stream = impl_from_IPin(iface);
730 HRESULT hr;
732 TRACE("stream %p, mt %p.\n", stream, mt);
734 EnterCriticalSection(&stream->cs);
736 if (stream->peer)
738 CopyMediaType(mt, &stream->mt);
739 hr = S_OK;
741 else
743 memset(mt, 0, sizeof(AM_MEDIA_TYPE));
744 hr = VFW_E_NOT_CONNECTED;
747 LeaveCriticalSection(&stream->cs);
749 return hr;
752 static HRESULT WINAPI ddraw_sink_QueryPinInfo(IPin *iface, PIN_INFO *info)
754 struct ddraw_stream *stream = impl_from_IPin(iface);
756 TRACE("stream %p, info %p.\n", stream, info);
758 IBaseFilter_AddRef(info->pFilter = (IBaseFilter *)stream->filter);
759 info->dir = PINDIR_INPUT;
760 wcscpy(info->achName, sink_id);
762 return S_OK;
765 static HRESULT WINAPI ddraw_sink_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
767 TRACE("iface %p, dir %p.\n", iface, dir);
768 *dir = PINDIR_INPUT;
769 return S_OK;
772 static HRESULT WINAPI ddraw_sink_QueryId(IPin *iface, WCHAR **id)
774 TRACE("iface %p, id %p.\n", iface, id);
776 if (!(*id = CoTaskMemAlloc(sizeof(sink_id))))
777 return E_OUTOFMEMORY;
779 wcscpy(*id, sink_id);
781 return S_OK;
784 static HRESULT WINAPI ddraw_sink_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
786 TRACE("iface %p, mt %p.\n", iface, mt);
788 if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)
789 && IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB8)
790 && IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
791 return S_OK;
793 return VFW_E_TYPE_NOT_ACCEPTED;
796 static HRESULT WINAPI ddraw_sink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types)
798 struct enum_media_types *object;
800 TRACE("iface %p, enum_media_types %p.\n", iface, enum_media_types);
802 if (!enum_media_types)
803 return E_POINTER;
805 if (!(object = heap_alloc(sizeof(*object))))
806 return E_OUTOFMEMORY;
808 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
809 object->refcount = 1;
810 object->index = 0;
812 *enum_media_types = &object->IEnumMediaTypes_iface;
813 return S_OK;
816 static HRESULT WINAPI ddraw_sink_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
818 TRACE("iface %p, pins %p, count %p.\n", iface, pins, count);
819 return E_NOTIMPL;
822 static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
824 FIXME("iface %p, stub!\n", iface);
825 return E_NOTIMPL;
828 static HRESULT WINAPI ddraw_sink_BeginFlush(IPin *iface)
830 FIXME("iface %p, stub!\n", iface);
831 return E_NOTIMPL;
834 static HRESULT WINAPI ddraw_sink_EndFlush(IPin *iface)
836 FIXME("iface %p, stub!\n", iface);
837 return E_NOTIMPL;
840 static HRESULT WINAPI ddraw_sink_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
842 FIXME("iface %p, start %s, stop %s, rate %0.16e, stub!\n",
843 iface, wine_dbgstr_longlong(start), wine_dbgstr_longlong(stop), rate);
844 return E_NOTIMPL;
847 static const IPinVtbl ddraw_sink_vtbl =
849 ddraw_sink_QueryInterface,
850 ddraw_sink_AddRef,
851 ddraw_sink_Release,
852 ddraw_sink_Connect,
853 ddraw_sink_ReceiveConnection,
854 ddraw_sink_Disconnect,
855 ddraw_sink_ConnectedTo,
856 ddraw_sink_ConnectionMediaType,
857 ddraw_sink_QueryPinInfo,
858 ddraw_sink_QueryDirection,
859 ddraw_sink_QueryId,
860 ddraw_sink_QueryAccept,
861 ddraw_sink_EnumMediaTypes,
862 ddraw_sink_QueryInternalConnections,
863 ddraw_sink_EndOfStream,
864 ddraw_sink_BeginFlush,
865 ddraw_sink_EndFlush,
866 ddraw_sink_NewSegment,
869 static inline struct ddraw_stream *impl_from_IMemInputPin(IMemInputPin *iface)
871 return CONTAINING_RECORD(iface, struct ddraw_stream, IMemInputPin_iface);
874 static HRESULT WINAPI ddraw_meminput_QueryInterface(IMemInputPin *iface, REFIID iid, void **out)
876 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
877 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
880 static ULONG WINAPI ddraw_meminput_AddRef(IMemInputPin *iface)
882 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
883 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
886 static ULONG WINAPI ddraw_meminput_Release(IMemInputPin *iface)
888 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
889 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
892 static HRESULT WINAPI ddraw_meminput_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
894 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
896 TRACE("stream %p, allocator %p.\n", stream, allocator);
898 if (stream->allocator)
900 IMemAllocator_AddRef(*allocator = stream->allocator);
901 return S_OK;
904 *allocator = NULL;
905 return VFW_E_NO_ALLOCATOR;
908 static HRESULT WINAPI ddraw_meminput_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readonly)
910 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
912 TRACE("stream %p, allocator %p, readonly %d.\n", stream, allocator, readonly);
914 if (!allocator)
915 return E_POINTER;
917 if (allocator)
918 IMemAllocator_AddRef(allocator);
919 if (stream->allocator)
920 IMemAllocator_Release(stream->allocator);
921 stream->allocator = allocator;
923 return S_OK;
926 static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
928 TRACE("iface %p, props %p.\n", iface, props);
929 return E_NOTIMPL;
932 static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample)
934 FIXME("iface %p, sample %p, stub!\n", iface, sample);
935 return E_NOTIMPL;
938 static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface,
939 IMediaSample **samples, LONG count, LONG *processed)
941 FIXME("iface %p, samples %p, count %u, processed %p, stub!\n", iface, samples, count, processed);
942 return E_NOTIMPL;
945 static HRESULT WINAPI ddraw_meminput_ReceiveCanBlock(IMemInputPin *iface)
947 TRACE("iface %p.\n", iface);
948 return S_OK;
951 static const IMemInputPinVtbl ddraw_meminput_vtbl =
953 ddraw_meminput_QueryInterface,
954 ddraw_meminput_AddRef,
955 ddraw_meminput_Release,
956 ddraw_meminput_GetAllocator,
957 ddraw_meminput_NotifyAllocator,
958 ddraw_meminput_GetAllocatorRequirements,
959 ddraw_meminput_Receive,
960 ddraw_meminput_ReceiveMultiple,
961 ddraw_meminput_ReceiveCanBlock,
964 HRESULT ddraw_stream_create(IUnknown *outer, void **out)
966 struct ddraw_stream *object;
968 if (outer)
969 return CLASS_E_NOAGGREGATION;
971 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
972 if (!object)
973 return E_OUTOFMEMORY;
975 object->IAMMediaStream_iface.lpVtbl = &ddraw_IAMMediaStream_vtbl;
976 object->IDirectDrawMediaStream_iface.lpVtbl = &ddraw_IDirectDrawMediaStream_Vtbl;
977 object->IMemInputPin_iface.lpVtbl = &ddraw_meminput_vtbl;
978 object->IPin_iface.lpVtbl = &ddraw_sink_vtbl;
979 object->ref = 1;
981 InitializeCriticalSection(&object->cs);
983 TRACE("Created ddraw stream %p.\n", object);
985 *out = &object->IAMMediaStream_iface;
987 return S_OK;
990 struct ddraw_sample
992 IDirectDrawStreamSample IDirectDrawStreamSample_iface;
993 LONG ref;
994 struct ddraw_stream *parent;
995 IDirectDrawSurface *surface;
996 RECT rect;
999 static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface)
1001 return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface);
1004 /*** IUnknown methods ***/
1005 static HRESULT WINAPI ddraw_sample_QueryInterface(IDirectDrawStreamSample *iface,
1006 REFIID riid, void **ret_iface)
1008 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface);
1010 if (IsEqualGUID(riid, &IID_IUnknown) ||
1011 IsEqualGUID(riid, &IID_IStreamSample) ||
1012 IsEqualGUID(riid, &IID_IDirectDrawStreamSample))
1014 IDirectDrawStreamSample_AddRef(iface);
1015 *ret_iface = iface;
1016 return S_OK;
1019 *ret_iface = NULL;
1021 ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
1022 return E_NOINTERFACE;
1025 static ULONG WINAPI ddraw_sample_AddRef(IDirectDrawStreamSample *iface)
1027 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1028 ULONG ref = InterlockedIncrement(&sample->ref);
1030 TRACE("(%p)->(): new ref = %u\n", iface, ref);
1032 return ref;
1035 static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)
1037 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1038 ULONG ref = InterlockedDecrement(&sample->ref);
1040 TRACE("(%p)->(): new ref = %u\n", iface, ref);
1042 if (!ref)
1044 EnterCriticalSection(&sample->parent->cs);
1045 --sample->parent->sample_refs;
1046 LeaveCriticalSection(&sample->parent->cs);
1048 if (sample->surface)
1049 IDirectDrawSurface_Release(sample->surface);
1050 HeapFree(GetProcessHeap(), 0, sample);
1053 return ref;
1056 /*** IStreamSample methods ***/
1057 static HRESULT WINAPI ddraw_sample_GetMediaStream(IDirectDrawStreamSample *iface, IMediaStream **media_stream)
1059 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1061 TRACE("sample %p, media_stream %p.\n", sample, media_stream);
1063 if (!media_stream)
1064 return E_POINTER;
1066 IAMMediaStream_AddRef(&sample->parent->IAMMediaStream_iface);
1067 *media_stream = (IMediaStream *)&sample->parent->IAMMediaStream_iface;
1069 return S_OK;
1072 static HRESULT WINAPI ddraw_sample_GetSampleTimes(IDirectDrawStreamSample *iface, STREAM_TIME *start_time,
1073 STREAM_TIME *end_time, STREAM_TIME *current_time)
1075 FIXME("(%p)->(%p,%p,%p): stub\n", iface, start_time, end_time, current_time);
1077 return E_NOTIMPL;
1080 static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface, const STREAM_TIME *start_time,
1081 const STREAM_TIME *end_time)
1083 FIXME("(%p)->(%p,%p): stub\n", iface, start_time, end_time);
1085 return E_NOTIMPL;
1088 static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event,
1089 PAPCFUNC func_APC, DWORD APC_data)
1091 FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC, APC_data);
1093 return S_OK;
1096 static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)
1098 FIXME("(%p)->(%x,%u): stub\n", iface, flags, milliseconds);
1100 return E_NOTIMPL;
1103 /*** IDirectDrawStreamSample methods ***/
1104 static HRESULT WINAPI ddraw_sample_GetSurface(IDirectDrawStreamSample *iface, IDirectDrawSurface **ddraw_surface,
1105 RECT *rect)
1107 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1109 TRACE("(%p)->(%p,%p)\n", iface, ddraw_surface, rect);
1111 if (ddraw_surface)
1113 *ddraw_surface = sample->surface;
1114 if (*ddraw_surface)
1115 IDirectDrawSurface_AddRef(*ddraw_surface);
1118 if (rect)
1119 *rect = sample->rect;
1121 return S_OK;
1124 static HRESULT WINAPI ddraw_sample_SetRect(IDirectDrawStreamSample *iface, const RECT *rect)
1126 FIXME("(%p)->(%p): stub\n", iface, rect);
1128 return E_NOTIMPL;
1131 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl =
1133 /*** IUnknown methods ***/
1134 ddraw_sample_QueryInterface,
1135 ddraw_sample_AddRef,
1136 ddraw_sample_Release,
1137 /*** IStreamSample methods ***/
1138 ddraw_sample_GetMediaStream,
1139 ddraw_sample_GetSampleTimes,
1140 ddraw_sample_SetSampleTimes,
1141 ddraw_sample_Update,
1142 ddraw_sample_CompletionStatus,
1143 /*** IDirectDrawStreamSample methods ***/
1144 ddraw_sample_GetSurface,
1145 ddraw_sample_SetRect
1148 static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
1149 const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample)
1151 struct ddraw_sample *object;
1152 HRESULT hr;
1154 TRACE("(%p)\n", ddraw_stream_sample);
1156 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1157 if (!object)
1158 return E_OUTOFMEMORY;
1160 object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl;
1161 object->ref = 1;
1162 object->parent = parent;
1163 ++parent->sample_refs;
1165 if (surface)
1167 object->surface = surface;
1168 IDirectDrawSurface_AddRef(surface);
1170 else
1172 DDSURFACEDESC desc;
1173 IDirectDraw *ddraw;
1175 hr = IDirectDrawMediaStream_GetDirectDraw(&parent->IDirectDrawMediaStream_iface, &ddraw);
1176 if (FAILED(hr))
1178 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1179 return hr;
1182 desc.dwSize = sizeof(desc);
1183 desc.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
1184 desc.dwHeight = 100;
1185 desc.dwWidth = 100;
1186 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
1187 desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1188 desc.ddpfPixelFormat.u1.dwRGBBitCount = 32;
1189 desc.ddpfPixelFormat.u2.dwRBitMask = 0xff0000;
1190 desc.ddpfPixelFormat.u3.dwGBitMask = 0x00ff00;
1191 desc.ddpfPixelFormat.u4.dwBBitMask = 0x0000ff;
1192 desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask = 0;
1193 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN;
1194 desc.lpSurface = NULL;
1196 hr = IDirectDraw_CreateSurface(ddraw, &desc, &object->surface, NULL);
1197 IDirectDraw_Release(ddraw);
1198 if (FAILED(hr))
1200 ERR("failed to create surface, 0x%08x\n", hr);
1201 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1202 return hr;
1206 if (rect)
1207 object->rect = *rect;
1208 else if (object->surface)
1210 DDSURFACEDESC desc = { sizeof(desc) };
1211 hr = IDirectDrawSurface_GetSurfaceDesc(object->surface, &desc);
1212 if (hr == S_OK)
1213 SetRect(&object->rect, 0, 0, desc.dwWidth, desc.dwHeight);
1216 *ddraw_stream_sample = &object->IDirectDrawStreamSample_iface;
1218 return S_OK;