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
22 #include "amstream_private.h"
23 #include "wine/debug.h"
24 #include "wine/list.h"
25 #include "wine/strmbase.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
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
;
61 REFERENCE_TIME segment_start
;
64 CONDITION_VARIABLE update_queued_cv
;
65 struct list update_queue
;
70 IDirectDrawStreamSample IDirectDrawStreamSample_iface
;
72 struct ddraw_stream
*parent
;
73 IMultiMediaStream
*mmstream
;
74 IDirectDrawSurface
*surface
;
76 STREAM_TIME start_time
;
78 BOOL continuous_update
;
79 CONDITION_VARIABLE update_cv
;
80 HANDLE external_event
;
87 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
88 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
);
90 static void remove_queued_update(struct ddraw_sample
*sample
)
93 list_remove(&sample
->entry
);
94 WakeConditionVariable(&sample
->update_cv
);
95 if (sample
->external_event
)
96 SetEvent(sample
->external_event
);
99 static void flush_update_queue(struct ddraw_stream
*stream
, HRESULT update_hr
)
102 while ((entry
= list_head(&stream
->update_queue
)))
104 struct ddraw_sample
*sample
= LIST_ENTRY(entry
, struct ddraw_sample
, entry
);
105 sample
->update_hr
= update_hr
;
106 remove_queued_update(sample
);
110 static HRESULT
process_update(struct ddraw_sample
*sample
, int stride
, BYTE
*pointer
,
111 STREAM_TIME start_time
, STREAM_TIME end_time
)
120 desc
.dwSize
= sizeof(desc
);
121 hr
= IDirectDrawSurface_Lock(sample
->surface
, &sample
->rect
, &desc
, DDLOCK_WAIT
, NULL
);
125 row_size
= (sample
->rect
.right
- sample
->rect
.left
) * desc
.ddpfPixelFormat
.dwRGBBitCount
/ 8;
127 dst_row
= desc
.lpSurface
;
128 for (row
= sample
->rect
.top
; row
< sample
->rect
.bottom
; ++row
)
130 memcpy(dst_row
, src_row
, row_size
);
132 dst_row
+= desc
.lPitch
;
135 hr
= IDirectDrawSurface_Unlock(sample
->surface
, desc
.lpSurface
);
139 sample
->start_time
= start_time
;
140 sample
->end_time
= end_time
;
145 static BOOL
is_format_compatible(struct ddraw_stream
*stream
,
146 DWORD width
, DWORD height
, const DDPIXELFORMAT
*connection_pf
)
148 if (stream
->format
.flags
& DDSD_HEIGHT
)
150 if (stream
->format
.width
!= width
|| stream
->format
.height
!= height
)
153 if (stream
->format
.flags
& DDSD_PIXELFORMAT
)
155 if (stream
->format
.pf
.dwFlags
& DDPF_FOURCC
)
157 if (stream
->format
.pf
.dwRGBBitCount
!= connection_pf
->dwRGBBitCount
)
159 if (stream
->format
.pf
.dwRGBBitCount
== 16 && stream
->format
.pf
.dwGBitMask
!= connection_pf
->dwGBitMask
)
165 static inline struct ddraw_stream
*impl_from_IAMMediaStream(IAMMediaStream
*iface
)
167 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IAMMediaStream_iface
);
170 /*** IUnknown methods ***/
171 static HRESULT WINAPI
ddraw_IAMMediaStream_QueryInterface(IAMMediaStream
*iface
,
172 REFIID riid
, void **ret_iface
)
174 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
176 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
178 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
179 IsEqualGUID(riid
, &IID_IMediaStream
) ||
180 IsEqualGUID(riid
, &IID_IAMMediaStream
))
182 IAMMediaStream_AddRef(iface
);
186 else if (IsEqualGUID(riid
, &IID_IDirectDrawMediaStream
))
188 IAMMediaStream_AddRef(iface
);
189 *ret_iface
= &This
->IDirectDrawMediaStream_iface
;
192 else if (IsEqualGUID(riid
, &IID_IPin
))
194 IAMMediaStream_AddRef(iface
);
195 *ret_iface
= &This
->IPin_iface
;
198 else if (IsEqualGUID(riid
, &IID_IMemInputPin
))
200 IAMMediaStream_AddRef(iface
);
201 *ret_iface
= &This
->IMemInputPin_iface
;
205 ERR("(%p)->(%s,%p),not found\n", This
, debugstr_guid(riid
), ret_iface
);
206 return E_NOINTERFACE
;
209 static ULONG WINAPI
ddraw_IAMMediaStream_AddRef(IAMMediaStream
*iface
)
211 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
212 ULONG ref
= InterlockedIncrement(&This
->ref
);
214 TRACE("(%p/%p)->(): new ref = %lu\n", iface
, This
, ref
);
219 static ULONG WINAPI
ddraw_IAMMediaStream_Release(IAMMediaStream
*iface
)
221 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
222 ULONG ref
= InterlockedDecrement(&stream
->ref
);
224 TRACE("%p decreasing refcount to %lu.\n", stream
, ref
);
228 DeleteCriticalSection(&stream
->cs
);
230 IDirectDraw_Release(stream
->ddraw
);
237 /*** IMediaStream methods ***/
238 static HRESULT WINAPI
ddraw_IAMMediaStream_GetMultiMediaStream(IAMMediaStream
*iface
,
239 IMultiMediaStream
**mmstream
)
241 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
243 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
249 IMultiMediaStream_AddRef(stream
->parent
);
250 *mmstream
= stream
->parent
;
254 static HRESULT WINAPI
ddraw_IAMMediaStream_GetInformation(IAMMediaStream
*iface
,
255 MSPID
*purpose_id
, STREAM_TYPE
*type
)
257 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
259 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, purpose_id
, type
);
262 *purpose_id
= This
->purpose_id
;
264 *type
= This
->stream_type
;
269 static HRESULT WINAPI
ddraw_IAMMediaStream_SetSameFormat(IAMMediaStream
*iface
,
270 IMediaStream
*pStreamThatHasDesiredFormat
, DWORD flags
)
272 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
274 FIXME("(%p/%p)->(%p,%lx) stub!\n", This
, iface
, pStreamThatHasDesiredFormat
, flags
);
279 static HRESULT WINAPI
ddraw_IAMMediaStream_AllocateSample(IAMMediaStream
*iface
,
280 DWORD flags
, IStreamSample
**sample
)
282 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
284 FIXME("(%p/%p)->(%lx,%p) stub!\n", This
, iface
, flags
, sample
);
289 static HRESULT WINAPI
ddraw_IAMMediaStream_CreateSharedSample(IAMMediaStream
*iface
,
290 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
292 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
294 FIXME("(%p/%p)->(%p,%lx,%p) stub!\n", This
, iface
, existing_sample
, flags
, sample
);
299 static HRESULT WINAPI
ddraw_IAMMediaStream_SendEndOfStream(IAMMediaStream
*iface
, DWORD flags
)
301 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
303 FIXME("(%p/%p)->(%lx) stub!\n", This
, iface
, flags
);
308 /*** IAMMediaStream methods ***/
309 static HRESULT WINAPI
ddraw_IAMMediaStream_Initialize(IAMMediaStream
*iface
, IUnknown
*source_object
, DWORD flags
,
310 REFMSPID purpose_id
, const STREAM_TYPE stream_type
)
312 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
315 TRACE("stream %p, source_object %p, flags %lx, purpose_id %s, stream_type %u.\n", stream
, source_object
, flags
,
316 debugstr_guid(purpose_id
), stream_type
);
321 if (flags
& AMMSF_CREATEPEER
)
322 FIXME("AMMSF_CREATEPEER is not yet supported.\n");
324 stream
->purpose_id
= *purpose_id
;
325 stream
->stream_type
= stream_type
;
328 IDirectDraw_Release(stream
->ddraw
);
329 stream
->ddraw
= NULL
;
332 && FAILED(hr
= IUnknown_QueryInterface(source_object
, &IID_IDirectDraw
, (void **)&stream
->ddraw
)))
333 FIXME("Stream object doesn't implement IDirectDraw interface, hr %#lx.\n", hr
);
337 if (FAILED(hr
= DirectDrawCreate(NULL
, &stream
->ddraw
, NULL
)))
339 IDirectDraw_SetCooperativeLevel(stream
->ddraw
, NULL
, DDSCL_NORMAL
);
345 static HRESULT WINAPI
ddraw_IAMMediaStream_SetState(IAMMediaStream
*iface
, FILTER_STATE state
)
347 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
349 TRACE("stream %p, state %u.\n", stream
, state
);
351 EnterCriticalSection(&stream
->cs
);
353 if (state
== State_Stopped
)
354 WakeConditionVariable(&stream
->update_queued_cv
);
355 if (stream
->state
== State_Stopped
)
358 stream
->state
= state
;
360 LeaveCriticalSection(&stream
->cs
);
365 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream
*iface
, IAMMultiMediaStream
*mmstream
)
367 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
369 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
371 stream
->parent
= (IMultiMediaStream
*)mmstream
;
376 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilter(IAMMediaStream
*iface
, IMediaStreamFilter
*filter
)
378 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
380 TRACE("iface %p, filter %p.\n", iface
, filter
);
382 stream
->filter
= filter
;
387 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream
*iface
, IFilterGraph
*filtergraph
)
389 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
391 TRACE("stream %p, filtergraph %p.\n", stream
, filtergraph
);
393 stream
->graph
= filtergraph
;
398 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl
=
400 /*** IUnknown methods ***/
401 ddraw_IAMMediaStream_QueryInterface
,
402 ddraw_IAMMediaStream_AddRef
,
403 ddraw_IAMMediaStream_Release
,
404 /*** IMediaStream methods ***/
405 ddraw_IAMMediaStream_GetMultiMediaStream
,
406 ddraw_IAMMediaStream_GetInformation
,
407 ddraw_IAMMediaStream_SetSameFormat
,
408 ddraw_IAMMediaStream_AllocateSample
,
409 ddraw_IAMMediaStream_CreateSharedSample
,
410 ddraw_IAMMediaStream_SendEndOfStream
,
411 /*** IAMMediaStream methods ***/
412 ddraw_IAMMediaStream_Initialize
,
413 ddraw_IAMMediaStream_SetState
,
414 ddraw_IAMMediaStream_JoinAMMultiMediaStream
,
415 ddraw_IAMMediaStream_JoinFilter
,
416 ddraw_IAMMediaStream_JoinFilterGraph
419 static inline struct ddraw_stream
*impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream
*iface
)
421 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IDirectDrawMediaStream_iface
);
424 /*** IUnknown methods ***/
425 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream
*iface
,
426 REFIID riid
, void **ret_iface
)
428 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
429 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
430 return IAMMediaStream_QueryInterface(&This
->IAMMediaStream_iface
, riid
, ret_iface
);
433 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream
*iface
)
435 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
436 TRACE("(%p/%p)\n", iface
, This
);
437 return IAMMediaStream_AddRef(&This
->IAMMediaStream_iface
);
440 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream
*iface
)
442 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
443 TRACE("(%p/%p)\n", iface
, This
);
444 return IAMMediaStream_Release(&This
->IAMMediaStream_iface
);
447 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream
*iface
,
448 IMultiMediaStream
**mmstream
)
450 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
451 return IAMMediaStream_GetMultiMediaStream(&stream
->IAMMediaStream_iface
, mmstream
);
454 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream
*iface
,
455 MSPID
*purpose_id
, STREAM_TYPE
*type
)
457 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
458 return IAMMediaStream_GetInformation(&stream
->IAMMediaStream_iface
, purpose_id
, type
);
461 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream
*iface
,
462 IMediaStream
*other
, DWORD flags
)
464 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
465 return IAMMediaStream_SetSameFormat(&stream
->IAMMediaStream_iface
, other
, flags
);
468 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream
*iface
,
469 DWORD flags
, IStreamSample
**sample
)
471 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
472 return IAMMediaStream_AllocateSample(&stream
->IAMMediaStream_iface
, flags
, sample
);
475 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream
*iface
,
476 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
478 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
479 return IAMMediaStream_CreateSharedSample(&stream
->IAMMediaStream_iface
, existing_sample
, flags
, sample
);
482 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream
*iface
, DWORD flags
)
484 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
485 return IAMMediaStream_SendEndOfStream(&stream
->IAMMediaStream_iface
, flags
);
488 /*** IDirectDrawMediaStream methods ***/
489 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream
*iface
,
490 DDSURFACEDESC
*current_format
, IDirectDrawPalette
**palette
,
491 DDSURFACEDESC
*desired_format
, DWORD
*flags
)
493 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
495 TRACE("stream %p, current_format %p, palette %p, desired_format %p, flags %p.\n", stream
, current_format
, palette
,
496 desired_format
, flags
);
498 EnterCriticalSection(&stream
->cs
);
502 LeaveCriticalSection(&stream
->cs
);
503 return MS_E_NOSTREAM
;
508 current_format
->dwFlags
= stream
->format
.flags
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_CAPS
;
509 current_format
->dwWidth
= stream
->format
.width
;
510 current_format
->dwHeight
= stream
->format
.height
;
511 current_format
->ddpfPixelFormat
= stream
->format
.pf
;
512 current_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
520 desired_format
->dwFlags
= DDSD_WIDTH
| DDSD_HEIGHT
;
521 desired_format
->dwWidth
= stream
->format
.width
;
522 desired_format
->dwHeight
= stream
->format
.height
;
523 desired_format
->ddpfPixelFormat
= stream
->format
.pf
;
524 desired_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
530 LeaveCriticalSection(&stream
->cs
);
535 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream
*iface
,
536 const DDSURFACEDESC
*format
, IDirectDrawPalette
*palette
)
538 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
539 AM_MEDIA_TYPE old_media_type
;
540 struct format old_format
;
544 TRACE("stream %p, format %p, palette %p.\n", stream
, format
, palette
);
547 FIXME("Setting palette is not yet supported.\n");
552 if (format
->dwSize
!= sizeof(DDSURFACEDESC
))
555 TRACE("flags %#lx, pixel format flags %#lx, bit count %lu, size %lux%lu.\n",
556 format
->dwFlags
, format
->ddpfPixelFormat
.dwFlags
,
557 format
->ddpfPixelFormat
.dwRGBBitCount
, format
->dwWidth
, format
->dwHeight
);
559 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
561 if (format
->ddpfPixelFormat
.dwSize
!= sizeof(DDPIXELFORMAT
))
562 return DDERR_INVALIDSURFACETYPE
;
564 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
566 if (!format
->ddpfPixelFormat
.dwRGBBitCount
)
571 if (format
->ddpfPixelFormat
.dwFlags
& (DDPF_YUV
| DDPF_PALETTEINDEXED1
|
572 DDPF_PALETTEINDEXED2
| DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXEDTO8
))
573 return DDERR_INVALIDSURFACETYPE
;
575 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
))
576 return DDERR_INVALIDSURFACETYPE
;
578 switch (format
->ddpfPixelFormat
.dwRGBBitCount
)
581 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
))
582 return DDERR_INVALIDSURFACETYPE
;
585 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
586 return DDERR_INVALIDSURFACETYPE
;
587 if ((format
->ddpfPixelFormat
.dwRBitMask
!= 0x7c00 ||
588 format
->ddpfPixelFormat
.dwGBitMask
!= 0x03e0 ||
589 format
->ddpfPixelFormat
.dwBBitMask
!= 0x001f) &&
590 (format
->ddpfPixelFormat
.dwRBitMask
!= 0xf800 ||
591 format
->ddpfPixelFormat
.dwGBitMask
!= 0x07e0 ||
592 format
->ddpfPixelFormat
.dwBBitMask
!= 0x001f))
593 return DDERR_INVALIDSURFACETYPE
;
597 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
598 return DDERR_INVALIDSURFACETYPE
;
599 if (format
->ddpfPixelFormat
.dwRBitMask
!= 0xff0000 ||
600 format
->ddpfPixelFormat
.dwGBitMask
!= 0x00ff00 ||
601 format
->ddpfPixelFormat
.dwBBitMask
!= 0x0000ff)
602 return DDERR_INVALIDSURFACETYPE
;
605 return DDERR_INVALIDSURFACETYPE
;
610 EnterCriticalSection(&stream
->cs
);
612 old_format
= stream
->format
;
613 stream
->format
.flags
= format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
);
614 if (format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
))
616 stream
->format
.width
= format
->dwWidth
;
617 stream
->format
.height
= format
->dwHeight
;
619 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
620 stream
->format
.pf
= format
->ddpfPixelFormat
;
622 if (stream
->peer
&& !is_format_compatible(stream
, old_format
.width
, old_format
.height
, &old_format
.pf
))
624 hr
= CopyMediaType(&old_media_type
, &stream
->mt
);
627 stream
->format
= old_format
;
628 LeaveCriticalSection(&stream
->cs
);
631 old_peer
= stream
->peer
;
632 IPin_AddRef(old_peer
);
634 IFilterGraph_Disconnect(stream
->graph
, stream
->peer
);
635 IFilterGraph_Disconnect(stream
->graph
, &stream
->IPin_iface
);
636 hr
= IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, NULL
);
639 stream
->format
= old_format
;
640 IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, &old_media_type
);
641 IPin_Release(old_peer
);
642 FreeMediaType(&old_media_type
);
643 LeaveCriticalSection(&stream
->cs
);
644 return DDERR_INVALIDSURFACETYPE
;
647 IPin_Release(old_peer
);
648 FreeMediaType(&old_media_type
);
651 LeaveCriticalSection(&stream
->cs
);
656 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream
*iface
,
659 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
661 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
672 IDirectDraw_AddRef(stream
->ddraw
);
673 *ddraw
= stream
->ddraw
;
678 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream
*iface
,
681 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
683 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
685 EnterCriticalSection(&stream
->cs
);
687 if (stream
->sample_refs
)
689 HRESULT hr
= (stream
->ddraw
== ddraw
) ? S_OK
: MS_E_SAMPLEALLOC
;
690 LeaveCriticalSection(&stream
->cs
);
695 IDirectDraw_Release(stream
->ddraw
);
699 IDirectDraw_AddRef(ddraw
);
700 stream
->ddraw
= ddraw
;
703 stream
->ddraw
= NULL
;
705 LeaveCriticalSection(&stream
->cs
);
710 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream
*iface
,
711 IDirectDrawSurface
*surface
, const RECT
*rect
, DWORD flags
,
712 IDirectDrawStreamSample
**sample
)
714 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
717 TRACE("stream %p, surface %p, rect %s, flags %#lx, sample %p.\n",
718 stream
, surface
, wine_dbgstr_rect(rect
), flags
, sample
);
720 if (!surface
&& rect
)
723 EnterCriticalSection(&stream
->cs
);
724 hr
= ddrawstreamsample_create(stream
, surface
, rect
, sample
);
725 LeaveCriticalSection(&stream
->cs
);
730 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream
*iface
,
731 STREAM_TIME
*frame_time
)
733 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
735 TRACE("stream %p, frame_time %p.\n", stream
, frame_time
);
740 EnterCriticalSection(&stream
->cs
);
744 LeaveCriticalSection(&stream
->cs
);
745 return MS_E_NOSTREAM
;
748 *frame_time
= ((VIDEOINFO
*)stream
->mt
.pbFormat
)->AvgTimePerFrame
;
750 LeaveCriticalSection(&stream
->cs
);
755 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl
=
757 /*** IUnknown methods ***/
758 ddraw_IDirectDrawMediaStream_QueryInterface
,
759 ddraw_IDirectDrawMediaStream_AddRef
,
760 ddraw_IDirectDrawMediaStream_Release
,
761 /*** IMediaStream methods ***/
762 ddraw_IDirectDrawMediaStream_GetMultiMediaStream
,
763 ddraw_IDirectDrawMediaStream_GetInformation
,
764 ddraw_IDirectDrawMediaStream_SetSameFormat
,
765 ddraw_IDirectDrawMediaStream_AllocateSample
,
766 ddraw_IDirectDrawMediaStream_CreateSharedSample
,
767 ddraw_IDirectDrawMediaStream_SendEndOfStream
,
768 /*** IDirectDrawMediaStream methods ***/
769 ddraw_IDirectDrawMediaStream_GetFormat
,
770 ddraw_IDirectDrawMediaStream_SetFormat
,
771 ddraw_IDirectDrawMediaStream_GetDirectDraw
,
772 ddraw_IDirectDrawMediaStream_SetDirectDraw
,
773 ddraw_IDirectDrawMediaStream_CreateSample
,
774 ddraw_IDirectDrawMediaStream_GetTimePerFrame
777 struct enum_media_types
779 IEnumMediaTypes IEnumMediaTypes_iface
;
784 static const IEnumMediaTypesVtbl enum_media_types_vtbl
;
786 static struct enum_media_types
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
788 return CONTAINING_RECORD(iface
, struct enum_media_types
, IEnumMediaTypes_iface
);
791 static HRESULT WINAPI
enum_media_types_QueryInterface(IEnumMediaTypes
*iface
, REFIID iid
, void **out
)
793 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
795 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMediaTypes
))
797 IEnumMediaTypes_AddRef(iface
);
802 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
804 return E_NOINTERFACE
;
807 static ULONG WINAPI
enum_media_types_AddRef(IEnumMediaTypes
*iface
)
809 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
810 ULONG refcount
= InterlockedIncrement(&enum_media_types
->refcount
);
811 TRACE("%p increasing refcount to %lu.\n", enum_media_types
, refcount
);
815 static ULONG WINAPI
enum_media_types_Release(IEnumMediaTypes
*iface
)
817 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
818 ULONG refcount
= InterlockedDecrement(&enum_media_types
->refcount
);
819 TRACE("%p decreasing refcount to %lu.\n", enum_media_types
, refcount
);
821 free(enum_media_types
);
825 static HRESULT WINAPI
enum_media_types_Next(IEnumMediaTypes
*iface
, ULONG count
, AM_MEDIA_TYPE
**mts
, ULONG
*ret_count
)
827 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
829 TRACE("iface %p, count %lu, mts %p, ret_count %p.\n", iface
, count
, mts
, ret_count
);
834 if (count
&& !enum_media_types
->index
)
836 mts
[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
837 memset(mts
[0], 0, sizeof(AM_MEDIA_TYPE
));
838 mts
[0]->majortype
= MEDIATYPE_Video
;
839 mts
[0]->subtype
= MEDIASUBTYPE_RGB8
;
840 mts
[0]->bFixedSizeSamples
= TRUE
;
841 mts
[0]->lSampleSize
= 10000;
842 ++enum_media_types
->index
;
844 return count
== 1 ? S_OK
: S_FALSE
;
848 return count
? S_FALSE
: S_OK
;
851 static HRESULT WINAPI
enum_media_types_Skip(IEnumMediaTypes
*iface
, ULONG count
)
853 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
855 TRACE("iface %p, count %lu.\n", iface
, count
);
857 enum_media_types
->index
+= count
;
862 static HRESULT WINAPI
enum_media_types_Reset(IEnumMediaTypes
*iface
)
864 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
866 TRACE("iface %p.\n", iface
);
868 enum_media_types
->index
= 0;
872 static HRESULT WINAPI
enum_media_types_Clone(IEnumMediaTypes
*iface
, IEnumMediaTypes
**out
)
874 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
875 struct enum_media_types
*object
;
877 TRACE("iface %p, out %p.\n", iface
, out
);
879 if (!(object
= calloc(1, sizeof(*object
))))
880 return E_OUTOFMEMORY
;
882 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
883 object
->refcount
= 1;
884 object
->index
= enum_media_types
->index
;
886 *out
= &object
->IEnumMediaTypes_iface
;
890 static const IEnumMediaTypesVtbl enum_media_types_vtbl
=
892 enum_media_types_QueryInterface
,
893 enum_media_types_AddRef
,
894 enum_media_types_Release
,
895 enum_media_types_Next
,
896 enum_media_types_Skip
,
897 enum_media_types_Reset
,
898 enum_media_types_Clone
,
901 static inline struct ddraw_stream
*impl_from_IPin(IPin
*iface
)
903 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IPin_iface
);
906 static HRESULT WINAPI
ddraw_sink_QueryInterface(IPin
*iface
, REFIID iid
, void **out
)
908 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
909 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
912 static ULONG WINAPI
ddraw_sink_AddRef(IPin
*iface
)
914 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
915 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
918 static ULONG WINAPI
ddraw_sink_Release(IPin
*iface
)
920 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
921 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
924 static HRESULT WINAPI
ddraw_sink_Connect(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
926 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface
, peer
, mt
);
930 static HRESULT WINAPI
ddraw_sink_ReceiveConnection(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
932 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
933 const VIDEOINFOHEADER
*video_info
;
937 DDPIXELFORMAT pf
= {sizeof(DDPIXELFORMAT
)};
939 TRACE("stream %p, peer %p, mt %p.\n", stream
, peer
, mt
);
941 EnterCriticalSection(&stream
->cs
);
945 LeaveCriticalSection(&stream
->cs
);
946 return VFW_E_ALREADY_CONNECTED
;
949 if (!IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
950 || !IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
952 LeaveCriticalSection(&stream
->cs
);
953 return VFW_E_TYPE_NOT_ACCEPTED
;
956 video_info
= (const VIDEOINFOHEADER
*)mt
->pbFormat
;
958 width
= video_info
->bmiHeader
.biWidth
;
959 height
= abs(video_info
->bmiHeader
.biHeight
);
960 pf
.dwFlags
= DDPF_RGB
;
961 if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
))
963 pf
.dwFlags
|= DDPF_PALETTEINDEXED8
;
964 pf
.dwRGBBitCount
= 8;
966 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB555
))
968 pf
.dwRGBBitCount
= 16;
969 pf
.dwRBitMask
= 0x7c00;
970 pf
.dwGBitMask
= 0x03e0;
971 pf
.dwBBitMask
= 0x001f;
973 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB565
))
975 pf
.dwRGBBitCount
= 16;
976 pf
.dwRBitMask
= 0xf800;
977 pf
.dwGBitMask
= 0x07e0;
978 pf
.dwBBitMask
= 0x001f;
980 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB24
))
982 pf
.dwRGBBitCount
= 24;
983 pf
.dwRBitMask
= 0xff0000;
984 pf
.dwGBitMask
= 0x00ff00;
985 pf
.dwBBitMask
= 0x0000ff;
987 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB32
))
989 pf
.dwRGBBitCount
= 32;
990 pf
.dwRBitMask
= 0xff0000;
991 pf
.dwGBitMask
= 0x00ff00;
992 pf
.dwBBitMask
= 0x0000ff;
996 LeaveCriticalSection(&stream
->cs
);
997 return VFW_E_TYPE_NOT_ACCEPTED
;
1000 if (!is_format_compatible(stream
, width
, height
, &pf
))
1002 LeaveCriticalSection(&stream
->cs
);
1003 return VFW_E_TYPE_NOT_ACCEPTED
;
1006 IPin_QueryDirection(peer
, &dir
);
1007 if (dir
!= PINDIR_OUTPUT
)
1009 WARN("Rejecting connection from input pin.\n");
1010 LeaveCriticalSection(&stream
->cs
);
1011 return VFW_E_INVALID_DIRECTION
;
1014 CopyMediaType(&stream
->mt
, mt
);
1015 IPin_AddRef(stream
->peer
= peer
);
1017 stream
->format
.width
= width
;
1018 stream
->format
.height
= height
;
1019 if (!(stream
->format
.flags
& DDSD_PIXELFORMAT
))
1020 stream
->format
.pf
= pf
;
1022 LeaveCriticalSection(&stream
->cs
);
1027 static HRESULT WINAPI
ddraw_sink_Disconnect(IPin
*iface
)
1029 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1031 TRACE("stream %p.\n", stream
);
1033 EnterCriticalSection(&stream
->cs
);
1037 LeaveCriticalSection(&stream
->cs
);
1041 IPin_Release(stream
->peer
);
1042 stream
->peer
= NULL
;
1043 FreeMediaType(&stream
->mt
);
1044 memset(&stream
->mt
, 0, sizeof(AM_MEDIA_TYPE
));
1046 LeaveCriticalSection(&stream
->cs
);
1051 static HRESULT WINAPI
ddraw_sink_ConnectedTo(IPin
*iface
, IPin
**peer
)
1053 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1056 TRACE("stream %p, peer %p.\n", stream
, peer
);
1058 EnterCriticalSection(&stream
->cs
);
1062 IPin_AddRef(*peer
= stream
->peer
);
1068 hr
= VFW_E_NOT_CONNECTED
;
1071 LeaveCriticalSection(&stream
->cs
);
1076 static HRESULT WINAPI
ddraw_sink_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mt
)
1078 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1081 TRACE("stream %p, mt %p.\n", stream
, mt
);
1083 EnterCriticalSection(&stream
->cs
);
1087 CopyMediaType(mt
, &stream
->mt
);
1092 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
1093 hr
= VFW_E_NOT_CONNECTED
;
1096 LeaveCriticalSection(&stream
->cs
);
1101 static HRESULT WINAPI
ddraw_sink_QueryPinInfo(IPin
*iface
, PIN_INFO
*info
)
1103 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1105 TRACE("stream %p, info %p.\n", stream
, info
);
1107 IBaseFilter_AddRef(info
->pFilter
= (IBaseFilter
*)stream
->filter
);
1108 info
->dir
= PINDIR_INPUT
;
1109 wcscpy(info
->achName
, sink_id
);
1114 static HRESULT WINAPI
ddraw_sink_QueryDirection(IPin
*iface
, PIN_DIRECTION
*dir
)
1116 TRACE("iface %p, dir %p.\n", iface
, dir
);
1117 *dir
= PINDIR_INPUT
;
1121 static HRESULT WINAPI
ddraw_sink_QueryId(IPin
*iface
, WCHAR
**id
)
1123 TRACE("iface %p, id %p.\n", iface
, id
);
1125 if (!(*id
= CoTaskMemAlloc(sizeof(sink_id
))))
1126 return E_OUTOFMEMORY
;
1128 wcscpy(*id
, sink_id
);
1133 static HRESULT WINAPI
ddraw_sink_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*mt
)
1135 TRACE("iface %p, mt %p.\n", iface
, mt
);
1137 if (IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
1138 && IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
)
1139 && IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
1142 return VFW_E_TYPE_NOT_ACCEPTED
;
1145 static HRESULT WINAPI
ddraw_sink_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**enum_media_types
)
1147 struct enum_media_types
*object
;
1149 TRACE("iface %p, enum_media_types %p.\n", iface
, enum_media_types
);
1151 if (!enum_media_types
)
1154 if (!(object
= calloc(1, sizeof(*object
))))
1155 return E_OUTOFMEMORY
;
1157 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
1158 object
->refcount
= 1;
1161 *enum_media_types
= &object
->IEnumMediaTypes_iface
;
1165 static HRESULT WINAPI
ddraw_sink_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*count
)
1167 TRACE("iface %p, pins %p, count %p.\n", iface
, pins
, count
);
1171 static HRESULT WINAPI
ddraw_sink_EndOfStream(IPin
*iface
)
1173 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1175 TRACE("stream %p.\n", stream
);
1177 EnterCriticalSection(&stream
->cs
);
1179 if (stream
->eos
|| stream
->flushing
)
1181 LeaveCriticalSection(&stream
->cs
);
1187 flush_update_queue(stream
, MS_S_ENDOFSTREAM
);
1189 LeaveCriticalSection(&stream
->cs
);
1191 /* Calling IMediaStreamFilter::EndOfStream() inside the critical section
1192 * would invert the locking order, so we must leave it first to avoid
1193 * the streaming thread deadlocking on the filter's critical section. */
1194 IMediaStreamFilter_EndOfStream(stream
->filter
);
1199 static HRESULT WINAPI
ddraw_sink_BeginFlush(IPin
*iface
)
1201 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1204 TRACE("stream %p.\n", stream
);
1206 EnterCriticalSection(&stream
->cs
);
1208 cancel_eos
= stream
->eos
;
1210 stream
->flushing
= TRUE
;
1211 stream
->eos
= FALSE
;
1212 WakeConditionVariable(&stream
->update_queued_cv
);
1214 LeaveCriticalSection(&stream
->cs
);
1216 /* Calling IMediaStreamFilter::Flush() inside the critical section would
1217 * invert the locking order, so we must leave it first to avoid the
1218 * application thread deadlocking on the filter's critical section. */
1219 IMediaStreamFilter_Flush(stream
->filter
, cancel_eos
);
1224 static HRESULT WINAPI
ddraw_sink_EndFlush(IPin
*iface
)
1226 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1228 TRACE("stream %p.\n", stream
);
1230 EnterCriticalSection(&stream
->cs
);
1232 stream
->flushing
= FALSE
;
1234 LeaveCriticalSection(&stream
->cs
);
1239 static HRESULT WINAPI
ddraw_sink_NewSegment(IPin
*iface
, REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
1241 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1243 TRACE("stream %p, start %s, stop %s, rate %0.16e\n",
1244 stream
, wine_dbgstr_longlong(start
), wine_dbgstr_longlong(stop
), rate
);
1246 EnterCriticalSection(&stream
->cs
);
1248 stream
->segment_start
= start
;
1250 LeaveCriticalSection(&stream
->cs
);
1255 static const IPinVtbl ddraw_sink_vtbl
=
1257 ddraw_sink_QueryInterface
,
1261 ddraw_sink_ReceiveConnection
,
1262 ddraw_sink_Disconnect
,
1263 ddraw_sink_ConnectedTo
,
1264 ddraw_sink_ConnectionMediaType
,
1265 ddraw_sink_QueryPinInfo
,
1266 ddraw_sink_QueryDirection
,
1268 ddraw_sink_QueryAccept
,
1269 ddraw_sink_EnumMediaTypes
,
1270 ddraw_sink_QueryInternalConnections
,
1271 ddraw_sink_EndOfStream
,
1272 ddraw_sink_BeginFlush
,
1273 ddraw_sink_EndFlush
,
1274 ddraw_sink_NewSegment
,
1277 static inline struct ddraw_stream
*impl_from_IMemInputPin(IMemInputPin
*iface
)
1279 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IMemInputPin_iface
);
1282 static HRESULT WINAPI
ddraw_meminput_QueryInterface(IMemInputPin
*iface
, REFIID iid
, void **out
)
1284 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1285 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
1288 static ULONG WINAPI
ddraw_meminput_AddRef(IMemInputPin
*iface
)
1290 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1291 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
1294 static ULONG WINAPI
ddraw_meminput_Release(IMemInputPin
*iface
)
1296 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1297 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
1300 static HRESULT WINAPI
ddraw_meminput_GetAllocator(IMemInputPin
*iface
, IMemAllocator
**allocator
)
1302 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1304 TRACE("stream %p, allocator %p.\n", stream
, allocator
);
1306 if (stream
->allocator
)
1308 IMemAllocator_AddRef(*allocator
= stream
->allocator
);
1313 return VFW_E_NO_ALLOCATOR
;
1316 static HRESULT WINAPI
ddraw_meminput_NotifyAllocator(IMemInputPin
*iface
, IMemAllocator
*allocator
, BOOL readonly
)
1318 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1320 TRACE("stream %p, allocator %p, readonly %d.\n", stream
, allocator
, readonly
);
1326 IMemAllocator_AddRef(allocator
);
1327 if (stream
->allocator
)
1328 IMemAllocator_Release(stream
->allocator
);
1329 stream
->allocator
= allocator
;
1334 static HRESULT WINAPI
ddraw_meminput_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
1336 TRACE("iface %p, props %p.\n", iface
, props
);
1340 static HRESULT WINAPI
ddraw_meminput_Receive(IMemInputPin
*iface
, IMediaSample
*sample
)
1342 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1343 BITMAPINFOHEADER
*bitmap_info
;
1344 REFERENCE_TIME start_time
= 0;
1345 REFERENCE_TIME end_time
= 0;
1346 STREAM_TIME start_stream_time
;
1347 STREAM_TIME end_stream_time
;
1348 IMediaStreamFilter
*filter
;
1349 STREAM_TIME current_time
;
1350 BYTE
*top_down_pointer
;
1351 int top_down_stride
;
1357 TRACE("stream %p, sample %p.\n", stream
, sample
);
1359 hr
= IMediaSample_GetPointer(sample
, &pointer
);
1363 IMediaSample_GetTime(sample
, &start_time
, &end_time
);
1365 EnterCriticalSection(&stream
->cs
);
1367 if (stream
->state
== State_Stopped
)
1369 LeaveCriticalSection(&stream
->cs
);
1372 if (stream
->flushing
)
1374 LeaveCriticalSection(&stream
->cs
);
1378 bitmap_info
= &((VIDEOINFOHEADER
*)stream
->mt
.pbFormat
)->bmiHeader
;
1380 stride
= ((bitmap_info
->biWidth
* bitmap_info
->biBitCount
+ 31) & ~31) / 8;
1381 top_down
= (bitmap_info
->biHeight
< 0);
1383 top_down_stride
= top_down
? stride
: -stride
;
1384 top_down_pointer
= top_down
? pointer
: pointer
+ stride
* (bitmap_info
->biHeight
- 1);
1386 start_stream_time
= start_time
+ stream
->segment_start
;
1387 end_stream_time
= end_time
+ stream
->segment_start
;
1389 filter
= stream
->filter
;
1391 LeaveCriticalSection(&stream
->cs
);
1392 if (S_OK
== IMediaStreamFilter_GetCurrentStreamTime(filter
, ¤t_time
)
1393 && start_time
>= current_time
+ 10000)
1394 IMediaStreamFilter_WaitUntil(filter
, start_time
);
1395 EnterCriticalSection(&stream
->cs
);
1399 if (stream
->state
== State_Stopped
)
1401 LeaveCriticalSection(&stream
->cs
);
1404 if (stream
->flushing
)
1406 LeaveCriticalSection(&stream
->cs
);
1409 if (!list_empty(&stream
->update_queue
))
1411 struct ddraw_sample
*sample
= LIST_ENTRY(list_head(&stream
->update_queue
), struct ddraw_sample
, entry
);
1413 sample
->update_hr
= process_update(sample
, top_down_stride
, top_down_pointer
,
1414 start_stream_time
, end_stream_time
);
1416 if (sample
->continuous_update
&& SUCCEEDED(sample
->update_hr
))
1418 list_remove(&sample
->entry
);
1419 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1423 remove_queued_update(sample
);
1425 LeaveCriticalSection(&stream
->cs
);
1429 SleepConditionVariableCS(&stream
->update_queued_cv
, &stream
->cs
, INFINITE
);
1433 static HRESULT WINAPI
ddraw_meminput_ReceiveMultiple(IMemInputPin
*iface
,
1434 IMediaSample
**samples
, LONG count
, LONG
*processed
)
1436 FIXME("iface %p, samples %p, count %lu, processed %p, stub!\n", iface
, samples
, count
, processed
);
1440 static HRESULT WINAPI
ddraw_meminput_ReceiveCanBlock(IMemInputPin
*iface
)
1442 TRACE("iface %p.\n", iface
);
1446 static const IMemInputPinVtbl ddraw_meminput_vtbl
=
1448 ddraw_meminput_QueryInterface
,
1449 ddraw_meminput_AddRef
,
1450 ddraw_meminput_Release
,
1451 ddraw_meminput_GetAllocator
,
1452 ddraw_meminput_NotifyAllocator
,
1453 ddraw_meminput_GetAllocatorRequirements
,
1454 ddraw_meminput_Receive
,
1455 ddraw_meminput_ReceiveMultiple
,
1456 ddraw_meminput_ReceiveCanBlock
,
1459 HRESULT
ddraw_stream_create(IUnknown
*outer
, void **out
)
1461 struct ddraw_stream
*object
;
1464 return CLASS_E_NOAGGREGATION
;
1466 if (!(object
= calloc(1, sizeof(*object
))))
1467 return E_OUTOFMEMORY
;
1469 object
->IAMMediaStream_iface
.lpVtbl
= &ddraw_IAMMediaStream_vtbl
;
1470 object
->IDirectDrawMediaStream_iface
.lpVtbl
= &ddraw_IDirectDrawMediaStream_Vtbl
;
1471 object
->IMemInputPin_iface
.lpVtbl
= &ddraw_meminput_vtbl
;
1472 object
->IPin_iface
.lpVtbl
= &ddraw_sink_vtbl
;
1475 object
->format
.width
= 100;
1476 object
->format
.height
= 100;
1478 InitializeCriticalSection(&object
->cs
);
1479 InitializeConditionVariable(&object
->update_queued_cv
);
1480 list_init(&object
->update_queue
);
1482 TRACE("Created ddraw stream %p.\n", object
);
1484 *out
= &object
->IAMMediaStream_iface
;
1489 static inline struct ddraw_sample
*impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample
*iface
)
1491 return CONTAINING_RECORD(iface
, struct ddraw_sample
, IDirectDrawStreamSample_iface
);
1494 /*** IUnknown methods ***/
1495 static HRESULT WINAPI
ddraw_sample_QueryInterface(IDirectDrawStreamSample
*iface
,
1496 REFIID riid
, void **ret_iface
)
1498 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(riid
), ret_iface
);
1500 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1501 IsEqualGUID(riid
, &IID_IStreamSample
) ||
1502 IsEqualGUID(riid
, &IID_IDirectDrawStreamSample
))
1504 IDirectDrawStreamSample_AddRef(iface
);
1511 ERR("(%p)->(%s,%p),not found\n", iface
, debugstr_guid(riid
), ret_iface
);
1512 return E_NOINTERFACE
;
1515 static ULONG WINAPI
ddraw_sample_AddRef(IDirectDrawStreamSample
*iface
)
1517 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1518 ULONG ref
= InterlockedIncrement(&sample
->ref
);
1520 TRACE("(%p)->(): new ref = %lu\n", iface
, ref
);
1525 static ULONG WINAPI
ddraw_sample_Release(IDirectDrawStreamSample
*iface
)
1527 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1528 ULONG ref
= InterlockedDecrement(&sample
->ref
);
1530 TRACE("(%p)->(): new ref = %lu\n", iface
, ref
);
1534 EnterCriticalSection(&sample
->parent
->cs
);
1535 --sample
->parent
->sample_refs
;
1536 LeaveCriticalSection(&sample
->parent
->cs
);
1538 if (sample
->mmstream
)
1539 IMultiMediaStream_Release(sample
->mmstream
);
1540 IAMMediaStream_Release(&sample
->parent
->IAMMediaStream_iface
);
1542 if (sample
->surface
)
1543 IDirectDrawSurface_Release(sample
->surface
);
1550 /*** IStreamSample methods ***/
1551 static HRESULT WINAPI
ddraw_sample_GetMediaStream(IDirectDrawStreamSample
*iface
, IMediaStream
**media_stream
)
1553 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1555 TRACE("sample %p, media_stream %p.\n", sample
, media_stream
);
1560 IAMMediaStream_AddRef(&sample
->parent
->IAMMediaStream_iface
);
1561 *media_stream
= (IMediaStream
*)&sample
->parent
->IAMMediaStream_iface
;
1566 static HRESULT WINAPI
ddraw_sample_GetSampleTimes(IDirectDrawStreamSample
*iface
, STREAM_TIME
*start_time
,
1567 STREAM_TIME
*end_time
, STREAM_TIME
*current_time
)
1569 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1571 TRACE("sample %p, start_time %p, end_time %p, current_time %p.\n", sample
, start_time
, end_time
, current_time
);
1574 IMediaStreamFilter_GetCurrentStreamTime(sample
->parent
->filter
, current_time
);
1577 *start_time
= sample
->start_time
;
1579 *end_time
= sample
->end_time
;
1584 static HRESULT WINAPI
ddraw_sample_SetSampleTimes(IDirectDrawStreamSample
*iface
, const STREAM_TIME
*start_time
,
1585 const STREAM_TIME
*end_time
)
1587 FIXME("(%p)->(%p,%p): stub\n", iface
, start_time
, end_time
);
1592 static HRESULT WINAPI
ddraw_sample_Update(IDirectDrawStreamSample
*iface
,
1593 DWORD flags
, HANDLE event
, PAPCFUNC apc_func
, DWORD apc_data
)
1595 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1597 TRACE("sample %p, flags %#lx, event %p, apc_func %p, apc_data %#lx.\n",
1598 sample
, flags
, event
, apc_func
, apc_data
);
1600 if (event
&& apc_func
)
1601 return E_INVALIDARG
;
1605 FIXME("APC support is not implemented!\n");
1609 EnterCriticalSection(&sample
->parent
->cs
);
1611 if (sample
->parent
->state
!= State_Running
)
1613 LeaveCriticalSection(&sample
->parent
->cs
);
1614 return MS_E_NOTRUNNING
;
1616 if (!sample
->parent
->peer
|| sample
->parent
->eos
)
1618 sample
->update_hr
= MS_S_ENDOFSTREAM
;
1619 LeaveCriticalSection(&sample
->parent
->cs
);
1620 return MS_S_ENDOFSTREAM
;
1624 LeaveCriticalSection(&sample
->parent
->cs
);
1628 sample
->continuous_update
= (flags
& SSUPDATE_ASYNC
) && (flags
& SSUPDATE_CONTINUOUS
);
1630 sample
->update_hr
= MS_S_NOUPDATE
;
1631 sample
->busy
= TRUE
;
1632 sample
->external_event
= event
;
1633 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1634 WakeConditionVariable(&sample
->parent
->update_queued_cv
);
1636 if ((flags
& SSUPDATE_ASYNC
) || event
)
1638 LeaveCriticalSection(&sample
->parent
->cs
);
1639 return MS_S_PENDING
;
1642 while (sample
->busy
)
1643 SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, INFINITE
);
1645 LeaveCriticalSection(&sample
->parent
->cs
);
1647 return sample
->update_hr
;
1650 static HRESULT WINAPI
ddraw_sample_CompletionStatus(IDirectDrawStreamSample
*iface
, DWORD flags
, DWORD milliseconds
)
1652 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1655 TRACE("sample %p, flags %#lx, milliseconds %lu.\n", sample
, flags
, milliseconds
);
1657 EnterCriticalSection(&sample
->parent
->cs
);
1661 if (flags
& (COMPSTAT_NOUPDATEOK
| COMPSTAT_ABORT
))
1663 remove_queued_update(sample
);
1665 else if (flags
& COMPSTAT_WAIT
)
1667 DWORD start_time
= GetTickCount();
1669 sample
->continuous_update
= FALSE
;
1670 while (sample
->busy
&& elapsed
< milliseconds
)
1672 DWORD sleep_time
= milliseconds
- elapsed
;
1673 if (!SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, sleep_time
))
1675 elapsed
= GetTickCount() - start_time
;
1680 hr
= sample
->busy
? MS_S_PENDING
: sample
->update_hr
;
1682 LeaveCriticalSection(&sample
->parent
->cs
);
1687 /*** IDirectDrawStreamSample methods ***/
1688 static HRESULT WINAPI
ddraw_sample_GetSurface(IDirectDrawStreamSample
*iface
, IDirectDrawSurface
**ddraw_surface
,
1691 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1693 TRACE("(%p)->(%p,%p)\n", iface
, ddraw_surface
, rect
);
1697 *ddraw_surface
= sample
->surface
;
1699 IDirectDrawSurface_AddRef(*ddraw_surface
);
1703 *rect
= sample
->rect
;
1708 static HRESULT WINAPI
ddraw_sample_SetRect(IDirectDrawStreamSample
*iface
, const RECT
*rect
)
1710 FIXME("(%p)->(%p): stub\n", iface
, rect
);
1715 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl
=
1717 /*** IUnknown methods ***/
1718 ddraw_sample_QueryInterface
,
1719 ddraw_sample_AddRef
,
1720 ddraw_sample_Release
,
1721 /*** IStreamSample methods ***/
1722 ddraw_sample_GetMediaStream
,
1723 ddraw_sample_GetSampleTimes
,
1724 ddraw_sample_SetSampleTimes
,
1725 ddraw_sample_Update
,
1726 ddraw_sample_CompletionStatus
,
1727 /*** IDirectDrawStreamSample methods ***/
1728 ddraw_sample_GetSurface
,
1729 ddraw_sample_SetRect
1732 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
1733 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
)
1735 struct ddraw_sample
*object
;
1739 TRACE("(%p)\n", ddraw_stream_sample
);
1741 if (!(object
= calloc(1, sizeof(*object
))))
1742 return E_OUTOFMEMORY
;
1744 object
->IDirectDrawStreamSample_iface
.lpVtbl
= &DirectDrawStreamSample_Vtbl
;
1746 object
->parent
= parent
;
1747 object
->mmstream
= parent
->parent
;
1748 InitializeConditionVariable(&object
->update_cv
);
1749 IAMMediaStream_AddRef(&parent
->IAMMediaStream_iface
);
1750 if (object
->mmstream
)
1751 IMultiMediaStream_AddRef(object
->mmstream
);
1752 ++parent
->sample_refs
;
1756 object
->surface
= surface
;
1757 IDirectDrawSurface_AddRef(surface
);
1763 hr
= IDirectDrawMediaStream_GetDirectDraw(&parent
->IDirectDrawMediaStream_iface
, &ddraw
);
1766 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1770 desc
.dwSize
= sizeof(desc
);
1771 desc
.dwFlags
= DDSD_CAPS
|DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
;
1772 desc
.dwHeight
= parent
->format
.height
;
1773 desc
.dwWidth
= parent
->format
.width
;
1774 if (parent
->format
.flags
& DDSD_PIXELFORMAT
)
1776 desc
.ddpfPixelFormat
= parent
->format
.pf
;
1780 desc
.ddpfPixelFormat
.dwSize
= sizeof(desc
.ddpfPixelFormat
);
1781 desc
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
1782 desc
.ddpfPixelFormat
.dwRGBBitCount
= 32;
1783 desc
.ddpfPixelFormat
.dwRBitMask
= 0xff0000;
1784 desc
.ddpfPixelFormat
.dwGBitMask
= 0x00ff00;
1785 desc
.ddpfPixelFormat
.dwBBitMask
= 0x0000ff;
1786 desc
.ddpfPixelFormat
.dwRGBAlphaBitMask
= 0;
1788 desc
.ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
|DDSCAPS_OFFSCREENPLAIN
;
1789 desc
.lpSurface
= NULL
;
1791 hr
= IDirectDraw_CreateSurface(ddraw
, &desc
, &object
->surface
, NULL
);
1792 IDirectDraw_Release(ddraw
);
1795 ERR("failed to create surface, 0x%08lx\n", hr
);
1796 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1801 desc
.dwSize
= sizeof(desc
);
1802 hr
= IDirectDrawSurface_GetSurfaceDesc(object
->surface
, &desc
);
1805 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1811 object
->rect
= *rect
;
1812 desc
.dwWidth
= rect
->right
- rect
->left
;
1813 desc
.dwHeight
= rect
->bottom
- rect
->top
;
1817 SetRect(&object
->rect
, 0, 0, desc
.dwWidth
, desc
.dwHeight
);
1820 hr
= IDirectDrawMediaStream_SetFormat(&parent
->IDirectDrawMediaStream_iface
, &desc
, NULL
);
1823 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1827 *ddraw_stream_sample
= &object
->IDirectDrawStreamSample_iface
;