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
;
86 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
87 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
);
89 static void remove_queued_update(struct ddraw_sample
*sample
)
92 list_remove(&sample
->entry
);
93 WakeConditionVariable(&sample
->update_cv
);
96 static void flush_update_queue(struct ddraw_stream
*stream
, HRESULT update_hr
)
99 while ((entry
= list_head(&stream
->update_queue
)))
101 struct ddraw_sample
*sample
= LIST_ENTRY(entry
, struct ddraw_sample
, entry
);
102 sample
->update_hr
= update_hr
;
103 remove_queued_update(sample
);
107 static HRESULT
process_update(struct ddraw_sample
*sample
, int stride
, BYTE
*pointer
,
108 STREAM_TIME start_time
, STREAM_TIME end_time
)
117 desc
.dwSize
= sizeof(desc
);
118 hr
= IDirectDrawSurface_Lock(sample
->surface
, &sample
->rect
, &desc
, DDLOCK_WAIT
, NULL
);
122 row_size
= (sample
->rect
.right
- sample
->rect
.left
) * desc
.ddpfPixelFormat
.u1
.dwRGBBitCount
/ 8;
124 dst_row
= desc
.lpSurface
;
125 for (row
= sample
->rect
.top
; row
< sample
->rect
.bottom
; ++row
)
127 memcpy(dst_row
, src_row
, row_size
);
129 dst_row
+= desc
.u1
.lPitch
;
132 hr
= IDirectDrawSurface_Unlock(sample
->surface
, desc
.lpSurface
);
136 sample
->start_time
= start_time
;
137 sample
->end_time
= end_time
;
142 static BOOL
is_format_compatible(struct ddraw_stream
*stream
,
143 DWORD width
, DWORD height
, const DDPIXELFORMAT
*connection_pf
)
145 if (stream
->format
.flags
& DDSD_HEIGHT
)
147 if (stream
->format
.width
!= width
|| stream
->format
.height
!= height
)
150 if (stream
->format
.flags
& DDSD_PIXELFORMAT
)
152 if (stream
->format
.pf
.dwFlags
& DDPF_FOURCC
)
154 if (stream
->format
.pf
.u1
.dwRGBBitCount
!= connection_pf
->u1
.dwRGBBitCount
)
156 if (stream
->format
.pf
.u1
.dwRGBBitCount
== 16 && stream
->format
.pf
.u3
.dwGBitMask
!= connection_pf
->u3
.dwGBitMask
)
162 static inline struct ddraw_stream
*impl_from_IAMMediaStream(IAMMediaStream
*iface
)
164 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IAMMediaStream_iface
);
167 /*** IUnknown methods ***/
168 static HRESULT WINAPI
ddraw_IAMMediaStream_QueryInterface(IAMMediaStream
*iface
,
169 REFIID riid
, void **ret_iface
)
171 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
173 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
175 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
176 IsEqualGUID(riid
, &IID_IMediaStream
) ||
177 IsEqualGUID(riid
, &IID_IAMMediaStream
))
179 IAMMediaStream_AddRef(iface
);
183 else if (IsEqualGUID(riid
, &IID_IDirectDrawMediaStream
))
185 IAMMediaStream_AddRef(iface
);
186 *ret_iface
= &This
->IDirectDrawMediaStream_iface
;
189 else if (IsEqualGUID(riid
, &IID_IPin
))
191 IAMMediaStream_AddRef(iface
);
192 *ret_iface
= &This
->IPin_iface
;
195 else if (IsEqualGUID(riid
, &IID_IMemInputPin
))
197 IAMMediaStream_AddRef(iface
);
198 *ret_iface
= &This
->IMemInputPin_iface
;
202 ERR("(%p)->(%s,%p),not found\n", This
, debugstr_guid(riid
), ret_iface
);
203 return E_NOINTERFACE
;
206 static ULONG WINAPI
ddraw_IAMMediaStream_AddRef(IAMMediaStream
*iface
)
208 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
209 ULONG ref
= InterlockedIncrement(&This
->ref
);
211 TRACE("(%p/%p)->(): new ref = %u\n", iface
, This
, ref
);
216 static ULONG WINAPI
ddraw_IAMMediaStream_Release(IAMMediaStream
*iface
)
218 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
219 ULONG ref
= InterlockedDecrement(&stream
->ref
);
221 TRACE("%p decreasing refcount to %u.\n", stream
, ref
);
225 DeleteCriticalSection(&stream
->cs
);
227 IDirectDraw_Release(stream
->ddraw
);
228 HeapFree(GetProcessHeap(), 0, stream
);
234 /*** IMediaStream methods ***/
235 static HRESULT WINAPI
ddraw_IAMMediaStream_GetMultiMediaStream(IAMMediaStream
*iface
,
236 IMultiMediaStream
**mmstream
)
238 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
240 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
246 IMultiMediaStream_AddRef(stream
->parent
);
247 *mmstream
= stream
->parent
;
251 static HRESULT WINAPI
ddraw_IAMMediaStream_GetInformation(IAMMediaStream
*iface
,
252 MSPID
*purpose_id
, STREAM_TYPE
*type
)
254 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
256 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, purpose_id
, type
);
259 *purpose_id
= This
->purpose_id
;
261 *type
= This
->stream_type
;
266 static HRESULT WINAPI
ddraw_IAMMediaStream_SetSameFormat(IAMMediaStream
*iface
,
267 IMediaStream
*pStreamThatHasDesiredFormat
, DWORD flags
)
269 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
271 FIXME("(%p/%p)->(%p,%x) stub!\n", This
, iface
, pStreamThatHasDesiredFormat
, flags
);
276 static HRESULT WINAPI
ddraw_IAMMediaStream_AllocateSample(IAMMediaStream
*iface
,
277 DWORD flags
, IStreamSample
**sample
)
279 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
281 FIXME("(%p/%p)->(%x,%p) stub!\n", This
, iface
, flags
, sample
);
286 static HRESULT WINAPI
ddraw_IAMMediaStream_CreateSharedSample(IAMMediaStream
*iface
,
287 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
289 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
291 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This
, iface
, existing_sample
, flags
, sample
);
296 static HRESULT WINAPI
ddraw_IAMMediaStream_SendEndOfStream(IAMMediaStream
*iface
, DWORD flags
)
298 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
300 FIXME("(%p/%p)->(%x) stub!\n", This
, iface
, flags
);
305 /*** IAMMediaStream methods ***/
306 static HRESULT WINAPI
ddraw_IAMMediaStream_Initialize(IAMMediaStream
*iface
, IUnknown
*source_object
, DWORD flags
,
307 REFMSPID purpose_id
, const STREAM_TYPE stream_type
)
309 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
312 TRACE("stream %p, source_object %p, flags %x, purpose_id %s, stream_type %u.\n", stream
, source_object
, flags
,
313 debugstr_guid(purpose_id
), stream_type
);
318 if (flags
& AMMSF_CREATEPEER
)
319 FIXME("AMMSF_CREATEPEER is not yet supported.\n");
321 stream
->purpose_id
= *purpose_id
;
322 stream
->stream_type
= stream_type
;
325 && FAILED(hr
= IUnknown_QueryInterface(source_object
, &IID_IDirectDraw
, (void **)&stream
->ddraw
)))
326 FIXME("Stream object doesn't implement IDirectDraw interface, hr %#x.\n", hr
);
330 if (FAILED(hr
= DirectDrawCreate(NULL
, &stream
->ddraw
, NULL
)))
332 IDirectDraw_SetCooperativeLevel(stream
->ddraw
, NULL
, DDSCL_NORMAL
);
338 static HRESULT WINAPI
ddraw_IAMMediaStream_SetState(IAMMediaStream
*iface
, FILTER_STATE state
)
340 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
342 TRACE("stream %p, state %u.\n", stream
, state
);
344 EnterCriticalSection(&stream
->cs
);
346 if (state
== State_Stopped
)
347 WakeConditionVariable(&stream
->update_queued_cv
);
348 if (stream
->state
== State_Stopped
)
351 stream
->state
= state
;
353 LeaveCriticalSection(&stream
->cs
);
358 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream
*iface
, IAMMultiMediaStream
*mmstream
)
360 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
362 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
364 stream
->parent
= (IMultiMediaStream
*)mmstream
;
369 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilter(IAMMediaStream
*iface
, IMediaStreamFilter
*filter
)
371 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
373 TRACE("iface %p, filter %p.\n", iface
, filter
);
375 stream
->filter
= filter
;
380 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream
*iface
, IFilterGraph
*filtergraph
)
382 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
384 TRACE("stream %p, filtergraph %p.\n", stream
, filtergraph
);
386 stream
->graph
= filtergraph
;
391 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl
=
393 /*** IUnknown methods ***/
394 ddraw_IAMMediaStream_QueryInterface
,
395 ddraw_IAMMediaStream_AddRef
,
396 ddraw_IAMMediaStream_Release
,
397 /*** IMediaStream methods ***/
398 ddraw_IAMMediaStream_GetMultiMediaStream
,
399 ddraw_IAMMediaStream_GetInformation
,
400 ddraw_IAMMediaStream_SetSameFormat
,
401 ddraw_IAMMediaStream_AllocateSample
,
402 ddraw_IAMMediaStream_CreateSharedSample
,
403 ddraw_IAMMediaStream_SendEndOfStream
,
404 /*** IAMMediaStream methods ***/
405 ddraw_IAMMediaStream_Initialize
,
406 ddraw_IAMMediaStream_SetState
,
407 ddraw_IAMMediaStream_JoinAMMultiMediaStream
,
408 ddraw_IAMMediaStream_JoinFilter
,
409 ddraw_IAMMediaStream_JoinFilterGraph
412 static inline struct ddraw_stream
*impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream
*iface
)
414 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IDirectDrawMediaStream_iface
);
417 /*** IUnknown methods ***/
418 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream
*iface
,
419 REFIID riid
, void **ret_iface
)
421 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
422 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
423 return IAMMediaStream_QueryInterface(&This
->IAMMediaStream_iface
, riid
, ret_iface
);
426 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream
*iface
)
428 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
429 TRACE("(%p/%p)\n", iface
, This
);
430 return IAMMediaStream_AddRef(&This
->IAMMediaStream_iface
);
433 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream
*iface
)
435 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
436 TRACE("(%p/%p)\n", iface
, This
);
437 return IAMMediaStream_Release(&This
->IAMMediaStream_iface
);
440 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream
*iface
,
441 IMultiMediaStream
**mmstream
)
443 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
444 return IAMMediaStream_GetMultiMediaStream(&stream
->IAMMediaStream_iface
, mmstream
);
447 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream
*iface
,
448 MSPID
*purpose_id
, STREAM_TYPE
*type
)
450 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
451 return IAMMediaStream_GetInformation(&stream
->IAMMediaStream_iface
, purpose_id
, type
);
454 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream
*iface
,
455 IMediaStream
*other
, DWORD flags
)
457 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
458 return IAMMediaStream_SetSameFormat(&stream
->IAMMediaStream_iface
, other
, flags
);
461 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream
*iface
,
462 DWORD flags
, IStreamSample
**sample
)
464 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
465 return IAMMediaStream_AllocateSample(&stream
->IAMMediaStream_iface
, flags
, sample
);
468 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream
*iface
,
469 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
471 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
472 return IAMMediaStream_CreateSharedSample(&stream
->IAMMediaStream_iface
, existing_sample
, flags
, sample
);
475 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream
*iface
, DWORD flags
)
477 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
478 return IAMMediaStream_SendEndOfStream(&stream
->IAMMediaStream_iface
, flags
);
481 /*** IDirectDrawMediaStream methods ***/
482 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream
*iface
,
483 DDSURFACEDESC
*current_format
, IDirectDrawPalette
**palette
,
484 DDSURFACEDESC
*desired_format
, DWORD
*flags
)
486 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
488 TRACE("stream %p, current_format %p, palette %p, desired_format %p, flags %p.\n", stream
, current_format
, palette
,
489 desired_format
, flags
);
491 EnterCriticalSection(&stream
->cs
);
495 LeaveCriticalSection(&stream
->cs
);
496 return MS_E_NOSTREAM
;
501 current_format
->dwFlags
= stream
->format
.flags
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_CAPS
;
502 current_format
->dwWidth
= stream
->format
.width
;
503 current_format
->dwHeight
= stream
->format
.height
;
504 current_format
->ddpfPixelFormat
= stream
->format
.pf
;
505 current_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
513 desired_format
->dwFlags
= DDSD_WIDTH
| DDSD_HEIGHT
;
514 desired_format
->dwWidth
= stream
->format
.width
;
515 desired_format
->dwHeight
= stream
->format
.height
;
516 desired_format
->ddpfPixelFormat
= stream
->format
.pf
;
517 desired_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
523 LeaveCriticalSection(&stream
->cs
);
528 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream
*iface
,
529 const DDSURFACEDESC
*format
, IDirectDrawPalette
*palette
)
531 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
532 AM_MEDIA_TYPE old_media_type
;
533 struct format old_format
;
537 TRACE("stream %p, format %p, palette %p.\n", stream
, format
, palette
);
540 FIXME("Setting palette is not yet supported.\n");
545 if (format
->dwSize
!= sizeof(DDSURFACEDESC
))
548 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
550 if (format
->ddpfPixelFormat
.dwSize
!= sizeof(DDPIXELFORMAT
))
551 return DDERR_INVALIDSURFACETYPE
;
553 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
555 if (!format
->ddpfPixelFormat
.u1
.dwRGBBitCount
)
560 if (format
->ddpfPixelFormat
.dwFlags
& (DDPF_YUV
| DDPF_PALETTEINDEXED1
|
561 DDPF_PALETTEINDEXED2
| DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXEDTO8
))
562 return DDERR_INVALIDSURFACETYPE
;
564 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
))
565 return DDERR_INVALIDSURFACETYPE
;
567 switch (format
->ddpfPixelFormat
.u1
.dwRGBBitCount
)
570 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
))
571 return DDERR_INVALIDSURFACETYPE
;
574 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
575 return DDERR_INVALIDSURFACETYPE
;
576 if ((format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0x7c00 ||
577 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x03e0 ||
578 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x001f) &&
579 (format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0xf800 ||
580 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x07e0 ||
581 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x001f))
582 return DDERR_INVALIDSURFACETYPE
;
586 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
587 return DDERR_INVALIDSURFACETYPE
;
588 if (format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0xff0000 ||
589 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x00ff00 ||
590 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x0000ff)
591 return DDERR_INVALIDSURFACETYPE
;
594 return DDERR_INVALIDSURFACETYPE
;
599 EnterCriticalSection(&stream
->cs
);
601 old_format
= stream
->format
;
602 stream
->format
.flags
= format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
);
603 if (format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
))
605 stream
->format
.width
= format
->dwWidth
;
606 stream
->format
.height
= format
->dwHeight
;
608 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
609 stream
->format
.pf
= format
->ddpfPixelFormat
;
611 if (stream
->peer
&& !is_format_compatible(stream
, old_format
.width
, old_format
.height
, &old_format
.pf
))
613 hr
= CopyMediaType(&old_media_type
, &stream
->mt
);
616 stream
->format
= old_format
;
617 LeaveCriticalSection(&stream
->cs
);
620 old_peer
= stream
->peer
;
621 IPin_AddRef(old_peer
);
623 IFilterGraph_Disconnect(stream
->graph
, stream
->peer
);
624 IFilterGraph_Disconnect(stream
->graph
, &stream
->IPin_iface
);
625 hr
= IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, NULL
);
628 stream
->format
= old_format
;
629 IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, &old_media_type
);
630 IPin_Release(old_peer
);
631 FreeMediaType(&old_media_type
);
632 LeaveCriticalSection(&stream
->cs
);
633 return DDERR_INVALIDSURFACETYPE
;
636 IPin_Release(old_peer
);
637 FreeMediaType(&old_media_type
);
640 LeaveCriticalSection(&stream
->cs
);
645 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream
*iface
,
648 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
650 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
661 IDirectDraw_AddRef(stream
->ddraw
);
662 *ddraw
= stream
->ddraw
;
667 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream
*iface
,
670 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
672 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
674 EnterCriticalSection(&stream
->cs
);
676 if (stream
->sample_refs
)
678 HRESULT hr
= (stream
->ddraw
== ddraw
) ? S_OK
: MS_E_SAMPLEALLOC
;
679 LeaveCriticalSection(&stream
->cs
);
684 IDirectDraw_Release(stream
->ddraw
);
688 IDirectDraw_AddRef(ddraw
);
689 stream
->ddraw
= ddraw
;
692 stream
->ddraw
= NULL
;
694 LeaveCriticalSection(&stream
->cs
);
699 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream
*iface
,
700 IDirectDrawSurface
*surface
, const RECT
*rect
, DWORD flags
,
701 IDirectDrawStreamSample
**sample
)
703 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
706 TRACE("stream %p, surface %p, rect %s, flags %#x, sample %p.\n",
707 stream
, surface
, wine_dbgstr_rect(rect
), flags
, sample
);
709 if (!surface
&& rect
)
712 EnterCriticalSection(&stream
->cs
);
713 hr
= ddrawstreamsample_create(stream
, surface
, rect
, sample
);
714 LeaveCriticalSection(&stream
->cs
);
719 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream
*iface
,
720 STREAM_TIME
*frame_time
)
722 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
724 TRACE("stream %p, frame_time %p.\n", stream
, frame_time
);
729 EnterCriticalSection(&stream
->cs
);
733 LeaveCriticalSection(&stream
->cs
);
734 return MS_E_NOSTREAM
;
737 *frame_time
= ((VIDEOINFO
*)stream
->mt
.pbFormat
)->AvgTimePerFrame
;
739 LeaveCriticalSection(&stream
->cs
);
744 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl
=
746 /*** IUnknown methods ***/
747 ddraw_IDirectDrawMediaStream_QueryInterface
,
748 ddraw_IDirectDrawMediaStream_AddRef
,
749 ddraw_IDirectDrawMediaStream_Release
,
750 /*** IMediaStream methods ***/
751 ddraw_IDirectDrawMediaStream_GetMultiMediaStream
,
752 ddraw_IDirectDrawMediaStream_GetInformation
,
753 ddraw_IDirectDrawMediaStream_SetSameFormat
,
754 ddraw_IDirectDrawMediaStream_AllocateSample
,
755 ddraw_IDirectDrawMediaStream_CreateSharedSample
,
756 ddraw_IDirectDrawMediaStream_SendEndOfStream
,
757 /*** IDirectDrawMediaStream methods ***/
758 ddraw_IDirectDrawMediaStream_GetFormat
,
759 ddraw_IDirectDrawMediaStream_SetFormat
,
760 ddraw_IDirectDrawMediaStream_GetDirectDraw
,
761 ddraw_IDirectDrawMediaStream_SetDirectDraw
,
762 ddraw_IDirectDrawMediaStream_CreateSample
,
763 ddraw_IDirectDrawMediaStream_GetTimePerFrame
766 struct enum_media_types
768 IEnumMediaTypes IEnumMediaTypes_iface
;
773 static const IEnumMediaTypesVtbl enum_media_types_vtbl
;
775 static struct enum_media_types
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
777 return CONTAINING_RECORD(iface
, struct enum_media_types
, IEnumMediaTypes_iface
);
780 static HRESULT WINAPI
enum_media_types_QueryInterface(IEnumMediaTypes
*iface
, REFIID iid
, void **out
)
782 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
784 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMediaTypes
))
786 IEnumMediaTypes_AddRef(iface
);
791 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
793 return E_NOINTERFACE
;
796 static ULONG WINAPI
enum_media_types_AddRef(IEnumMediaTypes
*iface
)
798 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
799 ULONG refcount
= InterlockedIncrement(&enum_media_types
->refcount
);
800 TRACE("%p increasing refcount to %u.\n", enum_media_types
, refcount
);
804 static ULONG WINAPI
enum_media_types_Release(IEnumMediaTypes
*iface
)
806 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
807 ULONG refcount
= InterlockedDecrement(&enum_media_types
->refcount
);
808 TRACE("%p decreasing refcount to %u.\n", enum_media_types
, refcount
);
810 heap_free(enum_media_types
);
814 static HRESULT WINAPI
enum_media_types_Next(IEnumMediaTypes
*iface
, ULONG count
, AM_MEDIA_TYPE
**mts
, ULONG
*ret_count
)
816 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
818 TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface
, count
, mts
, ret_count
);
823 if (count
&& !enum_media_types
->index
)
825 mts
[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
826 memset(mts
[0], 0, sizeof(AM_MEDIA_TYPE
));
827 mts
[0]->majortype
= MEDIATYPE_Video
;
828 mts
[0]->subtype
= MEDIASUBTYPE_RGB8
;
829 mts
[0]->bFixedSizeSamples
= TRUE
;
830 mts
[0]->lSampleSize
= 10000;
831 ++enum_media_types
->index
;
833 return count
== 1 ? S_OK
: S_FALSE
;
837 return count
? S_FALSE
: S_OK
;
840 static HRESULT WINAPI
enum_media_types_Skip(IEnumMediaTypes
*iface
, ULONG count
)
842 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
844 TRACE("iface %p, count %u.\n", iface
, count
);
846 enum_media_types
->index
+= count
;
851 static HRESULT WINAPI
enum_media_types_Reset(IEnumMediaTypes
*iface
)
853 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
855 TRACE("iface %p.\n", iface
);
857 enum_media_types
->index
= 0;
861 static HRESULT WINAPI
enum_media_types_Clone(IEnumMediaTypes
*iface
, IEnumMediaTypes
**out
)
863 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
864 struct enum_media_types
*object
;
866 TRACE("iface %p, out %p.\n", iface
, out
);
868 if (!(object
= heap_alloc(sizeof(*object
))))
869 return E_OUTOFMEMORY
;
871 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
872 object
->refcount
= 1;
873 object
->index
= enum_media_types
->index
;
875 *out
= &object
->IEnumMediaTypes_iface
;
879 static const IEnumMediaTypesVtbl enum_media_types_vtbl
=
881 enum_media_types_QueryInterface
,
882 enum_media_types_AddRef
,
883 enum_media_types_Release
,
884 enum_media_types_Next
,
885 enum_media_types_Skip
,
886 enum_media_types_Reset
,
887 enum_media_types_Clone
,
890 static inline struct ddraw_stream
*impl_from_IPin(IPin
*iface
)
892 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IPin_iface
);
895 static HRESULT WINAPI
ddraw_sink_QueryInterface(IPin
*iface
, REFIID iid
, void **out
)
897 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
898 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
901 static ULONG WINAPI
ddraw_sink_AddRef(IPin
*iface
)
903 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
904 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
907 static ULONG WINAPI
ddraw_sink_Release(IPin
*iface
)
909 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
910 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
913 static HRESULT WINAPI
ddraw_sink_Connect(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
915 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface
, peer
, mt
);
919 static HRESULT WINAPI
ddraw_sink_ReceiveConnection(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
921 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
922 const VIDEOINFOHEADER
*video_info
;
926 DDPIXELFORMAT pf
= {sizeof(DDPIXELFORMAT
)};
928 TRACE("stream %p, peer %p, mt %p.\n", stream
, peer
, mt
);
930 EnterCriticalSection(&stream
->cs
);
934 LeaveCriticalSection(&stream
->cs
);
935 return VFW_E_ALREADY_CONNECTED
;
938 if (!IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
939 || !IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
941 LeaveCriticalSection(&stream
->cs
);
942 return VFW_E_TYPE_NOT_ACCEPTED
;
945 video_info
= (const VIDEOINFOHEADER
*)mt
->pbFormat
;
947 width
= video_info
->bmiHeader
.biWidth
;
948 height
= abs(video_info
->bmiHeader
.biHeight
);
949 pf
.dwFlags
= DDPF_RGB
;
950 if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
))
952 pf
.dwFlags
|= DDPF_PALETTEINDEXED8
;
953 pf
.u1
.dwRGBBitCount
= 8;
955 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB555
))
957 pf
.u1
.dwRGBBitCount
= 16;
958 pf
.u2
.dwRBitMask
= 0x7c00;
959 pf
.u3
.dwGBitMask
= 0x03e0;
960 pf
.u4
.dwBBitMask
= 0x001f;
962 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB565
))
964 pf
.u1
.dwRGBBitCount
= 16;
965 pf
.u2
.dwRBitMask
= 0xf800;
966 pf
.u3
.dwGBitMask
= 0x07e0;
967 pf
.u4
.dwBBitMask
= 0x001f;
969 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB24
))
971 pf
.u1
.dwRGBBitCount
= 24;
972 pf
.u2
.dwRBitMask
= 0xff0000;
973 pf
.u3
.dwGBitMask
= 0x00ff00;
974 pf
.u4
.dwBBitMask
= 0x0000ff;
976 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB32
))
978 pf
.u1
.dwRGBBitCount
= 32;
979 pf
.u2
.dwRBitMask
= 0xff0000;
980 pf
.u3
.dwGBitMask
= 0x00ff00;
981 pf
.u4
.dwBBitMask
= 0x0000ff;
985 LeaveCriticalSection(&stream
->cs
);
986 return VFW_E_TYPE_NOT_ACCEPTED
;
989 if (!is_format_compatible(stream
, width
, height
, &pf
))
991 LeaveCriticalSection(&stream
->cs
);
992 return VFW_E_TYPE_NOT_ACCEPTED
;
995 IPin_QueryDirection(peer
, &dir
);
996 if (dir
!= PINDIR_OUTPUT
)
998 WARN("Rejecting connection from input pin.\n");
999 LeaveCriticalSection(&stream
->cs
);
1000 return VFW_E_INVALID_DIRECTION
;
1003 CopyMediaType(&stream
->mt
, mt
);
1004 IPin_AddRef(stream
->peer
= peer
);
1006 stream
->format
.width
= width
;
1007 stream
->format
.height
= height
;
1008 if (!(stream
->format
.flags
& DDSD_PIXELFORMAT
))
1009 stream
->format
.pf
= pf
;
1011 LeaveCriticalSection(&stream
->cs
);
1016 static HRESULT WINAPI
ddraw_sink_Disconnect(IPin
*iface
)
1018 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1020 TRACE("stream %p.\n", stream
);
1022 EnterCriticalSection(&stream
->cs
);
1026 LeaveCriticalSection(&stream
->cs
);
1030 IPin_Release(stream
->peer
);
1031 stream
->peer
= NULL
;
1032 FreeMediaType(&stream
->mt
);
1033 memset(&stream
->mt
, 0, sizeof(AM_MEDIA_TYPE
));
1035 LeaveCriticalSection(&stream
->cs
);
1040 static HRESULT WINAPI
ddraw_sink_ConnectedTo(IPin
*iface
, IPin
**peer
)
1042 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1045 TRACE("stream %p, peer %p.\n", stream
, peer
);
1047 EnterCriticalSection(&stream
->cs
);
1051 IPin_AddRef(*peer
= stream
->peer
);
1057 hr
= VFW_E_NOT_CONNECTED
;
1060 LeaveCriticalSection(&stream
->cs
);
1065 static HRESULT WINAPI
ddraw_sink_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mt
)
1067 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1070 TRACE("stream %p, mt %p.\n", stream
, mt
);
1072 EnterCriticalSection(&stream
->cs
);
1076 CopyMediaType(mt
, &stream
->mt
);
1081 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
1082 hr
= VFW_E_NOT_CONNECTED
;
1085 LeaveCriticalSection(&stream
->cs
);
1090 static HRESULT WINAPI
ddraw_sink_QueryPinInfo(IPin
*iface
, PIN_INFO
*info
)
1092 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1094 TRACE("stream %p, info %p.\n", stream
, info
);
1096 IBaseFilter_AddRef(info
->pFilter
= (IBaseFilter
*)stream
->filter
);
1097 info
->dir
= PINDIR_INPUT
;
1098 wcscpy(info
->achName
, sink_id
);
1103 static HRESULT WINAPI
ddraw_sink_QueryDirection(IPin
*iface
, PIN_DIRECTION
*dir
)
1105 TRACE("iface %p, dir %p.\n", iface
, dir
);
1106 *dir
= PINDIR_INPUT
;
1110 static HRESULT WINAPI
ddraw_sink_QueryId(IPin
*iface
, WCHAR
**id
)
1112 TRACE("iface %p, id %p.\n", iface
, id
);
1114 if (!(*id
= CoTaskMemAlloc(sizeof(sink_id
))))
1115 return E_OUTOFMEMORY
;
1117 wcscpy(*id
, sink_id
);
1122 static HRESULT WINAPI
ddraw_sink_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*mt
)
1124 TRACE("iface %p, mt %p.\n", iface
, mt
);
1126 if (IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
1127 && IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
)
1128 && IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
1131 return VFW_E_TYPE_NOT_ACCEPTED
;
1134 static HRESULT WINAPI
ddraw_sink_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**enum_media_types
)
1136 struct enum_media_types
*object
;
1138 TRACE("iface %p, enum_media_types %p.\n", iface
, enum_media_types
);
1140 if (!enum_media_types
)
1143 if (!(object
= heap_alloc(sizeof(*object
))))
1144 return E_OUTOFMEMORY
;
1146 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
1147 object
->refcount
= 1;
1150 *enum_media_types
= &object
->IEnumMediaTypes_iface
;
1154 static HRESULT WINAPI
ddraw_sink_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*count
)
1156 TRACE("iface %p, pins %p, count %p.\n", iface
, pins
, count
);
1160 static HRESULT WINAPI
ddraw_sink_EndOfStream(IPin
*iface
)
1162 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1164 TRACE("stream %p.\n", stream
);
1166 EnterCriticalSection(&stream
->cs
);
1168 if (stream
->eos
|| stream
->flushing
)
1170 LeaveCriticalSection(&stream
->cs
);
1176 flush_update_queue(stream
, MS_S_ENDOFSTREAM
);
1178 LeaveCriticalSection(&stream
->cs
);
1183 static HRESULT WINAPI
ddraw_sink_BeginFlush(IPin
*iface
)
1185 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1187 TRACE("stream %p.\n", stream
);
1189 EnterCriticalSection(&stream
->cs
);
1191 stream
->flushing
= TRUE
;
1192 stream
->eos
= FALSE
;
1193 WakeConditionVariable(&stream
->update_queued_cv
);
1195 LeaveCriticalSection(&stream
->cs
);
1200 static HRESULT WINAPI
ddraw_sink_EndFlush(IPin
*iface
)
1202 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1204 TRACE("stream %p.\n", stream
);
1206 EnterCriticalSection(&stream
->cs
);
1208 stream
->flushing
= FALSE
;
1210 LeaveCriticalSection(&stream
->cs
);
1215 static HRESULT WINAPI
ddraw_sink_NewSegment(IPin
*iface
, REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
1217 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1219 TRACE("stream %p, start %s, stop %s, rate %0.16e\n",
1220 stream
, wine_dbgstr_longlong(start
), wine_dbgstr_longlong(stop
), rate
);
1222 EnterCriticalSection(&stream
->cs
);
1224 stream
->segment_start
= start
;
1226 LeaveCriticalSection(&stream
->cs
);
1231 static const IPinVtbl ddraw_sink_vtbl
=
1233 ddraw_sink_QueryInterface
,
1237 ddraw_sink_ReceiveConnection
,
1238 ddraw_sink_Disconnect
,
1239 ddraw_sink_ConnectedTo
,
1240 ddraw_sink_ConnectionMediaType
,
1241 ddraw_sink_QueryPinInfo
,
1242 ddraw_sink_QueryDirection
,
1244 ddraw_sink_QueryAccept
,
1245 ddraw_sink_EnumMediaTypes
,
1246 ddraw_sink_QueryInternalConnections
,
1247 ddraw_sink_EndOfStream
,
1248 ddraw_sink_BeginFlush
,
1249 ddraw_sink_EndFlush
,
1250 ddraw_sink_NewSegment
,
1253 static inline struct ddraw_stream
*impl_from_IMemInputPin(IMemInputPin
*iface
)
1255 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IMemInputPin_iface
);
1258 static HRESULT WINAPI
ddraw_meminput_QueryInterface(IMemInputPin
*iface
, REFIID iid
, void **out
)
1260 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1261 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
1264 static ULONG WINAPI
ddraw_meminput_AddRef(IMemInputPin
*iface
)
1266 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1267 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
1270 static ULONG WINAPI
ddraw_meminput_Release(IMemInputPin
*iface
)
1272 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1273 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
1276 static HRESULT WINAPI
ddraw_meminput_GetAllocator(IMemInputPin
*iface
, IMemAllocator
**allocator
)
1278 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1280 TRACE("stream %p, allocator %p.\n", stream
, allocator
);
1282 if (stream
->allocator
)
1284 IMemAllocator_AddRef(*allocator
= stream
->allocator
);
1289 return VFW_E_NO_ALLOCATOR
;
1292 static HRESULT WINAPI
ddraw_meminput_NotifyAllocator(IMemInputPin
*iface
, IMemAllocator
*allocator
, BOOL readonly
)
1294 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1296 TRACE("stream %p, allocator %p, readonly %d.\n", stream
, allocator
, readonly
);
1302 IMemAllocator_AddRef(allocator
);
1303 if (stream
->allocator
)
1304 IMemAllocator_Release(stream
->allocator
);
1305 stream
->allocator
= allocator
;
1310 static HRESULT WINAPI
ddraw_meminput_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
1312 TRACE("iface %p, props %p.\n", iface
, props
);
1316 static HRESULT WINAPI
ddraw_meminput_Receive(IMemInputPin
*iface
, IMediaSample
*sample
)
1318 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1319 BITMAPINFOHEADER
*bitmap_info
;
1320 REFERENCE_TIME start_time
= 0;
1321 REFERENCE_TIME end_time
= 0;
1322 STREAM_TIME start_stream_time
;
1323 STREAM_TIME end_stream_time
;
1324 IMediaStreamFilter
*filter
;
1325 STREAM_TIME current_time
;
1326 BYTE
*top_down_pointer
;
1327 int top_down_stride
;
1333 TRACE("stream %p, sample %p.\n", stream
, sample
);
1335 hr
= IMediaSample_GetPointer(sample
, &pointer
);
1339 IMediaSample_GetTime(sample
, &start_time
, &end_time
);
1341 EnterCriticalSection(&stream
->cs
);
1343 if (stream
->state
== State_Stopped
)
1345 LeaveCriticalSection(&stream
->cs
);
1348 if (stream
->flushing
)
1350 LeaveCriticalSection(&stream
->cs
);
1354 bitmap_info
= &((VIDEOINFOHEADER
*)stream
->mt
.pbFormat
)->bmiHeader
;
1356 stride
= ((bitmap_info
->biWidth
* bitmap_info
->biBitCount
+ 31) & ~31) / 8;
1357 top_down
= (bitmap_info
->biHeight
< 0);
1359 top_down_stride
= top_down
? stride
: -stride
;
1360 top_down_pointer
= top_down
? pointer
: pointer
+ stride
* (bitmap_info
->biHeight
- 1);
1362 start_stream_time
= start_time
+ stream
->segment_start
;
1363 end_stream_time
= end_time
+ stream
->segment_start
;
1365 filter
= stream
->filter
;
1367 LeaveCriticalSection(&stream
->cs
);
1368 if (S_OK
== IMediaStreamFilter_GetCurrentStreamTime(filter
, ¤t_time
)
1369 && start_time
>= current_time
+ 10000)
1370 IMediaStreamFilter_WaitUntil(filter
, start_time
);
1371 EnterCriticalSection(&stream
->cs
);
1375 if (stream
->state
== State_Stopped
)
1377 LeaveCriticalSection(&stream
->cs
);
1380 if (stream
->flushing
)
1382 LeaveCriticalSection(&stream
->cs
);
1385 if (!list_empty(&stream
->update_queue
))
1387 struct ddraw_sample
*sample
= LIST_ENTRY(list_head(&stream
->update_queue
), struct ddraw_sample
, entry
);
1389 sample
->update_hr
= process_update(sample
, top_down_stride
, top_down_pointer
,
1390 start_stream_time
, end_stream_time
);
1392 if (sample
->continuous_update
&& SUCCEEDED(sample
->update_hr
))
1394 list_remove(&sample
->entry
);
1395 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1399 remove_queued_update(sample
);
1401 LeaveCriticalSection(&stream
->cs
);
1405 SleepConditionVariableCS(&stream
->update_queued_cv
, &stream
->cs
, INFINITE
);
1409 static HRESULT WINAPI
ddraw_meminput_ReceiveMultiple(IMemInputPin
*iface
,
1410 IMediaSample
**samples
, LONG count
, LONG
*processed
)
1412 FIXME("iface %p, samples %p, count %u, processed %p, stub!\n", iface
, samples
, count
, processed
);
1416 static HRESULT WINAPI
ddraw_meminput_ReceiveCanBlock(IMemInputPin
*iface
)
1418 TRACE("iface %p.\n", iface
);
1422 static const IMemInputPinVtbl ddraw_meminput_vtbl
=
1424 ddraw_meminput_QueryInterface
,
1425 ddraw_meminput_AddRef
,
1426 ddraw_meminput_Release
,
1427 ddraw_meminput_GetAllocator
,
1428 ddraw_meminput_NotifyAllocator
,
1429 ddraw_meminput_GetAllocatorRequirements
,
1430 ddraw_meminput_Receive
,
1431 ddraw_meminput_ReceiveMultiple
,
1432 ddraw_meminput_ReceiveCanBlock
,
1435 HRESULT
ddraw_stream_create(IUnknown
*outer
, void **out
)
1437 struct ddraw_stream
*object
;
1440 return CLASS_E_NOAGGREGATION
;
1442 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1444 return E_OUTOFMEMORY
;
1446 object
->IAMMediaStream_iface
.lpVtbl
= &ddraw_IAMMediaStream_vtbl
;
1447 object
->IDirectDrawMediaStream_iface
.lpVtbl
= &ddraw_IDirectDrawMediaStream_Vtbl
;
1448 object
->IMemInputPin_iface
.lpVtbl
= &ddraw_meminput_vtbl
;
1449 object
->IPin_iface
.lpVtbl
= &ddraw_sink_vtbl
;
1452 object
->format
.width
= 100;
1453 object
->format
.height
= 100;
1455 InitializeCriticalSection(&object
->cs
);
1456 InitializeConditionVariable(&object
->update_queued_cv
);
1457 list_init(&object
->update_queue
);
1459 TRACE("Created ddraw stream %p.\n", object
);
1461 *out
= &object
->IAMMediaStream_iface
;
1466 static inline struct ddraw_sample
*impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample
*iface
)
1468 return CONTAINING_RECORD(iface
, struct ddraw_sample
, IDirectDrawStreamSample_iface
);
1471 /*** IUnknown methods ***/
1472 static HRESULT WINAPI
ddraw_sample_QueryInterface(IDirectDrawStreamSample
*iface
,
1473 REFIID riid
, void **ret_iface
)
1475 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(riid
), ret_iface
);
1477 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1478 IsEqualGUID(riid
, &IID_IStreamSample
) ||
1479 IsEqualGUID(riid
, &IID_IDirectDrawStreamSample
))
1481 IDirectDrawStreamSample_AddRef(iface
);
1488 ERR("(%p)->(%s,%p),not found\n", iface
, debugstr_guid(riid
), ret_iface
);
1489 return E_NOINTERFACE
;
1492 static ULONG WINAPI
ddraw_sample_AddRef(IDirectDrawStreamSample
*iface
)
1494 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1495 ULONG ref
= InterlockedIncrement(&sample
->ref
);
1497 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
1502 static ULONG WINAPI
ddraw_sample_Release(IDirectDrawStreamSample
*iface
)
1504 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1505 ULONG ref
= InterlockedDecrement(&sample
->ref
);
1507 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
1511 EnterCriticalSection(&sample
->parent
->cs
);
1512 --sample
->parent
->sample_refs
;
1513 LeaveCriticalSection(&sample
->parent
->cs
);
1515 if (sample
->mmstream
)
1516 IMultiMediaStream_Release(sample
->mmstream
);
1517 IAMMediaStream_Release(&sample
->parent
->IAMMediaStream_iface
);
1519 if (sample
->surface
)
1520 IDirectDrawSurface_Release(sample
->surface
);
1521 HeapFree(GetProcessHeap(), 0, sample
);
1527 /*** IStreamSample methods ***/
1528 static HRESULT WINAPI
ddraw_sample_GetMediaStream(IDirectDrawStreamSample
*iface
, IMediaStream
**media_stream
)
1530 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1532 TRACE("sample %p, media_stream %p.\n", sample
, media_stream
);
1537 IAMMediaStream_AddRef(&sample
->parent
->IAMMediaStream_iface
);
1538 *media_stream
= (IMediaStream
*)&sample
->parent
->IAMMediaStream_iface
;
1543 static HRESULT WINAPI
ddraw_sample_GetSampleTimes(IDirectDrawStreamSample
*iface
, STREAM_TIME
*start_time
,
1544 STREAM_TIME
*end_time
, STREAM_TIME
*current_time
)
1546 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1548 TRACE("sample %p, start_time %p, end_time %p, current_time %p.\n", sample
, start_time
, end_time
, current_time
);
1551 IMediaStreamFilter_GetCurrentStreamTime(sample
->parent
->filter
, current_time
);
1554 *start_time
= sample
->start_time
;
1556 *end_time
= sample
->end_time
;
1561 static HRESULT WINAPI
ddraw_sample_SetSampleTimes(IDirectDrawStreamSample
*iface
, const STREAM_TIME
*start_time
,
1562 const STREAM_TIME
*end_time
)
1564 FIXME("(%p)->(%p,%p): stub\n", iface
, start_time
, end_time
);
1569 static HRESULT WINAPI
ddraw_sample_Update(IDirectDrawStreamSample
*iface
,
1570 DWORD flags
, HANDLE event
, PAPCFUNC apc_func
, DWORD apc_data
)
1572 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1574 TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n",
1575 sample
, flags
, event
, apc_func
, apc_data
);
1577 if (event
&& apc_func
)
1578 return E_INVALIDARG
;
1582 FIXME("APC support is not implemented!\n");
1588 FIXME("Event parameter support is not implemented!\n");
1592 EnterCriticalSection(&sample
->parent
->cs
);
1594 if (sample
->parent
->state
!= State_Running
)
1596 LeaveCriticalSection(&sample
->parent
->cs
);
1597 return MS_E_NOTRUNNING
;
1599 if (!sample
->parent
->peer
|| sample
->parent
->eos
)
1601 sample
->update_hr
= MS_S_ENDOFSTREAM
;
1602 LeaveCriticalSection(&sample
->parent
->cs
);
1603 return MS_S_ENDOFSTREAM
;
1607 LeaveCriticalSection(&sample
->parent
->cs
);
1611 sample
->continuous_update
= (flags
& SSUPDATE_ASYNC
) && (flags
& SSUPDATE_CONTINUOUS
);
1613 sample
->update_hr
= MS_S_NOUPDATE
;
1614 sample
->busy
= TRUE
;
1615 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1616 WakeConditionVariable(&sample
->parent
->update_queued_cv
);
1618 if (flags
& SSUPDATE_ASYNC
)
1620 LeaveCriticalSection(&sample
->parent
->cs
);
1621 return MS_S_PENDING
;
1624 while (sample
->busy
)
1625 SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, INFINITE
);
1627 LeaveCriticalSection(&sample
->parent
->cs
);
1629 return sample
->update_hr
;
1632 static HRESULT WINAPI
ddraw_sample_CompletionStatus(IDirectDrawStreamSample
*iface
, DWORD flags
, DWORD milliseconds
)
1634 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1637 TRACE("sample %p, flags %#x, milliseconds %u.\n", sample
, flags
, milliseconds
);
1639 EnterCriticalSection(&sample
->parent
->cs
);
1643 if (flags
& (COMPSTAT_NOUPDATEOK
| COMPSTAT_ABORT
))
1645 remove_queued_update(sample
);
1647 else if (flags
& COMPSTAT_WAIT
)
1649 DWORD start_time
= GetTickCount();
1651 sample
->continuous_update
= FALSE
;
1652 while (sample
->busy
&& elapsed
< milliseconds
)
1654 DWORD sleep_time
= milliseconds
- elapsed
;
1655 if (!SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, sleep_time
))
1657 elapsed
= GetTickCount() - start_time
;
1662 hr
= sample
->busy
? MS_S_PENDING
: sample
->update_hr
;
1664 LeaveCriticalSection(&sample
->parent
->cs
);
1669 /*** IDirectDrawStreamSample methods ***/
1670 static HRESULT WINAPI
ddraw_sample_GetSurface(IDirectDrawStreamSample
*iface
, IDirectDrawSurface
**ddraw_surface
,
1673 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1675 TRACE("(%p)->(%p,%p)\n", iface
, ddraw_surface
, rect
);
1679 *ddraw_surface
= sample
->surface
;
1681 IDirectDrawSurface_AddRef(*ddraw_surface
);
1685 *rect
= sample
->rect
;
1690 static HRESULT WINAPI
ddraw_sample_SetRect(IDirectDrawStreamSample
*iface
, const RECT
*rect
)
1692 FIXME("(%p)->(%p): stub\n", iface
, rect
);
1697 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl
=
1699 /*** IUnknown methods ***/
1700 ddraw_sample_QueryInterface
,
1701 ddraw_sample_AddRef
,
1702 ddraw_sample_Release
,
1703 /*** IStreamSample methods ***/
1704 ddraw_sample_GetMediaStream
,
1705 ddraw_sample_GetSampleTimes
,
1706 ddraw_sample_SetSampleTimes
,
1707 ddraw_sample_Update
,
1708 ddraw_sample_CompletionStatus
,
1709 /*** IDirectDrawStreamSample methods ***/
1710 ddraw_sample_GetSurface
,
1711 ddraw_sample_SetRect
1714 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
1715 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
)
1717 struct ddraw_sample
*object
;
1721 TRACE("(%p)\n", ddraw_stream_sample
);
1723 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1725 return E_OUTOFMEMORY
;
1727 object
->IDirectDrawStreamSample_iface
.lpVtbl
= &DirectDrawStreamSample_Vtbl
;
1729 object
->parent
= parent
;
1730 object
->mmstream
= parent
->parent
;
1731 InitializeConditionVariable(&object
->update_cv
);
1732 IAMMediaStream_AddRef(&parent
->IAMMediaStream_iface
);
1733 if (object
->mmstream
)
1734 IMultiMediaStream_AddRef(object
->mmstream
);
1735 ++parent
->sample_refs
;
1739 object
->surface
= surface
;
1740 IDirectDrawSurface_AddRef(surface
);
1746 hr
= IDirectDrawMediaStream_GetDirectDraw(&parent
->IDirectDrawMediaStream_iface
, &ddraw
);
1749 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1753 desc
.dwSize
= sizeof(desc
);
1754 desc
.dwFlags
= DDSD_CAPS
|DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
;
1755 desc
.dwHeight
= parent
->format
.height
;
1756 desc
.dwWidth
= parent
->format
.width
;
1757 if (parent
->format
.flags
& DDSD_PIXELFORMAT
)
1759 desc
.ddpfPixelFormat
= parent
->format
.pf
;
1763 desc
.ddpfPixelFormat
.dwSize
= sizeof(desc
.ddpfPixelFormat
);
1764 desc
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
1765 desc
.ddpfPixelFormat
.u1
.dwRGBBitCount
= 32;
1766 desc
.ddpfPixelFormat
.u2
.dwRBitMask
= 0xff0000;
1767 desc
.ddpfPixelFormat
.u3
.dwGBitMask
= 0x00ff00;
1768 desc
.ddpfPixelFormat
.u4
.dwBBitMask
= 0x0000ff;
1769 desc
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
= 0;
1771 desc
.ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
|DDSCAPS_OFFSCREENPLAIN
;
1772 desc
.lpSurface
= NULL
;
1774 hr
= IDirectDraw_CreateSurface(ddraw
, &desc
, &object
->surface
, NULL
);
1775 IDirectDraw_Release(ddraw
);
1778 ERR("failed to create surface, 0x%08x\n", hr
);
1779 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1784 desc
.dwSize
= sizeof(desc
);
1785 hr
= IDirectDrawSurface_GetSurfaceDesc(object
->surface
, &desc
);
1788 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1794 object
->rect
= *rect
;
1795 desc
.dwWidth
= rect
->right
- rect
->left
;
1796 desc
.dwHeight
= rect
->bottom
- rect
->top
;
1800 SetRect(&object
->rect
, 0, 0, desc
.dwWidth
, desc
.dwHeight
);
1803 hr
= IDirectDrawMediaStream_SetFormat(&parent
->IDirectDrawMediaStream_iface
, &desc
, NULL
);
1806 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1810 *ddraw_stream_sample
= &object
->IDirectDrawStreamSample_iface
;