d3dx10: Implement D3DX10GetImageInfoFromFileW().
[wine.git] / dlls / amstream / ddrawstream.c
blob972c2b9f4d01bbfd3ebcdb68ca79d2fd446ca09b
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 format
33 DWORD flags;
34 DWORD width;
35 DWORD height;
36 DDPIXELFORMAT pf;
39 struct ddraw_stream
41 IAMMediaStream IAMMediaStream_iface;
42 IDirectDrawMediaStream IDirectDrawMediaStream_iface;
43 IMemInputPin IMemInputPin_iface;
44 IPin IPin_iface;
45 LONG ref;
46 LONG sample_refs;
48 IMultiMediaStream* parent;
49 MSPID purpose_id;
50 STREAM_TYPE stream_type;
51 IDirectDraw *ddraw;
52 CRITICAL_SECTION cs;
53 IMediaStreamFilter *filter;
54 IFilterGraph *graph;
56 IPin *peer;
57 IMemAllocator *allocator;
58 AM_MEDIA_TYPE mt;
59 struct format format;
60 FILTER_STATE state;
61 BOOL eos;
62 CONDITION_VARIABLE update_queued_cv;
63 struct list update_queue;
66 struct ddraw_sample
68 IDirectDrawStreamSample IDirectDrawStreamSample_iface;
69 LONG ref;
70 struct ddraw_stream *parent;
71 IDirectDrawSurface *surface;
72 RECT rect;
73 HANDLE update_event;
75 struct list entry;
76 HRESULT update_hr;
79 static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
80 const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
82 static void remove_queued_update(struct ddraw_sample *sample)
84 list_remove(&sample->entry);
85 SetEvent(sample->update_event);
88 static void flush_update_queue(struct ddraw_stream *stream, HRESULT update_hr)
90 struct list *entry;
91 while ((entry = list_head(&stream->update_queue)))
93 struct ddraw_sample *sample = LIST_ENTRY(entry, struct ddraw_sample, entry);
94 sample->update_hr = update_hr;
95 remove_queued_update(sample);
99 static HRESULT process_update(struct ddraw_sample *sample, int stride, BYTE *pointer)
101 DDSURFACEDESC desc;
102 DWORD row_size;
103 const BYTE *src_row;
104 BYTE *dst_row;
105 DWORD row;
106 HRESULT hr;
108 desc.dwSize = sizeof(desc);
109 hr = IDirectDrawSurface_Lock(sample->surface, &sample->rect, &desc, DDLOCK_WAIT, NULL);
110 if (FAILED(hr))
111 return hr;
113 row_size = (sample->rect.right - sample->rect.left) * desc.ddpfPixelFormat.u1.dwRGBBitCount / 8;
114 src_row = pointer;
115 dst_row = desc.lpSurface;
116 for (row = sample->rect.top; row < sample->rect.bottom; ++row)
118 memcpy(dst_row, src_row, row_size);
119 src_row += stride;
120 dst_row += desc.u1.lPitch;
123 hr = IDirectDrawSurface_Unlock(sample->surface, desc.lpSurface);
124 if (FAILED(hr))
125 return hr;
127 return S_OK;
130 static BOOL is_format_compatible(struct ddraw_stream *stream,
131 DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf)
133 if (stream->format.flags & DDSD_HEIGHT)
135 if (stream->format.width != width || stream->format.height != height)
136 return FALSE;
138 if (stream->format.flags & DDSD_PIXELFORMAT)
140 if (stream->format.pf.dwFlags & DDPF_FOURCC)
141 return FALSE;
142 if (stream->format.pf.u1.dwRGBBitCount != connection_pf->u1.dwRGBBitCount)
143 return FALSE;
144 if (stream->format.pf.u1.dwRGBBitCount == 16 && stream->format.pf.u3.dwGBitMask != connection_pf->u3.dwGBitMask)
145 return FALSE;
147 return TRUE;
150 static inline struct ddraw_stream *impl_from_IAMMediaStream(IAMMediaStream *iface)
152 return CONTAINING_RECORD(iface, struct ddraw_stream, IAMMediaStream_iface);
155 /*** IUnknown methods ***/
156 static HRESULT WINAPI ddraw_IAMMediaStream_QueryInterface(IAMMediaStream *iface,
157 REFIID riid, void **ret_iface)
159 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
161 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
163 if (IsEqualGUID(riid, &IID_IUnknown) ||
164 IsEqualGUID(riid, &IID_IMediaStream) ||
165 IsEqualGUID(riid, &IID_IAMMediaStream))
167 IAMMediaStream_AddRef(iface);
168 *ret_iface = iface;
169 return S_OK;
171 else if (IsEqualGUID(riid, &IID_IDirectDrawMediaStream))
173 IAMMediaStream_AddRef(iface);
174 *ret_iface = &This->IDirectDrawMediaStream_iface;
175 return S_OK;
177 else if (IsEqualGUID(riid, &IID_IPin))
179 IAMMediaStream_AddRef(iface);
180 *ret_iface = &This->IPin_iface;
181 return S_OK;
183 else if (IsEqualGUID(riid, &IID_IMemInputPin))
185 IAMMediaStream_AddRef(iface);
186 *ret_iface = &This->IMemInputPin_iface;
187 return S_OK;
190 ERR("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ret_iface);
191 return E_NOINTERFACE;
194 static ULONG WINAPI ddraw_IAMMediaStream_AddRef(IAMMediaStream *iface)
196 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
197 ULONG ref = InterlockedIncrement(&This->ref);
199 TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
201 return ref;
204 static ULONG WINAPI ddraw_IAMMediaStream_Release(IAMMediaStream *iface)
206 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
207 ULONG ref = InterlockedDecrement(&stream->ref);
209 TRACE("%p decreasing refcount to %u.\n", stream, ref);
211 if (!ref)
213 DeleteCriticalSection(&stream->cs);
214 if (stream->ddraw)
215 IDirectDraw_Release(stream->ddraw);
216 HeapFree(GetProcessHeap(), 0, stream);
219 return ref;
222 /*** IMediaStream methods ***/
223 static HRESULT WINAPI ddraw_IAMMediaStream_GetMultiMediaStream(IAMMediaStream *iface,
224 IMultiMediaStream **mmstream)
226 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
228 TRACE("stream %p, mmstream %p.\n", stream, mmstream);
230 if (!mmstream)
231 return E_POINTER;
233 if (stream->parent)
234 IMultiMediaStream_AddRef(stream->parent);
235 *mmstream = stream->parent;
236 return S_OK;
239 static HRESULT WINAPI ddraw_IAMMediaStream_GetInformation(IAMMediaStream *iface,
240 MSPID *purpose_id, STREAM_TYPE *type)
242 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
244 TRACE("(%p/%p)->(%p,%p)\n", This, iface, purpose_id, type);
246 if (purpose_id)
247 *purpose_id = This->purpose_id;
248 if (type)
249 *type = This->stream_type;
251 return S_OK;
254 static HRESULT WINAPI ddraw_IAMMediaStream_SetSameFormat(IAMMediaStream *iface,
255 IMediaStream *pStreamThatHasDesiredFormat, DWORD flags)
257 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
259 FIXME("(%p/%p)->(%p,%x) stub!\n", This, iface, pStreamThatHasDesiredFormat, flags);
261 return S_FALSE;
264 static HRESULT WINAPI ddraw_IAMMediaStream_AllocateSample(IAMMediaStream *iface,
265 DWORD flags, IStreamSample **sample)
267 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
269 FIXME("(%p/%p)->(%x,%p) stub!\n", This, iface, flags, sample);
271 return S_FALSE;
274 static HRESULT WINAPI ddraw_IAMMediaStream_CreateSharedSample(IAMMediaStream *iface,
275 IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
277 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
279 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This, iface, existing_sample, flags, sample);
281 return S_FALSE;
284 static HRESULT WINAPI ddraw_IAMMediaStream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
286 struct ddraw_stream *This = impl_from_IAMMediaStream(iface);
288 FIXME("(%p/%p)->(%x) stub!\n", This, iface, flags);
290 return S_FALSE;
293 /*** IAMMediaStream methods ***/
294 static HRESULT WINAPI ddraw_IAMMediaStream_Initialize(IAMMediaStream *iface, IUnknown *source_object, DWORD flags,
295 REFMSPID purpose_id, const STREAM_TYPE stream_type)
297 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
298 HRESULT hr;
300 TRACE("stream %p, source_object %p, flags %x, purpose_id %s, stream_type %u.\n", stream, source_object, flags,
301 debugstr_guid(purpose_id), stream_type);
303 if (!purpose_id)
304 return E_POINTER;
306 if (flags & AMMSF_CREATEPEER)
307 FIXME("AMMSF_CREATEPEER is not yet supported.\n");
309 stream->purpose_id = *purpose_id;
310 stream->stream_type = stream_type;
312 if (source_object
313 && FAILED(hr = IUnknown_QueryInterface(source_object, &IID_IDirectDraw, (void **)&stream->ddraw)))
314 FIXME("Stream object doesn't implement IDirectDraw interface, hr %#x.\n", hr);
316 if (!source_object)
318 if (FAILED(hr = DirectDrawCreate(NULL, &stream->ddraw, NULL)))
319 return hr;
320 IDirectDraw_SetCooperativeLevel(stream->ddraw, NULL, DDSCL_NORMAL);
323 return S_OK;
326 static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTER_STATE state)
328 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
330 TRACE("stream %p, state %u.\n", stream, state);
332 EnterCriticalSection(&stream->cs);
334 if (state == State_Stopped)
335 WakeConditionVariable(&stream->update_queued_cv);
336 if (stream->state == State_Stopped)
337 stream->eos = FALSE;
339 stream->state = state;
341 LeaveCriticalSection(&stream->cs);
343 return S_OK;
346 static HRESULT WINAPI ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream)
348 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
350 TRACE("stream %p, mmstream %p.\n", stream, mmstream);
352 stream->parent = (IMultiMediaStream *)mmstream;
354 return S_OK;
357 static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
359 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
361 TRACE("iface %p, filter %p.\n", iface, filter);
363 stream->filter = filter;
365 return S_OK;
368 static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *filtergraph)
370 struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
372 TRACE("stream %p, filtergraph %p.\n", stream, filtergraph);
374 stream->graph = filtergraph;
376 return S_OK;
379 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl =
381 /*** IUnknown methods ***/
382 ddraw_IAMMediaStream_QueryInterface,
383 ddraw_IAMMediaStream_AddRef,
384 ddraw_IAMMediaStream_Release,
385 /*** IMediaStream methods ***/
386 ddraw_IAMMediaStream_GetMultiMediaStream,
387 ddraw_IAMMediaStream_GetInformation,
388 ddraw_IAMMediaStream_SetSameFormat,
389 ddraw_IAMMediaStream_AllocateSample,
390 ddraw_IAMMediaStream_CreateSharedSample,
391 ddraw_IAMMediaStream_SendEndOfStream,
392 /*** IAMMediaStream methods ***/
393 ddraw_IAMMediaStream_Initialize,
394 ddraw_IAMMediaStream_SetState,
395 ddraw_IAMMediaStream_JoinAMMultiMediaStream,
396 ddraw_IAMMediaStream_JoinFilter,
397 ddraw_IAMMediaStream_JoinFilterGraph
400 static inline struct ddraw_stream *impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream *iface)
402 return CONTAINING_RECORD(iface, struct ddraw_stream, IDirectDrawMediaStream_iface);
405 /*** IUnknown methods ***/
406 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream *iface,
407 REFIID riid, void **ret_iface)
409 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
410 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ret_iface);
411 return IAMMediaStream_QueryInterface(&This->IAMMediaStream_iface, riid, ret_iface);
414 static ULONG WINAPI ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream *iface)
416 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
417 TRACE("(%p/%p)\n", iface, This);
418 return IAMMediaStream_AddRef(&This->IAMMediaStream_iface);
421 static ULONG WINAPI ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream *iface)
423 struct ddraw_stream *This = impl_from_IDirectDrawMediaStream(iface);
424 TRACE("(%p/%p)\n", iface, This);
425 return IAMMediaStream_Release(&This->IAMMediaStream_iface);
428 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream *iface,
429 IMultiMediaStream **mmstream)
431 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
432 return IAMMediaStream_GetMultiMediaStream(&stream->IAMMediaStream_iface, mmstream);
435 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream *iface,
436 MSPID *purpose_id, STREAM_TYPE *type)
438 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
439 return IAMMediaStream_GetInformation(&stream->IAMMediaStream_iface, purpose_id, type);
442 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream *iface,
443 IMediaStream *other, DWORD flags)
445 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
446 return IAMMediaStream_SetSameFormat(&stream->IAMMediaStream_iface, other, flags);
449 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream *iface,
450 DWORD flags, IStreamSample **sample)
452 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
453 return IAMMediaStream_AllocateSample(&stream->IAMMediaStream_iface, flags, sample);
456 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream *iface,
457 IStreamSample *existing_sample, DWORD flags, IStreamSample **sample)
459 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
460 return IAMMediaStream_CreateSharedSample(&stream->IAMMediaStream_iface, existing_sample, flags, sample);
463 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream *iface, DWORD flags)
465 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
466 return IAMMediaStream_SendEndOfStream(&stream->IAMMediaStream_iface, flags);
469 /*** IDirectDrawMediaStream methods ***/
470 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream *iface,
471 DDSURFACEDESC *current_format, IDirectDrawPalette **palette,
472 DDSURFACEDESC *desired_format, DWORD *flags)
474 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
476 TRACE("stream %p, current_format %p, palette %p, desired_format %p, flags %p.\n", stream, current_format, palette,
477 desired_format, flags);
479 EnterCriticalSection(&stream->cs);
481 if (!stream->peer)
483 LeaveCriticalSection(&stream->cs);
484 return MS_E_NOSTREAM;
487 if (current_format)
489 current_format->dwFlags = stream->format.flags | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
490 current_format->dwWidth = stream->format.width;
491 current_format->dwHeight = stream->format.height;
492 current_format->ddpfPixelFormat = stream->format.pf;
493 current_format->ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
496 if (palette)
497 *palette = NULL;
499 if (desired_format)
501 desired_format->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
502 desired_format->dwWidth = stream->format.width;
503 desired_format->dwHeight = stream->format.height;
504 desired_format->ddpfPixelFormat = stream->format.pf;
505 desired_format->ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
508 if (flags)
509 *flags = 0;
511 LeaveCriticalSection(&stream->cs);
513 return S_OK;
516 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream *iface,
517 const DDSURFACEDESC *format, IDirectDrawPalette *palette)
519 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
520 AM_MEDIA_TYPE old_media_type;
521 struct format old_format;
522 IPin *old_peer;
523 HRESULT hr;
525 TRACE("stream %p, format %p, palette %p.\n", stream, format, palette);
527 if (palette)
528 FIXME("Setting palette is not yet supported.\n");
530 if (!format)
531 return E_POINTER;
533 if (format->dwSize != sizeof(DDSURFACEDESC))
534 return E_INVALIDARG;
536 if (format->dwFlags & DDSD_PIXELFORMAT)
538 if (format->ddpfPixelFormat.dwSize != sizeof(DDPIXELFORMAT))
539 return DDERR_INVALIDSURFACETYPE;
541 if (format->ddpfPixelFormat.dwFlags & DDPF_FOURCC)
543 if (!format->ddpfPixelFormat.u1.dwRGBBitCount)
544 return E_INVALIDARG;
546 else
548 if (format->ddpfPixelFormat.dwFlags & (DDPF_YUV | DDPF_PALETTEINDEXED1 |
549 DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXEDTO8))
550 return DDERR_INVALIDSURFACETYPE;
552 if (!(format->ddpfPixelFormat.dwFlags & DDPF_RGB))
553 return DDERR_INVALIDSURFACETYPE;
555 switch (format->ddpfPixelFormat.u1.dwRGBBitCount)
557 case 8:
558 if (!(format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8))
559 return DDERR_INVALIDSURFACETYPE;
560 break;
561 case 16:
562 if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
563 return DDERR_INVALIDSURFACETYPE;
564 if ((format->ddpfPixelFormat.u2.dwRBitMask != 0x7c00 ||
565 format->ddpfPixelFormat.u3.dwGBitMask != 0x03e0 ||
566 format->ddpfPixelFormat.u4.dwBBitMask != 0x001f) &&
567 (format->ddpfPixelFormat.u2.dwRBitMask != 0xf800 ||
568 format->ddpfPixelFormat.u3.dwGBitMask != 0x07e0 ||
569 format->ddpfPixelFormat.u4.dwBBitMask != 0x001f))
570 return DDERR_INVALIDSURFACETYPE;
571 break;
572 case 24:
573 case 32:
574 if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
575 return DDERR_INVALIDSURFACETYPE;
576 if (format->ddpfPixelFormat.u2.dwRBitMask != 0xff0000 ||
577 format->ddpfPixelFormat.u3.dwGBitMask != 0x00ff00 ||
578 format->ddpfPixelFormat.u4.dwBBitMask != 0x0000ff)
579 return DDERR_INVALIDSURFACETYPE;
580 break;
581 default:
582 return DDERR_INVALIDSURFACETYPE;
587 EnterCriticalSection(&stream->cs);
589 old_format = stream->format;
590 stream->format.flags = format->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT);
591 if (format->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT))
593 stream->format.width = format->dwWidth;
594 stream->format.height = format->dwHeight;
596 if (format->dwFlags & DDSD_PIXELFORMAT)
597 stream->format.pf = format->ddpfPixelFormat;
599 if (stream->peer && !is_format_compatible(stream, old_format.width, old_format.height, &old_format.pf))
601 hr = CopyMediaType(&old_media_type, &stream->mt);
602 if (FAILED(hr))
604 stream->format = old_format;
605 LeaveCriticalSection(&stream->cs);
606 return hr;
608 old_peer = stream->peer;
609 IPin_AddRef(old_peer);
611 IFilterGraph_Disconnect(stream->graph, stream->peer);
612 IFilterGraph_Disconnect(stream->graph, &stream->IPin_iface);
613 hr = IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, NULL);
614 if (FAILED(hr))
616 stream->format = old_format;
617 IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, &old_media_type);
618 IPin_Release(old_peer);
619 FreeMediaType(&old_media_type);
620 LeaveCriticalSection(&stream->cs);
621 return DDERR_INVALIDSURFACETYPE;
624 IPin_Release(old_peer);
625 FreeMediaType(&old_media_type);
628 LeaveCriticalSection(&stream->cs);
630 return S_OK;
633 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream *iface,
634 IDirectDraw **ddraw)
636 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
638 TRACE("stream %p, ddraw %p.\n", stream, ddraw);
640 if (!ddraw)
641 return E_POINTER;
643 if (!stream->ddraw)
645 *ddraw = NULL;
646 return S_OK;
649 IDirectDraw_AddRef(stream->ddraw);
650 *ddraw = stream->ddraw;
652 return S_OK;
655 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream *iface,
656 IDirectDraw *ddraw)
658 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
660 TRACE("stream %p, ddraw %p.\n", stream, ddraw);
662 EnterCriticalSection(&stream->cs);
664 if (stream->sample_refs)
666 HRESULT hr = (stream->ddraw == ddraw) ? S_OK : MS_E_SAMPLEALLOC;
667 LeaveCriticalSection(&stream->cs);
668 return hr;
671 if (stream->ddraw)
672 IDirectDraw_Release(stream->ddraw);
674 if (ddraw)
676 IDirectDraw_AddRef(ddraw);
677 stream->ddraw = ddraw;
679 else
680 stream->ddraw = NULL;
682 LeaveCriticalSection(&stream->cs);
684 return S_OK;
687 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream *iface,
688 IDirectDrawSurface *surface, const RECT *rect, DWORD flags,
689 IDirectDrawStreamSample **sample)
691 struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
692 HRESULT hr;
694 TRACE("stream %p, surface %p, rect %s, flags %#x, sample %p.\n",
695 stream, surface, wine_dbgstr_rect(rect), flags, sample);
697 if (!surface && rect)
698 return E_INVALIDARG;
700 EnterCriticalSection(&stream->cs);
701 hr = ddrawstreamsample_create(stream, surface, rect, sample);
702 LeaveCriticalSection(&stream->cs);
704 return hr;
707 static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream *iface,
708 STREAM_TIME *pFrameTime)
710 FIXME("(%p)->(%p) stub!\n", iface, pFrameTime);
712 return E_NOTIMPL;
715 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl =
717 /*** IUnknown methods ***/
718 ddraw_IDirectDrawMediaStream_QueryInterface,
719 ddraw_IDirectDrawMediaStream_AddRef,
720 ddraw_IDirectDrawMediaStream_Release,
721 /*** IMediaStream methods ***/
722 ddraw_IDirectDrawMediaStream_GetMultiMediaStream,
723 ddraw_IDirectDrawMediaStream_GetInformation,
724 ddraw_IDirectDrawMediaStream_SetSameFormat,
725 ddraw_IDirectDrawMediaStream_AllocateSample,
726 ddraw_IDirectDrawMediaStream_CreateSharedSample,
727 ddraw_IDirectDrawMediaStream_SendEndOfStream,
728 /*** IDirectDrawMediaStream methods ***/
729 ddraw_IDirectDrawMediaStream_GetFormat,
730 ddraw_IDirectDrawMediaStream_SetFormat,
731 ddraw_IDirectDrawMediaStream_GetDirectDraw,
732 ddraw_IDirectDrawMediaStream_SetDirectDraw,
733 ddraw_IDirectDrawMediaStream_CreateSample,
734 ddraw_IDirectDrawMediaStream_GetTimePerFrame
737 struct enum_media_types
739 IEnumMediaTypes IEnumMediaTypes_iface;
740 LONG refcount;
741 unsigned int index;
744 static const IEnumMediaTypesVtbl enum_media_types_vtbl;
746 static struct enum_media_types *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
748 return CONTAINING_RECORD(iface, struct enum_media_types, IEnumMediaTypes_iface);
751 static HRESULT WINAPI enum_media_types_QueryInterface(IEnumMediaTypes *iface, REFIID iid, void **out)
753 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
755 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumMediaTypes))
757 IEnumMediaTypes_AddRef(iface);
758 *out = iface;
759 return S_OK;
762 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
763 *out = NULL;
764 return E_NOINTERFACE;
767 static ULONG WINAPI enum_media_types_AddRef(IEnumMediaTypes *iface)
769 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
770 ULONG refcount = InterlockedIncrement(&enum_media_types->refcount);
771 TRACE("%p increasing refcount to %u.\n", enum_media_types, refcount);
772 return refcount;
775 static ULONG WINAPI enum_media_types_Release(IEnumMediaTypes *iface)
777 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
778 ULONG refcount = InterlockedDecrement(&enum_media_types->refcount);
779 TRACE("%p decreasing refcount to %u.\n", enum_media_types, refcount);
780 if (!refcount)
781 heap_free(enum_media_types);
782 return refcount;
785 static HRESULT WINAPI enum_media_types_Next(IEnumMediaTypes *iface, ULONG count, AM_MEDIA_TYPE **mts, ULONG *ret_count)
787 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
789 TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface, count, mts, ret_count);
791 if (!ret_count)
792 return E_POINTER;
794 if (count && !enum_media_types->index)
796 mts[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
797 memset(mts[0], 0, sizeof(AM_MEDIA_TYPE));
798 mts[0]->majortype = MEDIATYPE_Video;
799 mts[0]->subtype = MEDIASUBTYPE_RGB8;
800 mts[0]->bFixedSizeSamples = TRUE;
801 mts[0]->lSampleSize = 10000;
802 ++enum_media_types->index;
803 *ret_count = 1;
804 return count == 1 ? S_OK : S_FALSE;
807 *ret_count = 0;
808 return count ? S_FALSE : S_OK;
811 static HRESULT WINAPI enum_media_types_Skip(IEnumMediaTypes *iface, ULONG count)
813 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
815 TRACE("iface %p, count %u.\n", iface, count);
817 enum_media_types->index += count;
819 return S_OK;
822 static HRESULT WINAPI enum_media_types_Reset(IEnumMediaTypes *iface)
824 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
826 TRACE("iface %p.\n", iface);
828 enum_media_types->index = 0;
829 return S_OK;
832 static HRESULT WINAPI enum_media_types_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **out)
834 struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
835 struct enum_media_types *object;
837 TRACE("iface %p, out %p.\n", iface, out);
839 if (!(object = heap_alloc(sizeof(*object))))
840 return E_OUTOFMEMORY;
842 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
843 object->refcount = 1;
844 object->index = enum_media_types->index;
846 *out = &object->IEnumMediaTypes_iface;
847 return S_OK;
850 static const IEnumMediaTypesVtbl enum_media_types_vtbl =
852 enum_media_types_QueryInterface,
853 enum_media_types_AddRef,
854 enum_media_types_Release,
855 enum_media_types_Next,
856 enum_media_types_Skip,
857 enum_media_types_Reset,
858 enum_media_types_Clone,
861 static inline struct ddraw_stream *impl_from_IPin(IPin *iface)
863 return CONTAINING_RECORD(iface, struct ddraw_stream, IPin_iface);
866 static HRESULT WINAPI ddraw_sink_QueryInterface(IPin *iface, REFIID iid, void **out)
868 struct ddraw_stream *stream = impl_from_IPin(iface);
869 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
872 static ULONG WINAPI ddraw_sink_AddRef(IPin *iface)
874 struct ddraw_stream *stream = impl_from_IPin(iface);
875 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
878 static ULONG WINAPI ddraw_sink_Release(IPin *iface)
880 struct ddraw_stream *stream = impl_from_IPin(iface);
881 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
884 static HRESULT WINAPI ddraw_sink_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
886 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface, peer, mt);
887 return E_UNEXPECTED;
890 static HRESULT WINAPI ddraw_sink_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
892 struct ddraw_stream *stream = impl_from_IPin(iface);
893 const VIDEOINFOHEADER *video_info;
894 PIN_DIRECTION dir;
895 DWORD width;
896 DWORD height;
897 DDPIXELFORMAT pf = {sizeof(DDPIXELFORMAT)};
899 TRACE("stream %p, peer %p, mt %p.\n", stream, peer, mt);
901 EnterCriticalSection(&stream->cs);
903 if (stream->peer)
905 LeaveCriticalSection(&stream->cs);
906 return VFW_E_ALREADY_CONNECTED;
909 if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)
910 || !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
912 LeaveCriticalSection(&stream->cs);
913 return VFW_E_TYPE_NOT_ACCEPTED;
916 video_info = (const VIDEOINFOHEADER *)mt->pbFormat;
918 width = video_info->bmiHeader.biWidth;
919 height = abs(video_info->bmiHeader.biHeight);
920 pf.dwFlags = DDPF_RGB;
921 if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB8))
923 pf.dwFlags |= DDPF_PALETTEINDEXED8;
924 pf.u1.dwRGBBitCount = 8;
926 else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB555))
928 pf.u1.dwRGBBitCount = 16;
929 pf.u2.dwRBitMask = 0x7c00;
930 pf.u3.dwGBitMask = 0x03e0;
931 pf.u4.dwBBitMask = 0x001f;
933 else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB565))
935 pf.u1.dwRGBBitCount = 16;
936 pf.u2.dwRBitMask = 0xf800;
937 pf.u3.dwGBitMask = 0x07e0;
938 pf.u4.dwBBitMask = 0x001f;
940 else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB24))
942 pf.u1.dwRGBBitCount = 24;
943 pf.u2.dwRBitMask = 0xff0000;
944 pf.u3.dwGBitMask = 0x00ff00;
945 pf.u4.dwBBitMask = 0x0000ff;
947 else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB32))
949 pf.u1.dwRGBBitCount = 32;
950 pf.u2.dwRBitMask = 0xff0000;
951 pf.u3.dwGBitMask = 0x00ff00;
952 pf.u4.dwBBitMask = 0x0000ff;
954 else
956 LeaveCriticalSection(&stream->cs);
957 return VFW_E_TYPE_NOT_ACCEPTED;
960 if (!is_format_compatible(stream, width, height, &pf))
962 LeaveCriticalSection(&stream->cs);
963 return VFW_E_TYPE_NOT_ACCEPTED;
966 IPin_QueryDirection(peer, &dir);
967 if (dir != PINDIR_OUTPUT)
969 WARN("Rejecting connection from input pin.\n");
970 LeaveCriticalSection(&stream->cs);
971 return VFW_E_INVALID_DIRECTION;
974 CopyMediaType(&stream->mt, mt);
975 IPin_AddRef(stream->peer = peer);
977 stream->format.width = width;
978 stream->format.height = height;
979 if (!(stream->format.flags & DDSD_PIXELFORMAT))
980 stream->format.pf = pf;
982 LeaveCriticalSection(&stream->cs);
984 return S_OK;
987 static HRESULT WINAPI ddraw_sink_Disconnect(IPin *iface)
989 struct ddraw_stream *stream = impl_from_IPin(iface);
991 TRACE("stream %p.\n", stream);
993 EnterCriticalSection(&stream->cs);
995 if (!stream->peer)
997 LeaveCriticalSection(&stream->cs);
998 return S_FALSE;
1001 IPin_Release(stream->peer);
1002 stream->peer = NULL;
1003 FreeMediaType(&stream->mt);
1004 memset(&stream->mt, 0, sizeof(AM_MEDIA_TYPE));
1006 LeaveCriticalSection(&stream->cs);
1008 return S_OK;
1011 static HRESULT WINAPI ddraw_sink_ConnectedTo(IPin *iface, IPin **peer)
1013 struct ddraw_stream *stream = impl_from_IPin(iface);
1014 HRESULT hr;
1016 TRACE("stream %p, peer %p.\n", stream, peer);
1018 EnterCriticalSection(&stream->cs);
1020 if (stream->peer)
1022 IPin_AddRef(*peer = stream->peer);
1023 hr = S_OK;
1025 else
1027 *peer = NULL;
1028 hr = VFW_E_NOT_CONNECTED;
1031 LeaveCriticalSection(&stream->cs);
1033 return hr;
1036 static HRESULT WINAPI ddraw_sink_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
1038 struct ddraw_stream *stream = impl_from_IPin(iface);
1039 HRESULT hr;
1041 TRACE("stream %p, mt %p.\n", stream, mt);
1043 EnterCriticalSection(&stream->cs);
1045 if (stream->peer)
1047 CopyMediaType(mt, &stream->mt);
1048 hr = S_OK;
1050 else
1052 memset(mt, 0, sizeof(AM_MEDIA_TYPE));
1053 hr = VFW_E_NOT_CONNECTED;
1056 LeaveCriticalSection(&stream->cs);
1058 return hr;
1061 static HRESULT WINAPI ddraw_sink_QueryPinInfo(IPin *iface, PIN_INFO *info)
1063 struct ddraw_stream *stream = impl_from_IPin(iface);
1065 TRACE("stream %p, info %p.\n", stream, info);
1067 IBaseFilter_AddRef(info->pFilter = (IBaseFilter *)stream->filter);
1068 info->dir = PINDIR_INPUT;
1069 wcscpy(info->achName, sink_id);
1071 return S_OK;
1074 static HRESULT WINAPI ddraw_sink_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
1076 TRACE("iface %p, dir %p.\n", iface, dir);
1077 *dir = PINDIR_INPUT;
1078 return S_OK;
1081 static HRESULT WINAPI ddraw_sink_QueryId(IPin *iface, WCHAR **id)
1083 TRACE("iface %p, id %p.\n", iface, id);
1085 if (!(*id = CoTaskMemAlloc(sizeof(sink_id))))
1086 return E_OUTOFMEMORY;
1088 wcscpy(*id, sink_id);
1090 return S_OK;
1093 static HRESULT WINAPI ddraw_sink_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
1095 TRACE("iface %p, mt %p.\n", iface, mt);
1097 if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)
1098 && IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB8)
1099 && IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
1100 return S_OK;
1102 return VFW_E_TYPE_NOT_ACCEPTED;
1105 static HRESULT WINAPI ddraw_sink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types)
1107 struct enum_media_types *object;
1109 TRACE("iface %p, enum_media_types %p.\n", iface, enum_media_types);
1111 if (!enum_media_types)
1112 return E_POINTER;
1114 if (!(object = heap_alloc(sizeof(*object))))
1115 return E_OUTOFMEMORY;
1117 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
1118 object->refcount = 1;
1119 object->index = 0;
1121 *enum_media_types = &object->IEnumMediaTypes_iface;
1122 return S_OK;
1125 static HRESULT WINAPI ddraw_sink_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
1127 TRACE("iface %p, pins %p, count %p.\n", iface, pins, count);
1128 return E_NOTIMPL;
1131 static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
1133 struct ddraw_stream *stream = impl_from_IPin(iface);
1135 TRACE("stream %p.\n", stream);
1137 EnterCriticalSection(&stream->cs);
1139 if (stream->eos)
1141 LeaveCriticalSection(&stream->cs);
1142 return E_FAIL;
1145 stream->eos = TRUE;
1147 flush_update_queue(stream, MS_S_ENDOFSTREAM);
1149 LeaveCriticalSection(&stream->cs);
1151 return S_OK;
1154 static HRESULT WINAPI ddraw_sink_BeginFlush(IPin *iface)
1156 FIXME("iface %p, stub!\n", iface);
1157 return E_NOTIMPL;
1160 static HRESULT WINAPI ddraw_sink_EndFlush(IPin *iface)
1162 FIXME("iface %p, stub!\n", iface);
1163 return E_NOTIMPL;
1166 static HRESULT WINAPI ddraw_sink_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
1168 FIXME("iface %p, start %s, stop %s, rate %0.16e, stub!\n",
1169 iface, wine_dbgstr_longlong(start), wine_dbgstr_longlong(stop), rate);
1170 return E_NOTIMPL;
1173 static const IPinVtbl ddraw_sink_vtbl =
1175 ddraw_sink_QueryInterface,
1176 ddraw_sink_AddRef,
1177 ddraw_sink_Release,
1178 ddraw_sink_Connect,
1179 ddraw_sink_ReceiveConnection,
1180 ddraw_sink_Disconnect,
1181 ddraw_sink_ConnectedTo,
1182 ddraw_sink_ConnectionMediaType,
1183 ddraw_sink_QueryPinInfo,
1184 ddraw_sink_QueryDirection,
1185 ddraw_sink_QueryId,
1186 ddraw_sink_QueryAccept,
1187 ddraw_sink_EnumMediaTypes,
1188 ddraw_sink_QueryInternalConnections,
1189 ddraw_sink_EndOfStream,
1190 ddraw_sink_BeginFlush,
1191 ddraw_sink_EndFlush,
1192 ddraw_sink_NewSegment,
1195 static inline struct ddraw_stream *impl_from_IMemInputPin(IMemInputPin *iface)
1197 return CONTAINING_RECORD(iface, struct ddraw_stream, IMemInputPin_iface);
1200 static HRESULT WINAPI ddraw_meminput_QueryInterface(IMemInputPin *iface, REFIID iid, void **out)
1202 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
1203 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
1206 static ULONG WINAPI ddraw_meminput_AddRef(IMemInputPin *iface)
1208 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
1209 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
1212 static ULONG WINAPI ddraw_meminput_Release(IMemInputPin *iface)
1214 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
1215 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
1218 static HRESULT WINAPI ddraw_meminput_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
1220 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
1222 TRACE("stream %p, allocator %p.\n", stream, allocator);
1224 if (stream->allocator)
1226 IMemAllocator_AddRef(*allocator = stream->allocator);
1227 return S_OK;
1230 *allocator = NULL;
1231 return VFW_E_NO_ALLOCATOR;
1234 static HRESULT WINAPI ddraw_meminput_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readonly)
1236 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
1238 TRACE("stream %p, allocator %p, readonly %d.\n", stream, allocator, readonly);
1240 if (!allocator)
1241 return E_POINTER;
1243 if (allocator)
1244 IMemAllocator_AddRef(allocator);
1245 if (stream->allocator)
1246 IMemAllocator_Release(stream->allocator);
1247 stream->allocator = allocator;
1249 return S_OK;
1252 static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
1254 TRACE("iface %p, props %p.\n", iface, props);
1255 return E_NOTIMPL;
1258 static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample)
1260 struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
1261 BITMAPINFOHEADER *bitmap_info;
1262 BYTE *top_down_pointer;
1263 int top_down_stride;
1264 BYTE *pointer;
1265 BOOL top_down;
1266 int stride;
1267 HRESULT hr;
1269 TRACE("stream %p, sample %p.\n", stream, sample);
1271 hr = IMediaSample_GetPointer(sample, &pointer);
1272 if (FAILED(hr))
1273 return hr;
1275 EnterCriticalSection(&stream->cs);
1277 bitmap_info = &((VIDEOINFOHEADER *)stream->mt.pbFormat)->bmiHeader;
1279 stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) & ~31) / 8;
1280 top_down = (bitmap_info->biHeight < 0);
1282 top_down_stride = top_down ? stride : -stride;
1283 top_down_pointer = top_down ? pointer : pointer + stride * (bitmap_info->biHeight - 1);
1285 for (;;)
1287 if (stream->state == State_Stopped)
1289 LeaveCriticalSection(&stream->cs);
1290 return S_OK;
1292 if (!list_empty(&stream->update_queue))
1294 struct ddraw_sample *sample = LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry);
1296 sample->update_hr = process_update(sample, top_down_stride, top_down_pointer);
1298 remove_queued_update(sample);
1299 LeaveCriticalSection(&stream->cs);
1300 return S_OK;
1303 SleepConditionVariableCS(&stream->update_queued_cv, &stream->cs, INFINITE);
1307 static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface,
1308 IMediaSample **samples, LONG count, LONG *processed)
1310 FIXME("iface %p, samples %p, count %u, processed %p, stub!\n", iface, samples, count, processed);
1311 return E_NOTIMPL;
1314 static HRESULT WINAPI ddraw_meminput_ReceiveCanBlock(IMemInputPin *iface)
1316 TRACE("iface %p.\n", iface);
1317 return S_OK;
1320 static const IMemInputPinVtbl ddraw_meminput_vtbl =
1322 ddraw_meminput_QueryInterface,
1323 ddraw_meminput_AddRef,
1324 ddraw_meminput_Release,
1325 ddraw_meminput_GetAllocator,
1326 ddraw_meminput_NotifyAllocator,
1327 ddraw_meminput_GetAllocatorRequirements,
1328 ddraw_meminput_Receive,
1329 ddraw_meminput_ReceiveMultiple,
1330 ddraw_meminput_ReceiveCanBlock,
1333 HRESULT ddraw_stream_create(IUnknown *outer, void **out)
1335 struct ddraw_stream *object;
1337 if (outer)
1338 return CLASS_E_NOAGGREGATION;
1340 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1341 if (!object)
1342 return E_OUTOFMEMORY;
1344 object->IAMMediaStream_iface.lpVtbl = &ddraw_IAMMediaStream_vtbl;
1345 object->IDirectDrawMediaStream_iface.lpVtbl = &ddraw_IDirectDrawMediaStream_Vtbl;
1346 object->IMemInputPin_iface.lpVtbl = &ddraw_meminput_vtbl;
1347 object->IPin_iface.lpVtbl = &ddraw_sink_vtbl;
1348 object->ref = 1;
1350 object->format.width = 100;
1351 object->format.height = 100;
1353 InitializeCriticalSection(&object->cs);
1354 InitializeConditionVariable(&object->update_queued_cv);
1355 list_init(&object->update_queue);
1357 TRACE("Created ddraw stream %p.\n", object);
1359 *out = &object->IAMMediaStream_iface;
1361 return S_OK;
1364 static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface)
1366 return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface);
1369 /*** IUnknown methods ***/
1370 static HRESULT WINAPI ddraw_sample_QueryInterface(IDirectDrawStreamSample *iface,
1371 REFIID riid, void **ret_iface)
1373 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ret_iface);
1375 if (IsEqualGUID(riid, &IID_IUnknown) ||
1376 IsEqualGUID(riid, &IID_IStreamSample) ||
1377 IsEqualGUID(riid, &IID_IDirectDrawStreamSample))
1379 IDirectDrawStreamSample_AddRef(iface);
1380 *ret_iface = iface;
1381 return S_OK;
1384 *ret_iface = NULL;
1386 ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
1387 return E_NOINTERFACE;
1390 static ULONG WINAPI ddraw_sample_AddRef(IDirectDrawStreamSample *iface)
1392 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1393 ULONG ref = InterlockedIncrement(&sample->ref);
1395 TRACE("(%p)->(): new ref = %u\n", iface, ref);
1397 return ref;
1400 static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)
1402 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1403 ULONG ref = InterlockedDecrement(&sample->ref);
1405 TRACE("(%p)->(): new ref = %u\n", iface, ref);
1407 if (!ref)
1409 EnterCriticalSection(&sample->parent->cs);
1410 --sample->parent->sample_refs;
1411 LeaveCriticalSection(&sample->parent->cs);
1413 IAMMediaStream_Release(&sample->parent->IAMMediaStream_iface);
1415 if (sample->surface)
1416 IDirectDrawSurface_Release(sample->surface);
1417 CloseHandle(sample->update_event);
1418 HeapFree(GetProcessHeap(), 0, sample);
1421 return ref;
1424 /*** IStreamSample methods ***/
1425 static HRESULT WINAPI ddraw_sample_GetMediaStream(IDirectDrawStreamSample *iface, IMediaStream **media_stream)
1427 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1429 TRACE("sample %p, media_stream %p.\n", sample, media_stream);
1431 if (!media_stream)
1432 return E_POINTER;
1434 IAMMediaStream_AddRef(&sample->parent->IAMMediaStream_iface);
1435 *media_stream = (IMediaStream *)&sample->parent->IAMMediaStream_iface;
1437 return S_OK;
1440 static HRESULT WINAPI ddraw_sample_GetSampleTimes(IDirectDrawStreamSample *iface, STREAM_TIME *start_time,
1441 STREAM_TIME *end_time, STREAM_TIME *current_time)
1443 FIXME("(%p)->(%p,%p,%p): stub\n", iface, start_time, end_time, current_time);
1445 return E_NOTIMPL;
1448 static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface, const STREAM_TIME *start_time,
1449 const STREAM_TIME *end_time)
1451 FIXME("(%p)->(%p,%p): stub\n", iface, start_time, end_time);
1453 return E_NOTIMPL;
1456 static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface,
1457 DWORD flags, HANDLE event, PAPCFUNC apc_func, DWORD apc_data)
1459 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1461 TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n",
1462 sample, flags, event, apc_func, apc_data);
1464 if (event && apc_func)
1465 return E_INVALIDARG;
1467 if (apc_func)
1469 FIXME("APC support is not implemented!\n");
1470 return E_NOTIMPL;
1473 if (event)
1475 FIXME("Event parameter support is not implemented!\n");
1476 return E_NOTIMPL;
1479 if (flags & ~SSUPDATE_ASYNC)
1481 FIXME("Unsupported flags %#x.\n", flags);
1482 return E_NOTIMPL;
1485 EnterCriticalSection(&sample->parent->cs);
1487 if (sample->parent->state != State_Running)
1489 LeaveCriticalSection(&sample->parent->cs);
1490 return MS_E_NOTRUNNING;
1492 if (!sample->parent->peer || sample->parent->eos)
1494 LeaveCriticalSection(&sample->parent->cs);
1495 return MS_S_ENDOFSTREAM;
1497 if (MS_S_PENDING == sample->update_hr)
1499 LeaveCriticalSection(&sample->parent->cs);
1500 return MS_E_BUSY;
1503 sample->update_hr = MS_S_PENDING;
1504 ResetEvent(sample->update_event);
1505 list_add_tail(&sample->parent->update_queue, &sample->entry);
1506 WakeConditionVariable(&sample->parent->update_queued_cv);
1508 LeaveCriticalSection(&sample->parent->cs);
1510 if (flags & SSUPDATE_ASYNC)
1511 return MS_S_PENDING;
1513 WaitForSingleObject(sample->update_event, INFINITE);
1515 return sample->update_hr;
1518 static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)
1520 FIXME("(%p)->(%x,%u): stub\n", iface, flags, milliseconds);
1522 return E_NOTIMPL;
1525 /*** IDirectDrawStreamSample methods ***/
1526 static HRESULT WINAPI ddraw_sample_GetSurface(IDirectDrawStreamSample *iface, IDirectDrawSurface **ddraw_surface,
1527 RECT *rect)
1529 struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
1531 TRACE("(%p)->(%p,%p)\n", iface, ddraw_surface, rect);
1533 if (ddraw_surface)
1535 *ddraw_surface = sample->surface;
1536 if (*ddraw_surface)
1537 IDirectDrawSurface_AddRef(*ddraw_surface);
1540 if (rect)
1541 *rect = sample->rect;
1543 return S_OK;
1546 static HRESULT WINAPI ddraw_sample_SetRect(IDirectDrawStreamSample *iface, const RECT *rect)
1548 FIXME("(%p)->(%p): stub\n", iface, rect);
1550 return E_NOTIMPL;
1553 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl =
1555 /*** IUnknown methods ***/
1556 ddraw_sample_QueryInterface,
1557 ddraw_sample_AddRef,
1558 ddraw_sample_Release,
1559 /*** IStreamSample methods ***/
1560 ddraw_sample_GetMediaStream,
1561 ddraw_sample_GetSampleTimes,
1562 ddraw_sample_SetSampleTimes,
1563 ddraw_sample_Update,
1564 ddraw_sample_CompletionStatus,
1565 /*** IDirectDrawStreamSample methods ***/
1566 ddraw_sample_GetSurface,
1567 ddraw_sample_SetRect
1570 static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
1571 const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample)
1573 struct ddraw_sample *object;
1574 DDSURFACEDESC desc;
1575 HRESULT hr;
1577 TRACE("(%p)\n", ddraw_stream_sample);
1579 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1580 if (!object)
1581 return E_OUTOFMEMORY;
1583 object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl;
1584 object->ref = 1;
1585 object->parent = parent;
1586 object->update_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1587 IAMMediaStream_AddRef(&parent->IAMMediaStream_iface);
1588 ++parent->sample_refs;
1590 if (surface)
1592 object->surface = surface;
1593 IDirectDrawSurface_AddRef(surface);
1595 else
1597 IDirectDraw *ddraw;
1599 hr = IDirectDrawMediaStream_GetDirectDraw(&parent->IDirectDrawMediaStream_iface, &ddraw);
1600 if (FAILED(hr))
1602 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1603 return hr;
1606 desc.dwSize = sizeof(desc);
1607 desc.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
1608 desc.dwHeight = parent->format.height;
1609 desc.dwWidth = parent->format.width;
1610 if (parent->format.flags & DDSD_PIXELFORMAT)
1612 desc.ddpfPixelFormat = parent->format.pf;
1614 else
1616 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
1617 desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1618 desc.ddpfPixelFormat.u1.dwRGBBitCount = 32;
1619 desc.ddpfPixelFormat.u2.dwRBitMask = 0xff0000;
1620 desc.ddpfPixelFormat.u3.dwGBitMask = 0x00ff00;
1621 desc.ddpfPixelFormat.u4.dwBBitMask = 0x0000ff;
1622 desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask = 0;
1624 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN;
1625 desc.lpSurface = NULL;
1627 hr = IDirectDraw_CreateSurface(ddraw, &desc, &object->surface, NULL);
1628 IDirectDraw_Release(ddraw);
1629 if (FAILED(hr))
1631 ERR("failed to create surface, 0x%08x\n", hr);
1632 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1633 return hr;
1637 desc.dwSize = sizeof(desc);
1638 hr = IDirectDrawSurface_GetSurfaceDesc(object->surface, &desc);
1639 if (FAILED(hr))
1641 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1642 return hr;
1645 if (rect)
1647 object->rect = *rect;
1648 desc.dwWidth = rect->right - rect->left;
1649 desc.dwHeight = rect->bottom - rect->top;
1651 else
1653 SetRect(&object->rect, 0, 0, desc.dwWidth, desc.dwHeight);
1656 hr = IDirectDrawMediaStream_SetFormat(&parent->IDirectDrawMediaStream_iface, &desc, NULL);
1657 if (FAILED(hr))
1659 IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
1660 return hr;
1663 *ddraw_stream_sample = &object->IDirectDrawStreamSample_iface;
1665 return S_OK;