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
;
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
.u1
.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
.u1
.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
.u1
.dwRGBBitCount
!= connection_pf
->u1
.dwRGBBitCount
)
159 if (stream
->format
.pf
.u1
.dwRGBBitCount
== 16 && stream
->format
.pf
.u3
.dwGBitMask
!= connection_pf
->u3
.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 = %u\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 %u.\n", stream
, ref
);
228 DeleteCriticalSection(&stream
->cs
);
230 IDirectDraw_Release(stream
->ddraw
);
231 HeapFree(GetProcessHeap(), 0, stream
);
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,%x) 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)->(%x,%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,%x,%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)->(%x) 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 %x, 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 && FAILED(hr
= IUnknown_QueryInterface(source_object
, &IID_IDirectDraw
, (void **)&stream
->ddraw
)))
329 FIXME("Stream object doesn't implement IDirectDraw interface, hr %#x.\n", hr
);
333 if (FAILED(hr
= DirectDrawCreate(NULL
, &stream
->ddraw
, NULL
)))
335 IDirectDraw_SetCooperativeLevel(stream
->ddraw
, NULL
, DDSCL_NORMAL
);
341 static HRESULT WINAPI
ddraw_IAMMediaStream_SetState(IAMMediaStream
*iface
, FILTER_STATE state
)
343 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
345 TRACE("stream %p, state %u.\n", stream
, state
);
347 EnterCriticalSection(&stream
->cs
);
349 if (state
== State_Stopped
)
350 WakeConditionVariable(&stream
->update_queued_cv
);
351 if (stream
->state
== State_Stopped
)
354 stream
->state
= state
;
356 LeaveCriticalSection(&stream
->cs
);
361 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream
*iface
, IAMMultiMediaStream
*mmstream
)
363 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
365 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
367 stream
->parent
= (IMultiMediaStream
*)mmstream
;
372 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilter(IAMMediaStream
*iface
, IMediaStreamFilter
*filter
)
374 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
376 TRACE("iface %p, filter %p.\n", iface
, filter
);
378 stream
->filter
= filter
;
383 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream
*iface
, IFilterGraph
*filtergraph
)
385 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
387 TRACE("stream %p, filtergraph %p.\n", stream
, filtergraph
);
389 stream
->graph
= filtergraph
;
394 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl
=
396 /*** IUnknown methods ***/
397 ddraw_IAMMediaStream_QueryInterface
,
398 ddraw_IAMMediaStream_AddRef
,
399 ddraw_IAMMediaStream_Release
,
400 /*** IMediaStream methods ***/
401 ddraw_IAMMediaStream_GetMultiMediaStream
,
402 ddraw_IAMMediaStream_GetInformation
,
403 ddraw_IAMMediaStream_SetSameFormat
,
404 ddraw_IAMMediaStream_AllocateSample
,
405 ddraw_IAMMediaStream_CreateSharedSample
,
406 ddraw_IAMMediaStream_SendEndOfStream
,
407 /*** IAMMediaStream methods ***/
408 ddraw_IAMMediaStream_Initialize
,
409 ddraw_IAMMediaStream_SetState
,
410 ddraw_IAMMediaStream_JoinAMMultiMediaStream
,
411 ddraw_IAMMediaStream_JoinFilter
,
412 ddraw_IAMMediaStream_JoinFilterGraph
415 static inline struct ddraw_stream
*impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream
*iface
)
417 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IDirectDrawMediaStream_iface
);
420 /*** IUnknown methods ***/
421 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream
*iface
,
422 REFIID riid
, void **ret_iface
)
424 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
425 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
426 return IAMMediaStream_QueryInterface(&This
->IAMMediaStream_iface
, riid
, ret_iface
);
429 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream
*iface
)
431 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
432 TRACE("(%p/%p)\n", iface
, This
);
433 return IAMMediaStream_AddRef(&This
->IAMMediaStream_iface
);
436 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream
*iface
)
438 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
439 TRACE("(%p/%p)\n", iface
, This
);
440 return IAMMediaStream_Release(&This
->IAMMediaStream_iface
);
443 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream
*iface
,
444 IMultiMediaStream
**mmstream
)
446 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
447 return IAMMediaStream_GetMultiMediaStream(&stream
->IAMMediaStream_iface
, mmstream
);
450 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream
*iface
,
451 MSPID
*purpose_id
, STREAM_TYPE
*type
)
453 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
454 return IAMMediaStream_GetInformation(&stream
->IAMMediaStream_iface
, purpose_id
, type
);
457 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream
*iface
,
458 IMediaStream
*other
, DWORD flags
)
460 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
461 return IAMMediaStream_SetSameFormat(&stream
->IAMMediaStream_iface
, other
, flags
);
464 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream
*iface
,
465 DWORD flags
, IStreamSample
**sample
)
467 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
468 return IAMMediaStream_AllocateSample(&stream
->IAMMediaStream_iface
, flags
, sample
);
471 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream
*iface
,
472 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
474 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
475 return IAMMediaStream_CreateSharedSample(&stream
->IAMMediaStream_iface
, existing_sample
, flags
, sample
);
478 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream
*iface
, DWORD flags
)
480 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
481 return IAMMediaStream_SendEndOfStream(&stream
->IAMMediaStream_iface
, flags
);
484 /*** IDirectDrawMediaStream methods ***/
485 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream
*iface
,
486 DDSURFACEDESC
*current_format
, IDirectDrawPalette
**palette
,
487 DDSURFACEDESC
*desired_format
, DWORD
*flags
)
489 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
491 TRACE("stream %p, current_format %p, palette %p, desired_format %p, flags %p.\n", stream
, current_format
, palette
,
492 desired_format
, flags
);
494 EnterCriticalSection(&stream
->cs
);
498 LeaveCriticalSection(&stream
->cs
);
499 return MS_E_NOSTREAM
;
504 current_format
->dwFlags
= stream
->format
.flags
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_CAPS
;
505 current_format
->dwWidth
= stream
->format
.width
;
506 current_format
->dwHeight
= stream
->format
.height
;
507 current_format
->ddpfPixelFormat
= stream
->format
.pf
;
508 current_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
516 desired_format
->dwFlags
= DDSD_WIDTH
| DDSD_HEIGHT
;
517 desired_format
->dwWidth
= stream
->format
.width
;
518 desired_format
->dwHeight
= stream
->format
.height
;
519 desired_format
->ddpfPixelFormat
= stream
->format
.pf
;
520 desired_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
526 LeaveCriticalSection(&stream
->cs
);
531 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream
*iface
,
532 const DDSURFACEDESC
*format
, IDirectDrawPalette
*palette
)
534 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
535 AM_MEDIA_TYPE old_media_type
;
536 struct format old_format
;
540 TRACE("stream %p, format %p, palette %p.\n", stream
, format
, palette
);
543 FIXME("Setting palette is not yet supported.\n");
548 if (format
->dwSize
!= sizeof(DDSURFACEDESC
))
551 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
553 if (format
->ddpfPixelFormat
.dwSize
!= sizeof(DDPIXELFORMAT
))
554 return DDERR_INVALIDSURFACETYPE
;
556 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
558 if (!format
->ddpfPixelFormat
.u1
.dwRGBBitCount
)
563 if (format
->ddpfPixelFormat
.dwFlags
& (DDPF_YUV
| DDPF_PALETTEINDEXED1
|
564 DDPF_PALETTEINDEXED2
| DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXEDTO8
))
565 return DDERR_INVALIDSURFACETYPE
;
567 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
))
568 return DDERR_INVALIDSURFACETYPE
;
570 switch (format
->ddpfPixelFormat
.u1
.dwRGBBitCount
)
573 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
))
574 return DDERR_INVALIDSURFACETYPE
;
577 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
578 return DDERR_INVALIDSURFACETYPE
;
579 if ((format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0x7c00 ||
580 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x03e0 ||
581 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x001f) &&
582 (format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0xf800 ||
583 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x07e0 ||
584 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x001f))
585 return DDERR_INVALIDSURFACETYPE
;
589 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
590 return DDERR_INVALIDSURFACETYPE
;
591 if (format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0xff0000 ||
592 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x00ff00 ||
593 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x0000ff)
594 return DDERR_INVALIDSURFACETYPE
;
597 return DDERR_INVALIDSURFACETYPE
;
602 EnterCriticalSection(&stream
->cs
);
604 old_format
= stream
->format
;
605 stream
->format
.flags
= format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
);
606 if (format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
))
608 stream
->format
.width
= format
->dwWidth
;
609 stream
->format
.height
= format
->dwHeight
;
611 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
612 stream
->format
.pf
= format
->ddpfPixelFormat
;
614 if (stream
->peer
&& !is_format_compatible(stream
, old_format
.width
, old_format
.height
, &old_format
.pf
))
616 hr
= CopyMediaType(&old_media_type
, &stream
->mt
);
619 stream
->format
= old_format
;
620 LeaveCriticalSection(&stream
->cs
);
623 old_peer
= stream
->peer
;
624 IPin_AddRef(old_peer
);
626 IFilterGraph_Disconnect(stream
->graph
, stream
->peer
);
627 IFilterGraph_Disconnect(stream
->graph
, &stream
->IPin_iface
);
628 hr
= IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, NULL
);
631 stream
->format
= old_format
;
632 IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, &old_media_type
);
633 IPin_Release(old_peer
);
634 FreeMediaType(&old_media_type
);
635 LeaveCriticalSection(&stream
->cs
);
636 return DDERR_INVALIDSURFACETYPE
;
639 IPin_Release(old_peer
);
640 FreeMediaType(&old_media_type
);
643 LeaveCriticalSection(&stream
->cs
);
648 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream
*iface
,
651 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
653 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
664 IDirectDraw_AddRef(stream
->ddraw
);
665 *ddraw
= stream
->ddraw
;
670 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream
*iface
,
673 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
675 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
677 EnterCriticalSection(&stream
->cs
);
679 if (stream
->sample_refs
)
681 HRESULT hr
= (stream
->ddraw
== ddraw
) ? S_OK
: MS_E_SAMPLEALLOC
;
682 LeaveCriticalSection(&stream
->cs
);
687 IDirectDraw_Release(stream
->ddraw
);
691 IDirectDraw_AddRef(ddraw
);
692 stream
->ddraw
= ddraw
;
695 stream
->ddraw
= NULL
;
697 LeaveCriticalSection(&stream
->cs
);
702 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream
*iface
,
703 IDirectDrawSurface
*surface
, const RECT
*rect
, DWORD flags
,
704 IDirectDrawStreamSample
**sample
)
706 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
709 TRACE("stream %p, surface %p, rect %s, flags %#x, sample %p.\n",
710 stream
, surface
, wine_dbgstr_rect(rect
), flags
, sample
);
712 if (!surface
&& rect
)
715 EnterCriticalSection(&stream
->cs
);
716 hr
= ddrawstreamsample_create(stream
, surface
, rect
, sample
);
717 LeaveCriticalSection(&stream
->cs
);
722 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream
*iface
,
723 STREAM_TIME
*frame_time
)
725 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
727 TRACE("stream %p, frame_time %p.\n", stream
, frame_time
);
732 EnterCriticalSection(&stream
->cs
);
736 LeaveCriticalSection(&stream
->cs
);
737 return MS_E_NOSTREAM
;
740 *frame_time
= ((VIDEOINFO
*)stream
->mt
.pbFormat
)->AvgTimePerFrame
;
742 LeaveCriticalSection(&stream
->cs
);
747 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl
=
749 /*** IUnknown methods ***/
750 ddraw_IDirectDrawMediaStream_QueryInterface
,
751 ddraw_IDirectDrawMediaStream_AddRef
,
752 ddraw_IDirectDrawMediaStream_Release
,
753 /*** IMediaStream methods ***/
754 ddraw_IDirectDrawMediaStream_GetMultiMediaStream
,
755 ddraw_IDirectDrawMediaStream_GetInformation
,
756 ddraw_IDirectDrawMediaStream_SetSameFormat
,
757 ddraw_IDirectDrawMediaStream_AllocateSample
,
758 ddraw_IDirectDrawMediaStream_CreateSharedSample
,
759 ddraw_IDirectDrawMediaStream_SendEndOfStream
,
760 /*** IDirectDrawMediaStream methods ***/
761 ddraw_IDirectDrawMediaStream_GetFormat
,
762 ddraw_IDirectDrawMediaStream_SetFormat
,
763 ddraw_IDirectDrawMediaStream_GetDirectDraw
,
764 ddraw_IDirectDrawMediaStream_SetDirectDraw
,
765 ddraw_IDirectDrawMediaStream_CreateSample
,
766 ddraw_IDirectDrawMediaStream_GetTimePerFrame
769 struct enum_media_types
771 IEnumMediaTypes IEnumMediaTypes_iface
;
776 static const IEnumMediaTypesVtbl enum_media_types_vtbl
;
778 static struct enum_media_types
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
780 return CONTAINING_RECORD(iface
, struct enum_media_types
, IEnumMediaTypes_iface
);
783 static HRESULT WINAPI
enum_media_types_QueryInterface(IEnumMediaTypes
*iface
, REFIID iid
, void **out
)
785 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
787 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMediaTypes
))
789 IEnumMediaTypes_AddRef(iface
);
794 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
796 return E_NOINTERFACE
;
799 static ULONG WINAPI
enum_media_types_AddRef(IEnumMediaTypes
*iface
)
801 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
802 ULONG refcount
= InterlockedIncrement(&enum_media_types
->refcount
);
803 TRACE("%p increasing refcount to %u.\n", enum_media_types
, refcount
);
807 static ULONG WINAPI
enum_media_types_Release(IEnumMediaTypes
*iface
)
809 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
810 ULONG refcount
= InterlockedDecrement(&enum_media_types
->refcount
);
811 TRACE("%p decreasing refcount to %u.\n", enum_media_types
, refcount
);
813 heap_free(enum_media_types
);
817 static HRESULT WINAPI
enum_media_types_Next(IEnumMediaTypes
*iface
, ULONG count
, AM_MEDIA_TYPE
**mts
, ULONG
*ret_count
)
819 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
821 TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface
, count
, mts
, ret_count
);
826 if (count
&& !enum_media_types
->index
)
828 mts
[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
829 memset(mts
[0], 0, sizeof(AM_MEDIA_TYPE
));
830 mts
[0]->majortype
= MEDIATYPE_Video
;
831 mts
[0]->subtype
= MEDIASUBTYPE_RGB8
;
832 mts
[0]->bFixedSizeSamples
= TRUE
;
833 mts
[0]->lSampleSize
= 10000;
834 ++enum_media_types
->index
;
836 return count
== 1 ? S_OK
: S_FALSE
;
840 return count
? S_FALSE
: S_OK
;
843 static HRESULT WINAPI
enum_media_types_Skip(IEnumMediaTypes
*iface
, ULONG count
)
845 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
847 TRACE("iface %p, count %u.\n", iface
, count
);
849 enum_media_types
->index
+= count
;
854 static HRESULT WINAPI
enum_media_types_Reset(IEnumMediaTypes
*iface
)
856 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
858 TRACE("iface %p.\n", iface
);
860 enum_media_types
->index
= 0;
864 static HRESULT WINAPI
enum_media_types_Clone(IEnumMediaTypes
*iface
, IEnumMediaTypes
**out
)
866 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
867 struct enum_media_types
*object
;
869 TRACE("iface %p, out %p.\n", iface
, out
);
871 if (!(object
= heap_alloc(sizeof(*object
))))
872 return E_OUTOFMEMORY
;
874 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
875 object
->refcount
= 1;
876 object
->index
= enum_media_types
->index
;
878 *out
= &object
->IEnumMediaTypes_iface
;
882 static const IEnumMediaTypesVtbl enum_media_types_vtbl
=
884 enum_media_types_QueryInterface
,
885 enum_media_types_AddRef
,
886 enum_media_types_Release
,
887 enum_media_types_Next
,
888 enum_media_types_Skip
,
889 enum_media_types_Reset
,
890 enum_media_types_Clone
,
893 static inline struct ddraw_stream
*impl_from_IPin(IPin
*iface
)
895 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IPin_iface
);
898 static HRESULT WINAPI
ddraw_sink_QueryInterface(IPin
*iface
, REFIID iid
, void **out
)
900 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
901 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
904 static ULONG WINAPI
ddraw_sink_AddRef(IPin
*iface
)
906 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
907 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
910 static ULONG WINAPI
ddraw_sink_Release(IPin
*iface
)
912 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
913 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
916 static HRESULT WINAPI
ddraw_sink_Connect(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
918 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface
, peer
, mt
);
922 static HRESULT WINAPI
ddraw_sink_ReceiveConnection(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
924 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
925 const VIDEOINFOHEADER
*video_info
;
929 DDPIXELFORMAT pf
= {sizeof(DDPIXELFORMAT
)};
931 TRACE("stream %p, peer %p, mt %p.\n", stream
, peer
, mt
);
933 EnterCriticalSection(&stream
->cs
);
937 LeaveCriticalSection(&stream
->cs
);
938 return VFW_E_ALREADY_CONNECTED
;
941 if (!IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
942 || !IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
944 LeaveCriticalSection(&stream
->cs
);
945 return VFW_E_TYPE_NOT_ACCEPTED
;
948 video_info
= (const VIDEOINFOHEADER
*)mt
->pbFormat
;
950 width
= video_info
->bmiHeader
.biWidth
;
951 height
= abs(video_info
->bmiHeader
.biHeight
);
952 pf
.dwFlags
= DDPF_RGB
;
953 if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
))
955 pf
.dwFlags
|= DDPF_PALETTEINDEXED8
;
956 pf
.u1
.dwRGBBitCount
= 8;
958 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB555
))
960 pf
.u1
.dwRGBBitCount
= 16;
961 pf
.u2
.dwRBitMask
= 0x7c00;
962 pf
.u3
.dwGBitMask
= 0x03e0;
963 pf
.u4
.dwBBitMask
= 0x001f;
965 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB565
))
967 pf
.u1
.dwRGBBitCount
= 16;
968 pf
.u2
.dwRBitMask
= 0xf800;
969 pf
.u3
.dwGBitMask
= 0x07e0;
970 pf
.u4
.dwBBitMask
= 0x001f;
972 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB24
))
974 pf
.u1
.dwRGBBitCount
= 24;
975 pf
.u2
.dwRBitMask
= 0xff0000;
976 pf
.u3
.dwGBitMask
= 0x00ff00;
977 pf
.u4
.dwBBitMask
= 0x0000ff;
979 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB32
))
981 pf
.u1
.dwRGBBitCount
= 32;
982 pf
.u2
.dwRBitMask
= 0xff0000;
983 pf
.u3
.dwGBitMask
= 0x00ff00;
984 pf
.u4
.dwBBitMask
= 0x0000ff;
988 LeaveCriticalSection(&stream
->cs
);
989 return VFW_E_TYPE_NOT_ACCEPTED
;
992 if (!is_format_compatible(stream
, width
, height
, &pf
))
994 LeaveCriticalSection(&stream
->cs
);
995 return VFW_E_TYPE_NOT_ACCEPTED
;
998 IPin_QueryDirection(peer
, &dir
);
999 if (dir
!= PINDIR_OUTPUT
)
1001 WARN("Rejecting connection from input pin.\n");
1002 LeaveCriticalSection(&stream
->cs
);
1003 return VFW_E_INVALID_DIRECTION
;
1006 CopyMediaType(&stream
->mt
, mt
);
1007 IPin_AddRef(stream
->peer
= peer
);
1009 stream
->format
.width
= width
;
1010 stream
->format
.height
= height
;
1011 if (!(stream
->format
.flags
& DDSD_PIXELFORMAT
))
1012 stream
->format
.pf
= pf
;
1014 LeaveCriticalSection(&stream
->cs
);
1019 static HRESULT WINAPI
ddraw_sink_Disconnect(IPin
*iface
)
1021 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1023 TRACE("stream %p.\n", stream
);
1025 EnterCriticalSection(&stream
->cs
);
1029 LeaveCriticalSection(&stream
->cs
);
1033 IPin_Release(stream
->peer
);
1034 stream
->peer
= NULL
;
1035 FreeMediaType(&stream
->mt
);
1036 memset(&stream
->mt
, 0, sizeof(AM_MEDIA_TYPE
));
1038 LeaveCriticalSection(&stream
->cs
);
1043 static HRESULT WINAPI
ddraw_sink_ConnectedTo(IPin
*iface
, IPin
**peer
)
1045 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1048 TRACE("stream %p, peer %p.\n", stream
, peer
);
1050 EnterCriticalSection(&stream
->cs
);
1054 IPin_AddRef(*peer
= stream
->peer
);
1060 hr
= VFW_E_NOT_CONNECTED
;
1063 LeaveCriticalSection(&stream
->cs
);
1068 static HRESULT WINAPI
ddraw_sink_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mt
)
1070 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1073 TRACE("stream %p, mt %p.\n", stream
, mt
);
1075 EnterCriticalSection(&stream
->cs
);
1079 CopyMediaType(mt
, &stream
->mt
);
1084 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
1085 hr
= VFW_E_NOT_CONNECTED
;
1088 LeaveCriticalSection(&stream
->cs
);
1093 static HRESULT WINAPI
ddraw_sink_QueryPinInfo(IPin
*iface
, PIN_INFO
*info
)
1095 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1097 TRACE("stream %p, info %p.\n", stream
, info
);
1099 IBaseFilter_AddRef(info
->pFilter
= (IBaseFilter
*)stream
->filter
);
1100 info
->dir
= PINDIR_INPUT
;
1101 wcscpy(info
->achName
, sink_id
);
1106 static HRESULT WINAPI
ddraw_sink_QueryDirection(IPin
*iface
, PIN_DIRECTION
*dir
)
1108 TRACE("iface %p, dir %p.\n", iface
, dir
);
1109 *dir
= PINDIR_INPUT
;
1113 static HRESULT WINAPI
ddraw_sink_QueryId(IPin
*iface
, WCHAR
**id
)
1115 TRACE("iface %p, id %p.\n", iface
, id
);
1117 if (!(*id
= CoTaskMemAlloc(sizeof(sink_id
))))
1118 return E_OUTOFMEMORY
;
1120 wcscpy(*id
, sink_id
);
1125 static HRESULT WINAPI
ddraw_sink_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*mt
)
1127 TRACE("iface %p, mt %p.\n", iface
, mt
);
1129 if (IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
1130 && IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
)
1131 && IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
1134 return VFW_E_TYPE_NOT_ACCEPTED
;
1137 static HRESULT WINAPI
ddraw_sink_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**enum_media_types
)
1139 struct enum_media_types
*object
;
1141 TRACE("iface %p, enum_media_types %p.\n", iface
, enum_media_types
);
1143 if (!enum_media_types
)
1146 if (!(object
= heap_alloc(sizeof(*object
))))
1147 return E_OUTOFMEMORY
;
1149 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
1150 object
->refcount
= 1;
1153 *enum_media_types
= &object
->IEnumMediaTypes_iface
;
1157 static HRESULT WINAPI
ddraw_sink_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*count
)
1159 TRACE("iface %p, pins %p, count %p.\n", iface
, pins
, count
);
1163 static HRESULT WINAPI
ddraw_sink_EndOfStream(IPin
*iface
)
1165 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1167 TRACE("stream %p.\n", stream
);
1169 EnterCriticalSection(&stream
->cs
);
1171 if (stream
->eos
|| stream
->flushing
)
1173 LeaveCriticalSection(&stream
->cs
);
1179 flush_update_queue(stream
, MS_S_ENDOFSTREAM
);
1181 LeaveCriticalSection(&stream
->cs
);
1183 /* Calling IMediaStreamFilter::EndOfStream() inside the critical section
1184 * would invert the locking order, so we must leave it first to avoid
1185 * the streaming thread deadlocking on the filter's critical section. */
1186 IMediaStreamFilter_EndOfStream(stream
->filter
);
1191 static HRESULT WINAPI
ddraw_sink_BeginFlush(IPin
*iface
)
1193 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1196 TRACE("stream %p.\n", stream
);
1198 EnterCriticalSection(&stream
->cs
);
1200 cancel_eos
= stream
->eos
;
1202 stream
->flushing
= TRUE
;
1203 stream
->eos
= FALSE
;
1204 WakeConditionVariable(&stream
->update_queued_cv
);
1206 LeaveCriticalSection(&stream
->cs
);
1208 /* Calling IMediaStreamFilter::Flush() inside the critical section would
1209 * invert the locking order, so we must leave it first to avoid the
1210 * application thread deadlocking on the filter's critical section. */
1211 IMediaStreamFilter_Flush(stream
->filter
, cancel_eos
);
1216 static HRESULT WINAPI
ddraw_sink_EndFlush(IPin
*iface
)
1218 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1220 TRACE("stream %p.\n", stream
);
1222 EnterCriticalSection(&stream
->cs
);
1224 stream
->flushing
= FALSE
;
1226 LeaveCriticalSection(&stream
->cs
);
1231 static HRESULT WINAPI
ddraw_sink_NewSegment(IPin
*iface
, REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
1233 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1235 TRACE("stream %p, start %s, stop %s, rate %0.16e\n",
1236 stream
, wine_dbgstr_longlong(start
), wine_dbgstr_longlong(stop
), rate
);
1238 EnterCriticalSection(&stream
->cs
);
1240 stream
->segment_start
= start
;
1242 LeaveCriticalSection(&stream
->cs
);
1247 static const IPinVtbl ddraw_sink_vtbl
=
1249 ddraw_sink_QueryInterface
,
1253 ddraw_sink_ReceiveConnection
,
1254 ddraw_sink_Disconnect
,
1255 ddraw_sink_ConnectedTo
,
1256 ddraw_sink_ConnectionMediaType
,
1257 ddraw_sink_QueryPinInfo
,
1258 ddraw_sink_QueryDirection
,
1260 ddraw_sink_QueryAccept
,
1261 ddraw_sink_EnumMediaTypes
,
1262 ddraw_sink_QueryInternalConnections
,
1263 ddraw_sink_EndOfStream
,
1264 ddraw_sink_BeginFlush
,
1265 ddraw_sink_EndFlush
,
1266 ddraw_sink_NewSegment
,
1269 static inline struct ddraw_stream
*impl_from_IMemInputPin(IMemInputPin
*iface
)
1271 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IMemInputPin_iface
);
1274 static HRESULT WINAPI
ddraw_meminput_QueryInterface(IMemInputPin
*iface
, REFIID iid
, void **out
)
1276 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1277 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
1280 static ULONG WINAPI
ddraw_meminput_AddRef(IMemInputPin
*iface
)
1282 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1283 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
1286 static ULONG WINAPI
ddraw_meminput_Release(IMemInputPin
*iface
)
1288 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1289 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
1292 static HRESULT WINAPI
ddraw_meminput_GetAllocator(IMemInputPin
*iface
, IMemAllocator
**allocator
)
1294 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1296 TRACE("stream %p, allocator %p.\n", stream
, allocator
);
1298 if (stream
->allocator
)
1300 IMemAllocator_AddRef(*allocator
= stream
->allocator
);
1305 return VFW_E_NO_ALLOCATOR
;
1308 static HRESULT WINAPI
ddraw_meminput_NotifyAllocator(IMemInputPin
*iface
, IMemAllocator
*allocator
, BOOL readonly
)
1310 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1312 TRACE("stream %p, allocator %p, readonly %d.\n", stream
, allocator
, readonly
);
1318 IMemAllocator_AddRef(allocator
);
1319 if (stream
->allocator
)
1320 IMemAllocator_Release(stream
->allocator
);
1321 stream
->allocator
= allocator
;
1326 static HRESULT WINAPI
ddraw_meminput_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
1328 TRACE("iface %p, props %p.\n", iface
, props
);
1332 static HRESULT WINAPI
ddraw_meminput_Receive(IMemInputPin
*iface
, IMediaSample
*sample
)
1334 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1335 BITMAPINFOHEADER
*bitmap_info
;
1336 REFERENCE_TIME start_time
= 0;
1337 REFERENCE_TIME end_time
= 0;
1338 STREAM_TIME start_stream_time
;
1339 STREAM_TIME end_stream_time
;
1340 IMediaStreamFilter
*filter
;
1341 STREAM_TIME current_time
;
1342 BYTE
*top_down_pointer
;
1343 int top_down_stride
;
1349 TRACE("stream %p, sample %p.\n", stream
, sample
);
1351 hr
= IMediaSample_GetPointer(sample
, &pointer
);
1355 IMediaSample_GetTime(sample
, &start_time
, &end_time
);
1357 EnterCriticalSection(&stream
->cs
);
1359 if (stream
->state
== State_Stopped
)
1361 LeaveCriticalSection(&stream
->cs
);
1364 if (stream
->flushing
)
1366 LeaveCriticalSection(&stream
->cs
);
1370 bitmap_info
= &((VIDEOINFOHEADER
*)stream
->mt
.pbFormat
)->bmiHeader
;
1372 stride
= ((bitmap_info
->biWidth
* bitmap_info
->biBitCount
+ 31) & ~31) / 8;
1373 top_down
= (bitmap_info
->biHeight
< 0);
1375 top_down_stride
= top_down
? stride
: -stride
;
1376 top_down_pointer
= top_down
? pointer
: pointer
+ stride
* (bitmap_info
->biHeight
- 1);
1378 start_stream_time
= start_time
+ stream
->segment_start
;
1379 end_stream_time
= end_time
+ stream
->segment_start
;
1381 filter
= stream
->filter
;
1383 LeaveCriticalSection(&stream
->cs
);
1384 if (S_OK
== IMediaStreamFilter_GetCurrentStreamTime(filter
, ¤t_time
)
1385 && start_time
>= current_time
+ 10000)
1386 IMediaStreamFilter_WaitUntil(filter
, start_time
);
1387 EnterCriticalSection(&stream
->cs
);
1391 if (stream
->state
== State_Stopped
)
1393 LeaveCriticalSection(&stream
->cs
);
1396 if (stream
->flushing
)
1398 LeaveCriticalSection(&stream
->cs
);
1401 if (!list_empty(&stream
->update_queue
))
1403 struct ddraw_sample
*sample
= LIST_ENTRY(list_head(&stream
->update_queue
), struct ddraw_sample
, entry
);
1405 sample
->update_hr
= process_update(sample
, top_down_stride
, top_down_pointer
,
1406 start_stream_time
, end_stream_time
);
1408 if (sample
->continuous_update
&& SUCCEEDED(sample
->update_hr
))
1410 list_remove(&sample
->entry
);
1411 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1415 remove_queued_update(sample
);
1417 LeaveCriticalSection(&stream
->cs
);
1421 SleepConditionVariableCS(&stream
->update_queued_cv
, &stream
->cs
, INFINITE
);
1425 static HRESULT WINAPI
ddraw_meminput_ReceiveMultiple(IMemInputPin
*iface
,
1426 IMediaSample
**samples
, LONG count
, LONG
*processed
)
1428 FIXME("iface %p, samples %p, count %u, processed %p, stub!\n", iface
, samples
, count
, processed
);
1432 static HRESULT WINAPI
ddraw_meminput_ReceiveCanBlock(IMemInputPin
*iface
)
1434 TRACE("iface %p.\n", iface
);
1438 static const IMemInputPinVtbl ddraw_meminput_vtbl
=
1440 ddraw_meminput_QueryInterface
,
1441 ddraw_meminput_AddRef
,
1442 ddraw_meminput_Release
,
1443 ddraw_meminput_GetAllocator
,
1444 ddraw_meminput_NotifyAllocator
,
1445 ddraw_meminput_GetAllocatorRequirements
,
1446 ddraw_meminput_Receive
,
1447 ddraw_meminput_ReceiveMultiple
,
1448 ddraw_meminput_ReceiveCanBlock
,
1451 HRESULT
ddraw_stream_create(IUnknown
*outer
, void **out
)
1453 struct ddraw_stream
*object
;
1456 return CLASS_E_NOAGGREGATION
;
1458 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1460 return E_OUTOFMEMORY
;
1462 object
->IAMMediaStream_iface
.lpVtbl
= &ddraw_IAMMediaStream_vtbl
;
1463 object
->IDirectDrawMediaStream_iface
.lpVtbl
= &ddraw_IDirectDrawMediaStream_Vtbl
;
1464 object
->IMemInputPin_iface
.lpVtbl
= &ddraw_meminput_vtbl
;
1465 object
->IPin_iface
.lpVtbl
= &ddraw_sink_vtbl
;
1468 object
->format
.width
= 100;
1469 object
->format
.height
= 100;
1471 InitializeCriticalSection(&object
->cs
);
1472 InitializeConditionVariable(&object
->update_queued_cv
);
1473 list_init(&object
->update_queue
);
1475 TRACE("Created ddraw stream %p.\n", object
);
1477 *out
= &object
->IAMMediaStream_iface
;
1482 static inline struct ddraw_sample
*impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample
*iface
)
1484 return CONTAINING_RECORD(iface
, struct ddraw_sample
, IDirectDrawStreamSample_iface
);
1487 /*** IUnknown methods ***/
1488 static HRESULT WINAPI
ddraw_sample_QueryInterface(IDirectDrawStreamSample
*iface
,
1489 REFIID riid
, void **ret_iface
)
1491 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(riid
), ret_iface
);
1493 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1494 IsEqualGUID(riid
, &IID_IStreamSample
) ||
1495 IsEqualGUID(riid
, &IID_IDirectDrawStreamSample
))
1497 IDirectDrawStreamSample_AddRef(iface
);
1504 ERR("(%p)->(%s,%p),not found\n", iface
, debugstr_guid(riid
), ret_iface
);
1505 return E_NOINTERFACE
;
1508 static ULONG WINAPI
ddraw_sample_AddRef(IDirectDrawStreamSample
*iface
)
1510 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1511 ULONG ref
= InterlockedIncrement(&sample
->ref
);
1513 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
1518 static ULONG WINAPI
ddraw_sample_Release(IDirectDrawStreamSample
*iface
)
1520 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1521 ULONG ref
= InterlockedDecrement(&sample
->ref
);
1523 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
1527 EnterCriticalSection(&sample
->parent
->cs
);
1528 --sample
->parent
->sample_refs
;
1529 LeaveCriticalSection(&sample
->parent
->cs
);
1531 if (sample
->mmstream
)
1532 IMultiMediaStream_Release(sample
->mmstream
);
1533 IAMMediaStream_Release(&sample
->parent
->IAMMediaStream_iface
);
1535 if (sample
->surface
)
1536 IDirectDrawSurface_Release(sample
->surface
);
1537 HeapFree(GetProcessHeap(), 0, sample
);
1543 /*** IStreamSample methods ***/
1544 static HRESULT WINAPI
ddraw_sample_GetMediaStream(IDirectDrawStreamSample
*iface
, IMediaStream
**media_stream
)
1546 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1548 TRACE("sample %p, media_stream %p.\n", sample
, media_stream
);
1553 IAMMediaStream_AddRef(&sample
->parent
->IAMMediaStream_iface
);
1554 *media_stream
= (IMediaStream
*)&sample
->parent
->IAMMediaStream_iface
;
1559 static HRESULT WINAPI
ddraw_sample_GetSampleTimes(IDirectDrawStreamSample
*iface
, STREAM_TIME
*start_time
,
1560 STREAM_TIME
*end_time
, STREAM_TIME
*current_time
)
1562 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1564 TRACE("sample %p, start_time %p, end_time %p, current_time %p.\n", sample
, start_time
, end_time
, current_time
);
1567 IMediaStreamFilter_GetCurrentStreamTime(sample
->parent
->filter
, current_time
);
1570 *start_time
= sample
->start_time
;
1572 *end_time
= sample
->end_time
;
1577 static HRESULT WINAPI
ddraw_sample_SetSampleTimes(IDirectDrawStreamSample
*iface
, const STREAM_TIME
*start_time
,
1578 const STREAM_TIME
*end_time
)
1580 FIXME("(%p)->(%p,%p): stub\n", iface
, start_time
, end_time
);
1585 static HRESULT WINAPI
ddraw_sample_Update(IDirectDrawStreamSample
*iface
,
1586 DWORD flags
, HANDLE event
, PAPCFUNC apc_func
, DWORD apc_data
)
1588 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1590 TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n",
1591 sample
, flags
, event
, apc_func
, apc_data
);
1593 if (event
&& apc_func
)
1594 return E_INVALIDARG
;
1598 FIXME("APC support is not implemented!\n");
1602 EnterCriticalSection(&sample
->parent
->cs
);
1604 if (sample
->parent
->state
!= State_Running
)
1606 LeaveCriticalSection(&sample
->parent
->cs
);
1607 return MS_E_NOTRUNNING
;
1609 if (!sample
->parent
->peer
|| sample
->parent
->eos
)
1611 sample
->update_hr
= MS_S_ENDOFSTREAM
;
1612 LeaveCriticalSection(&sample
->parent
->cs
);
1613 return MS_S_ENDOFSTREAM
;
1617 LeaveCriticalSection(&sample
->parent
->cs
);
1621 sample
->continuous_update
= (flags
& SSUPDATE_ASYNC
) && (flags
& SSUPDATE_CONTINUOUS
);
1623 sample
->update_hr
= MS_S_NOUPDATE
;
1624 sample
->busy
= TRUE
;
1625 sample
->external_event
= event
;
1626 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1627 WakeConditionVariable(&sample
->parent
->update_queued_cv
);
1629 if ((flags
& SSUPDATE_ASYNC
) || event
)
1631 LeaveCriticalSection(&sample
->parent
->cs
);
1632 return MS_S_PENDING
;
1635 while (sample
->busy
)
1636 SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, INFINITE
);
1638 LeaveCriticalSection(&sample
->parent
->cs
);
1640 return sample
->update_hr
;
1643 static HRESULT WINAPI
ddraw_sample_CompletionStatus(IDirectDrawStreamSample
*iface
, DWORD flags
, DWORD milliseconds
)
1645 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1648 TRACE("sample %p, flags %#x, milliseconds %u.\n", sample
, flags
, milliseconds
);
1650 EnterCriticalSection(&sample
->parent
->cs
);
1654 if (flags
& (COMPSTAT_NOUPDATEOK
| COMPSTAT_ABORT
))
1656 remove_queued_update(sample
);
1658 else if (flags
& COMPSTAT_WAIT
)
1660 DWORD start_time
= GetTickCount();
1662 sample
->continuous_update
= FALSE
;
1663 while (sample
->busy
&& elapsed
< milliseconds
)
1665 DWORD sleep_time
= milliseconds
- elapsed
;
1666 if (!SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, sleep_time
))
1668 elapsed
= GetTickCount() - start_time
;
1673 hr
= sample
->busy
? MS_S_PENDING
: sample
->update_hr
;
1675 LeaveCriticalSection(&sample
->parent
->cs
);
1680 /*** IDirectDrawStreamSample methods ***/
1681 static HRESULT WINAPI
ddraw_sample_GetSurface(IDirectDrawStreamSample
*iface
, IDirectDrawSurface
**ddraw_surface
,
1684 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1686 TRACE("(%p)->(%p,%p)\n", iface
, ddraw_surface
, rect
);
1690 *ddraw_surface
= sample
->surface
;
1692 IDirectDrawSurface_AddRef(*ddraw_surface
);
1696 *rect
= sample
->rect
;
1701 static HRESULT WINAPI
ddraw_sample_SetRect(IDirectDrawStreamSample
*iface
, const RECT
*rect
)
1703 FIXME("(%p)->(%p): stub\n", iface
, rect
);
1708 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl
=
1710 /*** IUnknown methods ***/
1711 ddraw_sample_QueryInterface
,
1712 ddraw_sample_AddRef
,
1713 ddraw_sample_Release
,
1714 /*** IStreamSample methods ***/
1715 ddraw_sample_GetMediaStream
,
1716 ddraw_sample_GetSampleTimes
,
1717 ddraw_sample_SetSampleTimes
,
1718 ddraw_sample_Update
,
1719 ddraw_sample_CompletionStatus
,
1720 /*** IDirectDrawStreamSample methods ***/
1721 ddraw_sample_GetSurface
,
1722 ddraw_sample_SetRect
1725 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
1726 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
)
1728 struct ddraw_sample
*object
;
1732 TRACE("(%p)\n", ddraw_stream_sample
);
1734 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1736 return E_OUTOFMEMORY
;
1738 object
->IDirectDrawStreamSample_iface
.lpVtbl
= &DirectDrawStreamSample_Vtbl
;
1740 object
->parent
= parent
;
1741 object
->mmstream
= parent
->parent
;
1742 InitializeConditionVariable(&object
->update_cv
);
1743 IAMMediaStream_AddRef(&parent
->IAMMediaStream_iface
);
1744 if (object
->mmstream
)
1745 IMultiMediaStream_AddRef(object
->mmstream
);
1746 ++parent
->sample_refs
;
1750 object
->surface
= surface
;
1751 IDirectDrawSurface_AddRef(surface
);
1757 hr
= IDirectDrawMediaStream_GetDirectDraw(&parent
->IDirectDrawMediaStream_iface
, &ddraw
);
1760 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1764 desc
.dwSize
= sizeof(desc
);
1765 desc
.dwFlags
= DDSD_CAPS
|DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
;
1766 desc
.dwHeight
= parent
->format
.height
;
1767 desc
.dwWidth
= parent
->format
.width
;
1768 if (parent
->format
.flags
& DDSD_PIXELFORMAT
)
1770 desc
.ddpfPixelFormat
= parent
->format
.pf
;
1774 desc
.ddpfPixelFormat
.dwSize
= sizeof(desc
.ddpfPixelFormat
);
1775 desc
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
1776 desc
.ddpfPixelFormat
.u1
.dwRGBBitCount
= 32;
1777 desc
.ddpfPixelFormat
.u2
.dwRBitMask
= 0xff0000;
1778 desc
.ddpfPixelFormat
.u3
.dwGBitMask
= 0x00ff00;
1779 desc
.ddpfPixelFormat
.u4
.dwBBitMask
= 0x0000ff;
1780 desc
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
= 0;
1782 desc
.ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
|DDSCAPS_OFFSCREENPLAIN
;
1783 desc
.lpSurface
= NULL
;
1785 hr
= IDirectDraw_CreateSurface(ddraw
, &desc
, &object
->surface
, NULL
);
1786 IDirectDraw_Release(ddraw
);
1789 ERR("failed to create surface, 0x%08x\n", hr
);
1790 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1795 desc
.dwSize
= sizeof(desc
);
1796 hr
= IDirectDrawSurface_GetSurfaceDesc(object
->surface
, &desc
);
1799 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1805 object
->rect
= *rect
;
1806 desc
.dwWidth
= rect
->right
- rect
->left
;
1807 desc
.dwHeight
= rect
->bottom
- rect
->top
;
1811 SetRect(&object
->rect
, 0, 0, desc
.dwWidth
, desc
.dwHeight
);
1814 hr
= IDirectDrawMediaStream_SetFormat(&parent
->IDirectDrawMediaStream_iface
, &desc
, NULL
);
1817 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1821 *ddraw_stream_sample
= &object
->IDirectDrawStreamSample_iface
;