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
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}";
41 IAMMediaStream IAMMediaStream_iface
;
42 IDirectDrawMediaStream IDirectDrawMediaStream_iface
;
43 IMemInputPin IMemInputPin_iface
;
48 IMultiMediaStream
* parent
;
50 STREAM_TYPE stream_type
;
53 IMediaStreamFilter
*filter
;
57 IMemAllocator
*allocator
;
62 CONDITION_VARIABLE update_queued_cv
;
63 struct list update_queue
;
68 IDirectDrawStreamSample IDirectDrawStreamSample_iface
;
70 struct ddraw_stream
*parent
;
71 IDirectDrawSurface
*surface
;
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
)
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
)
108 desc
.dwSize
= sizeof(desc
);
109 hr
= IDirectDrawSurface_Lock(sample
->surface
, &sample
->rect
, &desc
, DDLOCK_WAIT
, NULL
);
113 row_size
= (sample
->rect
.right
- sample
->rect
.left
) * desc
.ddpfPixelFormat
.u1
.dwRGBBitCount
/ 8;
115 dst_row
= desc
.lpSurface
;
116 for (row
= sample
->rect
.top
; row
< sample
->rect
.bottom
; ++row
)
118 memcpy(dst_row
, src_row
, row_size
);
120 dst_row
+= desc
.u1
.lPitch
;
123 hr
= IDirectDrawSurface_Unlock(sample
->surface
, desc
.lpSurface
);
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
)
138 if (stream
->format
.flags
& DDSD_PIXELFORMAT
)
140 if (stream
->format
.pf
.dwFlags
& DDPF_FOURCC
)
142 if (stream
->format
.pf
.u1
.dwRGBBitCount
!= connection_pf
->u1
.dwRGBBitCount
)
144 if (stream
->format
.pf
.u1
.dwRGBBitCount
== 16 && stream
->format
.pf
.u3
.dwGBitMask
!= connection_pf
->u3
.dwGBitMask
)
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
);
171 else if (IsEqualGUID(riid
, &IID_IDirectDrawMediaStream
))
173 IAMMediaStream_AddRef(iface
);
174 *ret_iface
= &This
->IDirectDrawMediaStream_iface
;
177 else if (IsEqualGUID(riid
, &IID_IPin
))
179 IAMMediaStream_AddRef(iface
);
180 *ret_iface
= &This
->IPin_iface
;
183 else if (IsEqualGUID(riid
, &IID_IMemInputPin
))
185 IAMMediaStream_AddRef(iface
);
186 *ret_iface
= &This
->IMemInputPin_iface
;
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
);
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
);
213 DeleteCriticalSection(&stream
->cs
);
215 IDirectDraw_Release(stream
->ddraw
);
216 HeapFree(GetProcessHeap(), 0, stream
);
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
);
234 IMultiMediaStream_AddRef(stream
->parent
);
235 *mmstream
= stream
->parent
;
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
);
247 *purpose_id
= This
->purpose_id
;
249 *type
= This
->stream_type
;
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
);
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
);
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
);
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
);
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
);
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
);
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
;
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
);
318 if (FAILED(hr
= DirectDrawCreate(NULL
, &stream
->ddraw
, NULL
)))
320 IDirectDraw_SetCooperativeLevel(stream
->ddraw
, NULL
, DDSCL_NORMAL
);
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
)
339 stream
->state
= state
;
341 LeaveCriticalSection(&stream
->cs
);
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
;
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
;
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
;
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
);
483 LeaveCriticalSection(&stream
->cs
);
484 return MS_E_NOSTREAM
;
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
;
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
;
511 LeaveCriticalSection(&stream
->cs
);
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
;
525 TRACE("stream %p, format %p, palette %p.\n", stream
, format
, palette
);
528 FIXME("Setting palette is not yet supported.\n");
533 if (format
->dwSize
!= sizeof(DDSURFACEDESC
))
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
)
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
)
558 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
))
559 return DDERR_INVALIDSURFACETYPE
;
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
;
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
;
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
);
604 stream
->format
= old_format
;
605 LeaveCriticalSection(&stream
->cs
);
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
);
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
);
633 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream
*iface
,
636 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
638 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
649 IDirectDraw_AddRef(stream
->ddraw
);
650 *ddraw
= stream
->ddraw
;
655 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream
*iface
,
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
);
672 IDirectDraw_Release(stream
->ddraw
);
676 IDirectDraw_AddRef(ddraw
);
677 stream
->ddraw
= ddraw
;
680 stream
->ddraw
= NULL
;
682 LeaveCriticalSection(&stream
->cs
);
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
);
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
)
700 EnterCriticalSection(&stream
->cs
);
701 hr
= ddrawstreamsample_create(stream
, surface
, rect
, sample
);
702 LeaveCriticalSection(&stream
->cs
);
707 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream
*iface
,
708 STREAM_TIME
*pFrameTime
)
710 FIXME("(%p)->(%p) stub!\n", iface
, pFrameTime
);
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
;
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
);
762 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
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
);
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
);
781 heap_free(enum_media_types
);
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
);
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
;
804 return count
== 1 ? S_OK
: S_FALSE
;
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
;
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;
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
;
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
);
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
;
897 DDPIXELFORMAT pf
= {sizeof(DDPIXELFORMAT
)};
899 TRACE("stream %p, peer %p, mt %p.\n", stream
, peer
, mt
);
901 EnterCriticalSection(&stream
->cs
);
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;
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
);
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
);
997 LeaveCriticalSection(&stream
->cs
);
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
);
1011 static HRESULT WINAPI
ddraw_sink_ConnectedTo(IPin
*iface
, IPin
**peer
)
1013 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1016 TRACE("stream %p, peer %p.\n", stream
, peer
);
1018 EnterCriticalSection(&stream
->cs
);
1022 IPin_AddRef(*peer
= stream
->peer
);
1028 hr
= VFW_E_NOT_CONNECTED
;
1031 LeaveCriticalSection(&stream
->cs
);
1036 static HRESULT WINAPI
ddraw_sink_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mt
)
1038 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1041 TRACE("stream %p, mt %p.\n", stream
, mt
);
1043 EnterCriticalSection(&stream
->cs
);
1047 CopyMediaType(mt
, &stream
->mt
);
1052 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
1053 hr
= VFW_E_NOT_CONNECTED
;
1056 LeaveCriticalSection(&stream
->cs
);
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
);
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
;
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
);
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
))
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
)
1114 if (!(object
= heap_alloc(sizeof(*object
))))
1115 return E_OUTOFMEMORY
;
1117 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
1118 object
->refcount
= 1;
1121 *enum_media_types
= &object
->IEnumMediaTypes_iface
;
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
);
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
);
1141 LeaveCriticalSection(&stream
->cs
);
1147 flush_update_queue(stream
, MS_S_ENDOFSTREAM
);
1149 LeaveCriticalSection(&stream
->cs
);
1154 static HRESULT WINAPI
ddraw_sink_BeginFlush(IPin
*iface
)
1156 FIXME("iface %p, stub!\n", iface
);
1160 static HRESULT WINAPI
ddraw_sink_EndFlush(IPin
*iface
)
1162 FIXME("iface %p, stub!\n", iface
);
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
);
1173 static const IPinVtbl ddraw_sink_vtbl
=
1175 ddraw_sink_QueryInterface
,
1179 ddraw_sink_ReceiveConnection
,
1180 ddraw_sink_Disconnect
,
1181 ddraw_sink_ConnectedTo
,
1182 ddraw_sink_ConnectionMediaType
,
1183 ddraw_sink_QueryPinInfo
,
1184 ddraw_sink_QueryDirection
,
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
);
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
);
1244 IMemAllocator_AddRef(allocator
);
1245 if (stream
->allocator
)
1246 IMemAllocator_Release(stream
->allocator
);
1247 stream
->allocator
= allocator
;
1252 static HRESULT WINAPI
ddraw_meminput_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
1254 TRACE("iface %p, props %p.\n", iface
, props
);
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
;
1269 TRACE("stream %p, sample %p.\n", stream
, sample
);
1271 hr
= IMediaSample_GetPointer(sample
, &pointer
);
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);
1287 if (stream
->state
== State_Stopped
)
1289 LeaveCriticalSection(&stream
->cs
);
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
);
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
);
1314 static HRESULT WINAPI
ddraw_meminput_ReceiveCanBlock(IMemInputPin
*iface
)
1316 TRACE("iface %p.\n", iface
);
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
;
1338 return CLASS_E_NOAGGREGATION
;
1340 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*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
;
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
;
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
);
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
);
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
);
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
);
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
);
1434 IAMMediaStream_AddRef(&sample
->parent
->IAMMediaStream_iface
);
1435 *media_stream
= (IMediaStream
*)&sample
->parent
->IAMMediaStream_iface
;
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
);
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
);
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
;
1469 FIXME("APC support is not implemented!\n");
1475 FIXME("Event parameter support is not implemented!\n");
1479 if (flags
& ~SSUPDATE_ASYNC
)
1481 FIXME("Unsupported flags %#x.\n", flags
);
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
);
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
);
1525 /*** IDirectDrawStreamSample methods ***/
1526 static HRESULT WINAPI
ddraw_sample_GetSurface(IDirectDrawStreamSample
*iface
, IDirectDrawSurface
**ddraw_surface
,
1529 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1531 TRACE("(%p)->(%p,%p)\n", iface
, ddraw_surface
, rect
);
1535 *ddraw_surface
= sample
->surface
;
1537 IDirectDrawSurface_AddRef(*ddraw_surface
);
1541 *rect
= sample
->rect
;
1546 static HRESULT WINAPI
ddraw_sample_SetRect(IDirectDrawStreamSample
*iface
, const RECT
*rect
)
1548 FIXME("(%p)->(%p): stub\n", iface
, rect
);
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
;
1577 TRACE("(%p)\n", ddraw_stream_sample
);
1579 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1581 return E_OUTOFMEMORY
;
1583 object
->IDirectDrawStreamSample_iface
.lpVtbl
= &DirectDrawStreamSample_Vtbl
;
1585 object
->parent
= parent
;
1586 object
->update_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1587 IAMMediaStream_AddRef(&parent
->IAMMediaStream_iface
);
1588 ++parent
->sample_refs
;
1592 object
->surface
= surface
;
1593 IDirectDrawSurface_AddRef(surface
);
1599 hr
= IDirectDrawMediaStream_GetDirectDraw(&parent
->IDirectDrawMediaStream_iface
, &ddraw
);
1602 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
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
;
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
);
1631 ERR("failed to create surface, 0x%08x\n", hr
);
1632 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1637 desc
.dwSize
= sizeof(desc
);
1638 hr
= IDirectDrawSurface_GetSurfaceDesc(object
->surface
, &desc
);
1641 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1647 object
->rect
= *rect
;
1648 desc
.dwWidth
= rect
->right
- rect
->left
;
1649 desc
.dwHeight
= rect
->bottom
- rect
->top
;
1653 SetRect(&object
->rect
, 0, 0, desc
.dwWidth
, desc
.dwHeight
);
1656 hr
= IDirectDrawMediaStream_SetFormat(&parent
->IDirectDrawMediaStream_iface
, &desc
, NULL
);
1659 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1663 *ddraw_stream_sample
= &object
->IDirectDrawStreamSample_iface
;