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/list.h"
26 #include "wine/strmbase.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
30 static const WCHAR sink_id
[] = L
"I{A35FF56A-9FDA-11D0-8FDF-00C04FD9189D}";
42 IAMMediaStream IAMMediaStream_iface
;
43 IDirectDrawMediaStream IDirectDrawMediaStream_iface
;
44 IMemInputPin IMemInputPin_iface
;
49 IMultiMediaStream
* parent
;
51 STREAM_TYPE stream_type
;
54 IMediaStreamFilter
*filter
;
58 IMemAllocator
*allocator
;
62 REFERENCE_TIME segment_start
;
65 CONDITION_VARIABLE update_queued_cv
;
66 struct list update_queue
;
71 IDirectDrawStreamSample IDirectDrawStreamSample_iface
;
73 struct ddraw_stream
*parent
;
74 IMultiMediaStream
*mmstream
;
75 IDirectDrawSurface
*surface
;
77 STREAM_TIME start_time
;
79 BOOL continuous_update
;
80 CONDITION_VARIABLE update_cv
;
81 HANDLE external_event
;
88 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
89 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
);
91 static void remove_queued_update(struct ddraw_sample
*sample
)
94 list_remove(&sample
->entry
);
95 WakeConditionVariable(&sample
->update_cv
);
96 if (sample
->external_event
)
97 SetEvent(sample
->external_event
);
100 static void flush_update_queue(struct ddraw_stream
*stream
, HRESULT update_hr
)
103 while ((entry
= list_head(&stream
->update_queue
)))
105 struct ddraw_sample
*sample
= LIST_ENTRY(entry
, struct ddraw_sample
, entry
);
106 sample
->update_hr
= update_hr
;
107 remove_queued_update(sample
);
111 static HRESULT
process_update(struct ddraw_sample
*sample
, int stride
, BYTE
*pointer
,
112 STREAM_TIME start_time
, STREAM_TIME end_time
)
121 desc
.dwSize
= sizeof(desc
);
122 hr
= IDirectDrawSurface_Lock(sample
->surface
, &sample
->rect
, &desc
, DDLOCK_WAIT
, NULL
);
126 row_size
= (sample
->rect
.right
- sample
->rect
.left
) * desc
.ddpfPixelFormat
.u1
.dwRGBBitCount
/ 8;
128 dst_row
= desc
.lpSurface
;
129 for (row
= sample
->rect
.top
; row
< sample
->rect
.bottom
; ++row
)
131 memcpy(dst_row
, src_row
, row_size
);
133 dst_row
+= desc
.u1
.lPitch
;
136 hr
= IDirectDrawSurface_Unlock(sample
->surface
, desc
.lpSurface
);
140 sample
->start_time
= start_time
;
141 sample
->end_time
= end_time
;
146 static BOOL
is_format_compatible(struct ddraw_stream
*stream
,
147 DWORD width
, DWORD height
, const DDPIXELFORMAT
*connection_pf
)
149 if (stream
->format
.flags
& DDSD_HEIGHT
)
151 if (stream
->format
.width
!= width
|| stream
->format
.height
!= height
)
154 if (stream
->format
.flags
& DDSD_PIXELFORMAT
)
156 if (stream
->format
.pf
.dwFlags
& DDPF_FOURCC
)
158 if (stream
->format
.pf
.u1
.dwRGBBitCount
!= connection_pf
->u1
.dwRGBBitCount
)
160 if (stream
->format
.pf
.u1
.dwRGBBitCount
== 16 && stream
->format
.pf
.u3
.dwGBitMask
!= connection_pf
->u3
.dwGBitMask
)
166 static inline struct ddraw_stream
*impl_from_IAMMediaStream(IAMMediaStream
*iface
)
168 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IAMMediaStream_iface
);
171 /*** IUnknown methods ***/
172 static HRESULT WINAPI
ddraw_IAMMediaStream_QueryInterface(IAMMediaStream
*iface
,
173 REFIID riid
, void **ret_iface
)
175 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
177 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
179 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
180 IsEqualGUID(riid
, &IID_IMediaStream
) ||
181 IsEqualGUID(riid
, &IID_IAMMediaStream
))
183 IAMMediaStream_AddRef(iface
);
187 else if (IsEqualGUID(riid
, &IID_IDirectDrawMediaStream
))
189 IAMMediaStream_AddRef(iface
);
190 *ret_iface
= &This
->IDirectDrawMediaStream_iface
;
193 else if (IsEqualGUID(riid
, &IID_IPin
))
195 IAMMediaStream_AddRef(iface
);
196 *ret_iface
= &This
->IPin_iface
;
199 else if (IsEqualGUID(riid
, &IID_IMemInputPin
))
201 IAMMediaStream_AddRef(iface
);
202 *ret_iface
= &This
->IMemInputPin_iface
;
206 ERR("(%p)->(%s,%p),not found\n", This
, debugstr_guid(riid
), ret_iface
);
207 return E_NOINTERFACE
;
210 static ULONG WINAPI
ddraw_IAMMediaStream_AddRef(IAMMediaStream
*iface
)
212 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
213 ULONG ref
= InterlockedIncrement(&This
->ref
);
215 TRACE("(%p/%p)->(): new ref = %lu\n", iface
, This
, ref
);
220 static ULONG WINAPI
ddraw_IAMMediaStream_Release(IAMMediaStream
*iface
)
222 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
223 ULONG ref
= InterlockedDecrement(&stream
->ref
);
225 TRACE("%p decreasing refcount to %lu.\n", stream
, ref
);
229 DeleteCriticalSection(&stream
->cs
);
231 IDirectDraw_Release(stream
->ddraw
);
238 /*** IMediaStream methods ***/
239 static HRESULT WINAPI
ddraw_IAMMediaStream_GetMultiMediaStream(IAMMediaStream
*iface
,
240 IMultiMediaStream
**mmstream
)
242 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
244 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
250 IMultiMediaStream_AddRef(stream
->parent
);
251 *mmstream
= stream
->parent
;
255 static HRESULT WINAPI
ddraw_IAMMediaStream_GetInformation(IAMMediaStream
*iface
,
256 MSPID
*purpose_id
, STREAM_TYPE
*type
)
258 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
260 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, purpose_id
, type
);
263 *purpose_id
= This
->purpose_id
;
265 *type
= This
->stream_type
;
270 static HRESULT WINAPI
ddraw_IAMMediaStream_SetSameFormat(IAMMediaStream
*iface
,
271 IMediaStream
*pStreamThatHasDesiredFormat
, DWORD flags
)
273 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
275 FIXME("(%p/%p)->(%p,%lx) stub!\n", This
, iface
, pStreamThatHasDesiredFormat
, flags
);
280 static HRESULT WINAPI
ddraw_IAMMediaStream_AllocateSample(IAMMediaStream
*iface
,
281 DWORD flags
, IStreamSample
**sample
)
283 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
285 FIXME("(%p/%p)->(%lx,%p) stub!\n", This
, iface
, flags
, sample
);
290 static HRESULT WINAPI
ddraw_IAMMediaStream_CreateSharedSample(IAMMediaStream
*iface
,
291 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
293 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
295 FIXME("(%p/%p)->(%p,%lx,%p) stub!\n", This
, iface
, existing_sample
, flags
, sample
);
300 static HRESULT WINAPI
ddraw_IAMMediaStream_SendEndOfStream(IAMMediaStream
*iface
, DWORD flags
)
302 struct ddraw_stream
*This
= impl_from_IAMMediaStream(iface
);
304 FIXME("(%p/%p)->(%lx) stub!\n", This
, iface
, flags
);
309 /*** IAMMediaStream methods ***/
310 static HRESULT WINAPI
ddraw_IAMMediaStream_Initialize(IAMMediaStream
*iface
, IUnknown
*source_object
, DWORD flags
,
311 REFMSPID purpose_id
, const STREAM_TYPE stream_type
)
313 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
316 TRACE("stream %p, source_object %p, flags %lx, purpose_id %s, stream_type %u.\n", stream
, source_object
, flags
,
317 debugstr_guid(purpose_id
), stream_type
);
322 if (flags
& AMMSF_CREATEPEER
)
323 FIXME("AMMSF_CREATEPEER is not yet supported.\n");
325 stream
->purpose_id
= *purpose_id
;
326 stream
->stream_type
= stream_type
;
329 && FAILED(hr
= IUnknown_QueryInterface(source_object
, &IID_IDirectDraw
, (void **)&stream
->ddraw
)))
330 FIXME("Stream object doesn't implement IDirectDraw interface, hr %#lx.\n", hr
);
334 if (FAILED(hr
= DirectDrawCreate(NULL
, &stream
->ddraw
, NULL
)))
336 IDirectDraw_SetCooperativeLevel(stream
->ddraw
, NULL
, DDSCL_NORMAL
);
342 static HRESULT WINAPI
ddraw_IAMMediaStream_SetState(IAMMediaStream
*iface
, FILTER_STATE state
)
344 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
346 TRACE("stream %p, state %u.\n", stream
, state
);
348 EnterCriticalSection(&stream
->cs
);
350 if (state
== State_Stopped
)
351 WakeConditionVariable(&stream
->update_queued_cv
);
352 if (stream
->state
== State_Stopped
)
355 stream
->state
= state
;
357 LeaveCriticalSection(&stream
->cs
);
362 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream
*iface
, IAMMultiMediaStream
*mmstream
)
364 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
366 TRACE("stream %p, mmstream %p.\n", stream
, mmstream
);
368 stream
->parent
= (IMultiMediaStream
*)mmstream
;
373 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilter(IAMMediaStream
*iface
, IMediaStreamFilter
*filter
)
375 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
377 TRACE("iface %p, filter %p.\n", iface
, filter
);
379 stream
->filter
= filter
;
384 static HRESULT WINAPI
ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream
*iface
, IFilterGraph
*filtergraph
)
386 struct ddraw_stream
*stream
= impl_from_IAMMediaStream(iface
);
388 TRACE("stream %p, filtergraph %p.\n", stream
, filtergraph
);
390 stream
->graph
= filtergraph
;
395 static const struct IAMMediaStreamVtbl ddraw_IAMMediaStream_vtbl
=
397 /*** IUnknown methods ***/
398 ddraw_IAMMediaStream_QueryInterface
,
399 ddraw_IAMMediaStream_AddRef
,
400 ddraw_IAMMediaStream_Release
,
401 /*** IMediaStream methods ***/
402 ddraw_IAMMediaStream_GetMultiMediaStream
,
403 ddraw_IAMMediaStream_GetInformation
,
404 ddraw_IAMMediaStream_SetSameFormat
,
405 ddraw_IAMMediaStream_AllocateSample
,
406 ddraw_IAMMediaStream_CreateSharedSample
,
407 ddraw_IAMMediaStream_SendEndOfStream
,
408 /*** IAMMediaStream methods ***/
409 ddraw_IAMMediaStream_Initialize
,
410 ddraw_IAMMediaStream_SetState
,
411 ddraw_IAMMediaStream_JoinAMMultiMediaStream
,
412 ddraw_IAMMediaStream_JoinFilter
,
413 ddraw_IAMMediaStream_JoinFilterGraph
416 static inline struct ddraw_stream
*impl_from_IDirectDrawMediaStream(IDirectDrawMediaStream
*iface
)
418 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IDirectDrawMediaStream_iface
);
421 /*** IUnknown methods ***/
422 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_QueryInterface(IDirectDrawMediaStream
*iface
,
423 REFIID riid
, void **ret_iface
)
425 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
426 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
427 return IAMMediaStream_QueryInterface(&This
->IAMMediaStream_iface
, riid
, ret_iface
);
430 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_AddRef(IDirectDrawMediaStream
*iface
)
432 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
433 TRACE("(%p/%p)\n", iface
, This
);
434 return IAMMediaStream_AddRef(&This
->IAMMediaStream_iface
);
437 static ULONG WINAPI
ddraw_IDirectDrawMediaStream_Release(IDirectDrawMediaStream
*iface
)
439 struct ddraw_stream
*This
= impl_from_IDirectDrawMediaStream(iface
);
440 TRACE("(%p/%p)\n", iface
, This
);
441 return IAMMediaStream_Release(&This
->IAMMediaStream_iface
);
444 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetMultiMediaStream(IDirectDrawMediaStream
*iface
,
445 IMultiMediaStream
**mmstream
)
447 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
448 return IAMMediaStream_GetMultiMediaStream(&stream
->IAMMediaStream_iface
, mmstream
);
451 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetInformation(IDirectDrawMediaStream
*iface
,
452 MSPID
*purpose_id
, STREAM_TYPE
*type
)
454 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
455 return IAMMediaStream_GetInformation(&stream
->IAMMediaStream_iface
, purpose_id
, type
);
458 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetSameFormat(IDirectDrawMediaStream
*iface
,
459 IMediaStream
*other
, DWORD flags
)
461 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
462 return IAMMediaStream_SetSameFormat(&stream
->IAMMediaStream_iface
, other
, flags
);
465 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_AllocateSample(IDirectDrawMediaStream
*iface
,
466 DWORD flags
, IStreamSample
**sample
)
468 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
469 return IAMMediaStream_AllocateSample(&stream
->IAMMediaStream_iface
, flags
, sample
);
472 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSharedSample(IDirectDrawMediaStream
*iface
,
473 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
475 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
476 return IAMMediaStream_CreateSharedSample(&stream
->IAMMediaStream_iface
, existing_sample
, flags
, sample
);
479 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SendEndOfStream(IDirectDrawMediaStream
*iface
, DWORD flags
)
481 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
482 return IAMMediaStream_SendEndOfStream(&stream
->IAMMediaStream_iface
, flags
);
485 /*** IDirectDrawMediaStream methods ***/
486 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStream
*iface
,
487 DDSURFACEDESC
*current_format
, IDirectDrawPalette
**palette
,
488 DDSURFACEDESC
*desired_format
, DWORD
*flags
)
490 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
492 TRACE("stream %p, current_format %p, palette %p, desired_format %p, flags %p.\n", stream
, current_format
, palette
,
493 desired_format
, flags
);
495 EnterCriticalSection(&stream
->cs
);
499 LeaveCriticalSection(&stream
->cs
);
500 return MS_E_NOSTREAM
;
505 current_format
->dwFlags
= stream
->format
.flags
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_CAPS
;
506 current_format
->dwWidth
= stream
->format
.width
;
507 current_format
->dwHeight
= stream
->format
.height
;
508 current_format
->ddpfPixelFormat
= stream
->format
.pf
;
509 current_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
517 desired_format
->dwFlags
= DDSD_WIDTH
| DDSD_HEIGHT
;
518 desired_format
->dwWidth
= stream
->format
.width
;
519 desired_format
->dwHeight
= stream
->format
.height
;
520 desired_format
->ddpfPixelFormat
= stream
->format
.pf
;
521 desired_format
->ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
| DDSCAPS_OFFSCREENPLAIN
;
527 LeaveCriticalSection(&stream
->cs
);
532 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream
*iface
,
533 const DDSURFACEDESC
*format
, IDirectDrawPalette
*palette
)
535 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
536 AM_MEDIA_TYPE old_media_type
;
537 struct format old_format
;
541 TRACE("stream %p, format %p, palette %p.\n", stream
, format
, palette
);
544 FIXME("Setting palette is not yet supported.\n");
549 if (format
->dwSize
!= sizeof(DDSURFACEDESC
))
552 TRACE("flags %#lx, pixel format flags %#lx, bit count %lu, size %lux%lu.\n",
553 format
->dwFlags
, format
->ddpfPixelFormat
.dwFlags
,
554 format
->ddpfPixelFormat
.u1
.dwRGBBitCount
, format
->dwWidth
, format
->dwHeight
);
556 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
558 if (format
->ddpfPixelFormat
.dwSize
!= sizeof(DDPIXELFORMAT
))
559 return DDERR_INVALIDSURFACETYPE
;
561 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
563 if (!format
->ddpfPixelFormat
.u1
.dwRGBBitCount
)
568 if (format
->ddpfPixelFormat
.dwFlags
& (DDPF_YUV
| DDPF_PALETTEINDEXED1
|
569 DDPF_PALETTEINDEXED2
| DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXEDTO8
))
570 return DDERR_INVALIDSURFACETYPE
;
572 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
))
573 return DDERR_INVALIDSURFACETYPE
;
575 switch (format
->ddpfPixelFormat
.u1
.dwRGBBitCount
)
578 if (!(format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
))
579 return DDERR_INVALIDSURFACETYPE
;
582 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
583 return DDERR_INVALIDSURFACETYPE
;
584 if ((format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0x7c00 ||
585 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x03e0 ||
586 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x001f) &&
587 (format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0xf800 ||
588 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x07e0 ||
589 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x001f))
590 return DDERR_INVALIDSURFACETYPE
;
594 if (format
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
)
595 return DDERR_INVALIDSURFACETYPE
;
596 if (format
->ddpfPixelFormat
.u2
.dwRBitMask
!= 0xff0000 ||
597 format
->ddpfPixelFormat
.u3
.dwGBitMask
!= 0x00ff00 ||
598 format
->ddpfPixelFormat
.u4
.dwBBitMask
!= 0x0000ff)
599 return DDERR_INVALIDSURFACETYPE
;
602 return DDERR_INVALIDSURFACETYPE
;
607 EnterCriticalSection(&stream
->cs
);
609 old_format
= stream
->format
;
610 stream
->format
.flags
= format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
);
611 if (format
->dwFlags
& (DDSD_WIDTH
| DDSD_HEIGHT
))
613 stream
->format
.width
= format
->dwWidth
;
614 stream
->format
.height
= format
->dwHeight
;
616 if (format
->dwFlags
& DDSD_PIXELFORMAT
)
617 stream
->format
.pf
= format
->ddpfPixelFormat
;
619 if (stream
->peer
&& !is_format_compatible(stream
, old_format
.width
, old_format
.height
, &old_format
.pf
))
621 hr
= CopyMediaType(&old_media_type
, &stream
->mt
);
624 stream
->format
= old_format
;
625 LeaveCriticalSection(&stream
->cs
);
628 old_peer
= stream
->peer
;
629 IPin_AddRef(old_peer
);
631 IFilterGraph_Disconnect(stream
->graph
, stream
->peer
);
632 IFilterGraph_Disconnect(stream
->graph
, &stream
->IPin_iface
);
633 hr
= IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, NULL
);
636 stream
->format
= old_format
;
637 IFilterGraph_ConnectDirect(stream
->graph
, old_peer
, &stream
->IPin_iface
, &old_media_type
);
638 IPin_Release(old_peer
);
639 FreeMediaType(&old_media_type
);
640 LeaveCriticalSection(&stream
->cs
);
641 return DDERR_INVALIDSURFACETYPE
;
644 IPin_Release(old_peer
);
645 FreeMediaType(&old_media_type
);
648 LeaveCriticalSection(&stream
->cs
);
653 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetDirectDraw(IDirectDrawMediaStream
*iface
,
656 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
658 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
669 IDirectDraw_AddRef(stream
->ddraw
);
670 *ddraw
= stream
->ddraw
;
675 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_SetDirectDraw(IDirectDrawMediaStream
*iface
,
678 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
680 TRACE("stream %p, ddraw %p.\n", stream
, ddraw
);
682 EnterCriticalSection(&stream
->cs
);
684 if (stream
->sample_refs
)
686 HRESULT hr
= (stream
->ddraw
== ddraw
) ? S_OK
: MS_E_SAMPLEALLOC
;
687 LeaveCriticalSection(&stream
->cs
);
692 IDirectDraw_Release(stream
->ddraw
);
696 IDirectDraw_AddRef(ddraw
);
697 stream
->ddraw
= ddraw
;
700 stream
->ddraw
= NULL
;
702 LeaveCriticalSection(&stream
->cs
);
707 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_CreateSample(IDirectDrawMediaStream
*iface
,
708 IDirectDrawSurface
*surface
, const RECT
*rect
, DWORD flags
,
709 IDirectDrawStreamSample
**sample
)
711 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
714 TRACE("stream %p, surface %p, rect %s, flags %#lx, sample %p.\n",
715 stream
, surface
, wine_dbgstr_rect(rect
), flags
, sample
);
717 if (!surface
&& rect
)
720 EnterCriticalSection(&stream
->cs
);
721 hr
= ddrawstreamsample_create(stream
, surface
, rect
, sample
);
722 LeaveCriticalSection(&stream
->cs
);
727 static HRESULT WINAPI
ddraw_IDirectDrawMediaStream_GetTimePerFrame(IDirectDrawMediaStream
*iface
,
728 STREAM_TIME
*frame_time
)
730 struct ddraw_stream
*stream
= impl_from_IDirectDrawMediaStream(iface
);
732 TRACE("stream %p, frame_time %p.\n", stream
, frame_time
);
737 EnterCriticalSection(&stream
->cs
);
741 LeaveCriticalSection(&stream
->cs
);
742 return MS_E_NOSTREAM
;
745 *frame_time
= ((VIDEOINFO
*)stream
->mt
.pbFormat
)->AvgTimePerFrame
;
747 LeaveCriticalSection(&stream
->cs
);
752 static const struct IDirectDrawMediaStreamVtbl ddraw_IDirectDrawMediaStream_Vtbl
=
754 /*** IUnknown methods ***/
755 ddraw_IDirectDrawMediaStream_QueryInterface
,
756 ddraw_IDirectDrawMediaStream_AddRef
,
757 ddraw_IDirectDrawMediaStream_Release
,
758 /*** IMediaStream methods ***/
759 ddraw_IDirectDrawMediaStream_GetMultiMediaStream
,
760 ddraw_IDirectDrawMediaStream_GetInformation
,
761 ddraw_IDirectDrawMediaStream_SetSameFormat
,
762 ddraw_IDirectDrawMediaStream_AllocateSample
,
763 ddraw_IDirectDrawMediaStream_CreateSharedSample
,
764 ddraw_IDirectDrawMediaStream_SendEndOfStream
,
765 /*** IDirectDrawMediaStream methods ***/
766 ddraw_IDirectDrawMediaStream_GetFormat
,
767 ddraw_IDirectDrawMediaStream_SetFormat
,
768 ddraw_IDirectDrawMediaStream_GetDirectDraw
,
769 ddraw_IDirectDrawMediaStream_SetDirectDraw
,
770 ddraw_IDirectDrawMediaStream_CreateSample
,
771 ddraw_IDirectDrawMediaStream_GetTimePerFrame
774 struct enum_media_types
776 IEnumMediaTypes IEnumMediaTypes_iface
;
781 static const IEnumMediaTypesVtbl enum_media_types_vtbl
;
783 static struct enum_media_types
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
785 return CONTAINING_RECORD(iface
, struct enum_media_types
, IEnumMediaTypes_iface
);
788 static HRESULT WINAPI
enum_media_types_QueryInterface(IEnumMediaTypes
*iface
, REFIID iid
, void **out
)
790 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
792 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMediaTypes
))
794 IEnumMediaTypes_AddRef(iface
);
799 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
801 return E_NOINTERFACE
;
804 static ULONG WINAPI
enum_media_types_AddRef(IEnumMediaTypes
*iface
)
806 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
807 ULONG refcount
= InterlockedIncrement(&enum_media_types
->refcount
);
808 TRACE("%p increasing refcount to %lu.\n", enum_media_types
, refcount
);
812 static ULONG WINAPI
enum_media_types_Release(IEnumMediaTypes
*iface
)
814 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
815 ULONG refcount
= InterlockedDecrement(&enum_media_types
->refcount
);
816 TRACE("%p decreasing refcount to %lu.\n", enum_media_types
, refcount
);
818 free(enum_media_types
);
822 static HRESULT WINAPI
enum_media_types_Next(IEnumMediaTypes
*iface
, ULONG count
, AM_MEDIA_TYPE
**mts
, ULONG
*ret_count
)
824 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
826 TRACE("iface %p, count %lu, mts %p, ret_count %p.\n", iface
, count
, mts
, ret_count
);
831 if (count
&& !enum_media_types
->index
)
833 mts
[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
834 memset(mts
[0], 0, sizeof(AM_MEDIA_TYPE
));
835 mts
[0]->majortype
= MEDIATYPE_Video
;
836 mts
[0]->subtype
= MEDIASUBTYPE_RGB8
;
837 mts
[0]->bFixedSizeSamples
= TRUE
;
838 mts
[0]->lSampleSize
= 10000;
839 ++enum_media_types
->index
;
841 return count
== 1 ? S_OK
: S_FALSE
;
845 return count
? S_FALSE
: S_OK
;
848 static HRESULT WINAPI
enum_media_types_Skip(IEnumMediaTypes
*iface
, ULONG count
)
850 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
852 TRACE("iface %p, count %lu.\n", iface
, count
);
854 enum_media_types
->index
+= count
;
859 static HRESULT WINAPI
enum_media_types_Reset(IEnumMediaTypes
*iface
)
861 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
863 TRACE("iface %p.\n", iface
);
865 enum_media_types
->index
= 0;
869 static HRESULT WINAPI
enum_media_types_Clone(IEnumMediaTypes
*iface
, IEnumMediaTypes
**out
)
871 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
872 struct enum_media_types
*object
;
874 TRACE("iface %p, out %p.\n", iface
, out
);
876 if (!(object
= calloc(1, sizeof(*object
))))
877 return E_OUTOFMEMORY
;
879 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
880 object
->refcount
= 1;
881 object
->index
= enum_media_types
->index
;
883 *out
= &object
->IEnumMediaTypes_iface
;
887 static const IEnumMediaTypesVtbl enum_media_types_vtbl
=
889 enum_media_types_QueryInterface
,
890 enum_media_types_AddRef
,
891 enum_media_types_Release
,
892 enum_media_types_Next
,
893 enum_media_types_Skip
,
894 enum_media_types_Reset
,
895 enum_media_types_Clone
,
898 static inline struct ddraw_stream
*impl_from_IPin(IPin
*iface
)
900 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IPin_iface
);
903 static HRESULT WINAPI
ddraw_sink_QueryInterface(IPin
*iface
, REFIID iid
, void **out
)
905 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
906 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
909 static ULONG WINAPI
ddraw_sink_AddRef(IPin
*iface
)
911 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
912 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
915 static ULONG WINAPI
ddraw_sink_Release(IPin
*iface
)
917 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
918 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
921 static HRESULT WINAPI
ddraw_sink_Connect(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
923 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface
, peer
, mt
);
927 static HRESULT WINAPI
ddraw_sink_ReceiveConnection(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
929 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
930 const VIDEOINFOHEADER
*video_info
;
934 DDPIXELFORMAT pf
= {sizeof(DDPIXELFORMAT
)};
936 TRACE("stream %p, peer %p, mt %p.\n", stream
, peer
, mt
);
938 EnterCriticalSection(&stream
->cs
);
942 LeaveCriticalSection(&stream
->cs
);
943 return VFW_E_ALREADY_CONNECTED
;
946 if (!IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
947 || !IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
949 LeaveCriticalSection(&stream
->cs
);
950 return VFW_E_TYPE_NOT_ACCEPTED
;
953 video_info
= (const VIDEOINFOHEADER
*)mt
->pbFormat
;
955 width
= video_info
->bmiHeader
.biWidth
;
956 height
= abs(video_info
->bmiHeader
.biHeight
);
957 pf
.dwFlags
= DDPF_RGB
;
958 if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
))
960 pf
.dwFlags
|= DDPF_PALETTEINDEXED8
;
961 pf
.u1
.dwRGBBitCount
= 8;
963 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB555
))
965 pf
.u1
.dwRGBBitCount
= 16;
966 pf
.u2
.dwRBitMask
= 0x7c00;
967 pf
.u3
.dwGBitMask
= 0x03e0;
968 pf
.u4
.dwBBitMask
= 0x001f;
970 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB565
))
972 pf
.u1
.dwRGBBitCount
= 16;
973 pf
.u2
.dwRBitMask
= 0xf800;
974 pf
.u3
.dwGBitMask
= 0x07e0;
975 pf
.u4
.dwBBitMask
= 0x001f;
977 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB24
))
979 pf
.u1
.dwRGBBitCount
= 24;
980 pf
.u2
.dwRBitMask
= 0xff0000;
981 pf
.u3
.dwGBitMask
= 0x00ff00;
982 pf
.u4
.dwBBitMask
= 0x0000ff;
984 else if (IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB32
))
986 pf
.u1
.dwRGBBitCount
= 32;
987 pf
.u2
.dwRBitMask
= 0xff0000;
988 pf
.u3
.dwGBitMask
= 0x00ff00;
989 pf
.u4
.dwBBitMask
= 0x0000ff;
993 LeaveCriticalSection(&stream
->cs
);
994 return VFW_E_TYPE_NOT_ACCEPTED
;
997 if (!is_format_compatible(stream
, width
, height
, &pf
))
999 LeaveCriticalSection(&stream
->cs
);
1000 return VFW_E_TYPE_NOT_ACCEPTED
;
1003 IPin_QueryDirection(peer
, &dir
);
1004 if (dir
!= PINDIR_OUTPUT
)
1006 WARN("Rejecting connection from input pin.\n");
1007 LeaveCriticalSection(&stream
->cs
);
1008 return VFW_E_INVALID_DIRECTION
;
1011 CopyMediaType(&stream
->mt
, mt
);
1012 IPin_AddRef(stream
->peer
= peer
);
1014 stream
->format
.width
= width
;
1015 stream
->format
.height
= height
;
1016 if (!(stream
->format
.flags
& DDSD_PIXELFORMAT
))
1017 stream
->format
.pf
= pf
;
1019 LeaveCriticalSection(&stream
->cs
);
1024 static HRESULT WINAPI
ddraw_sink_Disconnect(IPin
*iface
)
1026 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1028 TRACE("stream %p.\n", stream
);
1030 EnterCriticalSection(&stream
->cs
);
1034 LeaveCriticalSection(&stream
->cs
);
1038 IPin_Release(stream
->peer
);
1039 stream
->peer
= NULL
;
1040 FreeMediaType(&stream
->mt
);
1041 memset(&stream
->mt
, 0, sizeof(AM_MEDIA_TYPE
));
1043 LeaveCriticalSection(&stream
->cs
);
1048 static HRESULT WINAPI
ddraw_sink_ConnectedTo(IPin
*iface
, IPin
**peer
)
1050 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1053 TRACE("stream %p, peer %p.\n", stream
, peer
);
1055 EnterCriticalSection(&stream
->cs
);
1059 IPin_AddRef(*peer
= stream
->peer
);
1065 hr
= VFW_E_NOT_CONNECTED
;
1068 LeaveCriticalSection(&stream
->cs
);
1073 static HRESULT WINAPI
ddraw_sink_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mt
)
1075 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1078 TRACE("stream %p, mt %p.\n", stream
, mt
);
1080 EnterCriticalSection(&stream
->cs
);
1084 CopyMediaType(mt
, &stream
->mt
);
1089 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
1090 hr
= VFW_E_NOT_CONNECTED
;
1093 LeaveCriticalSection(&stream
->cs
);
1098 static HRESULT WINAPI
ddraw_sink_QueryPinInfo(IPin
*iface
, PIN_INFO
*info
)
1100 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1102 TRACE("stream %p, info %p.\n", stream
, info
);
1104 IBaseFilter_AddRef(info
->pFilter
= (IBaseFilter
*)stream
->filter
);
1105 info
->dir
= PINDIR_INPUT
;
1106 wcscpy(info
->achName
, sink_id
);
1111 static HRESULT WINAPI
ddraw_sink_QueryDirection(IPin
*iface
, PIN_DIRECTION
*dir
)
1113 TRACE("iface %p, dir %p.\n", iface
, dir
);
1114 *dir
= PINDIR_INPUT
;
1118 static HRESULT WINAPI
ddraw_sink_QueryId(IPin
*iface
, WCHAR
**id
)
1120 TRACE("iface %p, id %p.\n", iface
, id
);
1122 if (!(*id
= CoTaskMemAlloc(sizeof(sink_id
))))
1123 return E_OUTOFMEMORY
;
1125 wcscpy(*id
, sink_id
);
1130 static HRESULT WINAPI
ddraw_sink_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*mt
)
1132 TRACE("iface %p, mt %p.\n", iface
, mt
);
1134 if (IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Video
)
1135 && IsEqualGUID(&mt
->subtype
, &MEDIASUBTYPE_RGB8
)
1136 && IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
1139 return VFW_E_TYPE_NOT_ACCEPTED
;
1142 static HRESULT WINAPI
ddraw_sink_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**enum_media_types
)
1144 struct enum_media_types
*object
;
1146 TRACE("iface %p, enum_media_types %p.\n", iface
, enum_media_types
);
1148 if (!enum_media_types
)
1151 if (!(object
= calloc(1, sizeof(*object
))))
1152 return E_OUTOFMEMORY
;
1154 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
1155 object
->refcount
= 1;
1158 *enum_media_types
= &object
->IEnumMediaTypes_iface
;
1162 static HRESULT WINAPI
ddraw_sink_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*count
)
1164 TRACE("iface %p, pins %p, count %p.\n", iface
, pins
, count
);
1168 static HRESULT WINAPI
ddraw_sink_EndOfStream(IPin
*iface
)
1170 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1172 TRACE("stream %p.\n", stream
);
1174 EnterCriticalSection(&stream
->cs
);
1176 if (stream
->eos
|| stream
->flushing
)
1178 LeaveCriticalSection(&stream
->cs
);
1184 flush_update_queue(stream
, MS_S_ENDOFSTREAM
);
1186 LeaveCriticalSection(&stream
->cs
);
1188 /* Calling IMediaStreamFilter::EndOfStream() inside the critical section
1189 * would invert the locking order, so we must leave it first to avoid
1190 * the streaming thread deadlocking on the filter's critical section. */
1191 IMediaStreamFilter_EndOfStream(stream
->filter
);
1196 static HRESULT WINAPI
ddraw_sink_BeginFlush(IPin
*iface
)
1198 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1201 TRACE("stream %p.\n", stream
);
1203 EnterCriticalSection(&stream
->cs
);
1205 cancel_eos
= stream
->eos
;
1207 stream
->flushing
= TRUE
;
1208 stream
->eos
= FALSE
;
1209 WakeConditionVariable(&stream
->update_queued_cv
);
1211 LeaveCriticalSection(&stream
->cs
);
1213 /* Calling IMediaStreamFilter::Flush() inside the critical section would
1214 * invert the locking order, so we must leave it first to avoid the
1215 * application thread deadlocking on the filter's critical section. */
1216 IMediaStreamFilter_Flush(stream
->filter
, cancel_eos
);
1221 static HRESULT WINAPI
ddraw_sink_EndFlush(IPin
*iface
)
1223 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1225 TRACE("stream %p.\n", stream
);
1227 EnterCriticalSection(&stream
->cs
);
1229 stream
->flushing
= FALSE
;
1231 LeaveCriticalSection(&stream
->cs
);
1236 static HRESULT WINAPI
ddraw_sink_NewSegment(IPin
*iface
, REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
1238 struct ddraw_stream
*stream
= impl_from_IPin(iface
);
1240 TRACE("stream %p, start %s, stop %s, rate %0.16e\n",
1241 stream
, wine_dbgstr_longlong(start
), wine_dbgstr_longlong(stop
), rate
);
1243 EnterCriticalSection(&stream
->cs
);
1245 stream
->segment_start
= start
;
1247 LeaveCriticalSection(&stream
->cs
);
1252 static const IPinVtbl ddraw_sink_vtbl
=
1254 ddraw_sink_QueryInterface
,
1258 ddraw_sink_ReceiveConnection
,
1259 ddraw_sink_Disconnect
,
1260 ddraw_sink_ConnectedTo
,
1261 ddraw_sink_ConnectionMediaType
,
1262 ddraw_sink_QueryPinInfo
,
1263 ddraw_sink_QueryDirection
,
1265 ddraw_sink_QueryAccept
,
1266 ddraw_sink_EnumMediaTypes
,
1267 ddraw_sink_QueryInternalConnections
,
1268 ddraw_sink_EndOfStream
,
1269 ddraw_sink_BeginFlush
,
1270 ddraw_sink_EndFlush
,
1271 ddraw_sink_NewSegment
,
1274 static inline struct ddraw_stream
*impl_from_IMemInputPin(IMemInputPin
*iface
)
1276 return CONTAINING_RECORD(iface
, struct ddraw_stream
, IMemInputPin_iface
);
1279 static HRESULT WINAPI
ddraw_meminput_QueryInterface(IMemInputPin
*iface
, REFIID iid
, void **out
)
1281 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1282 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
1285 static ULONG WINAPI
ddraw_meminput_AddRef(IMemInputPin
*iface
)
1287 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1288 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
1291 static ULONG WINAPI
ddraw_meminput_Release(IMemInputPin
*iface
)
1293 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1294 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
1297 static HRESULT WINAPI
ddraw_meminput_GetAllocator(IMemInputPin
*iface
, IMemAllocator
**allocator
)
1299 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1301 TRACE("stream %p, allocator %p.\n", stream
, allocator
);
1303 if (stream
->allocator
)
1305 IMemAllocator_AddRef(*allocator
= stream
->allocator
);
1310 return VFW_E_NO_ALLOCATOR
;
1313 static HRESULT WINAPI
ddraw_meminput_NotifyAllocator(IMemInputPin
*iface
, IMemAllocator
*allocator
, BOOL readonly
)
1315 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1317 TRACE("stream %p, allocator %p, readonly %d.\n", stream
, allocator
, readonly
);
1323 IMemAllocator_AddRef(allocator
);
1324 if (stream
->allocator
)
1325 IMemAllocator_Release(stream
->allocator
);
1326 stream
->allocator
= allocator
;
1331 static HRESULT WINAPI
ddraw_meminput_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
1333 TRACE("iface %p, props %p.\n", iface
, props
);
1337 static HRESULT WINAPI
ddraw_meminput_Receive(IMemInputPin
*iface
, IMediaSample
*sample
)
1339 struct ddraw_stream
*stream
= impl_from_IMemInputPin(iface
);
1340 BITMAPINFOHEADER
*bitmap_info
;
1341 REFERENCE_TIME start_time
= 0;
1342 REFERENCE_TIME end_time
= 0;
1343 STREAM_TIME start_stream_time
;
1344 STREAM_TIME end_stream_time
;
1345 IMediaStreamFilter
*filter
;
1346 STREAM_TIME current_time
;
1347 BYTE
*top_down_pointer
;
1348 int top_down_stride
;
1354 TRACE("stream %p, sample %p.\n", stream
, sample
);
1356 hr
= IMediaSample_GetPointer(sample
, &pointer
);
1360 IMediaSample_GetTime(sample
, &start_time
, &end_time
);
1362 EnterCriticalSection(&stream
->cs
);
1364 if (stream
->state
== State_Stopped
)
1366 LeaveCriticalSection(&stream
->cs
);
1369 if (stream
->flushing
)
1371 LeaveCriticalSection(&stream
->cs
);
1375 bitmap_info
= &((VIDEOINFOHEADER
*)stream
->mt
.pbFormat
)->bmiHeader
;
1377 stride
= ((bitmap_info
->biWidth
* bitmap_info
->biBitCount
+ 31) & ~31) / 8;
1378 top_down
= (bitmap_info
->biHeight
< 0);
1380 top_down_stride
= top_down
? stride
: -stride
;
1381 top_down_pointer
= top_down
? pointer
: pointer
+ stride
* (bitmap_info
->biHeight
- 1);
1383 start_stream_time
= start_time
+ stream
->segment_start
;
1384 end_stream_time
= end_time
+ stream
->segment_start
;
1386 filter
= stream
->filter
;
1388 LeaveCriticalSection(&stream
->cs
);
1389 if (S_OK
== IMediaStreamFilter_GetCurrentStreamTime(filter
, ¤t_time
)
1390 && start_time
>= current_time
+ 10000)
1391 IMediaStreamFilter_WaitUntil(filter
, start_time
);
1392 EnterCriticalSection(&stream
->cs
);
1396 if (stream
->state
== State_Stopped
)
1398 LeaveCriticalSection(&stream
->cs
);
1401 if (stream
->flushing
)
1403 LeaveCriticalSection(&stream
->cs
);
1406 if (!list_empty(&stream
->update_queue
))
1408 struct ddraw_sample
*sample
= LIST_ENTRY(list_head(&stream
->update_queue
), struct ddraw_sample
, entry
);
1410 sample
->update_hr
= process_update(sample
, top_down_stride
, top_down_pointer
,
1411 start_stream_time
, end_stream_time
);
1413 if (sample
->continuous_update
&& SUCCEEDED(sample
->update_hr
))
1415 list_remove(&sample
->entry
);
1416 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1420 remove_queued_update(sample
);
1422 LeaveCriticalSection(&stream
->cs
);
1426 SleepConditionVariableCS(&stream
->update_queued_cv
, &stream
->cs
, INFINITE
);
1430 static HRESULT WINAPI
ddraw_meminput_ReceiveMultiple(IMemInputPin
*iface
,
1431 IMediaSample
**samples
, LONG count
, LONG
*processed
)
1433 FIXME("iface %p, samples %p, count %lu, processed %p, stub!\n", iface
, samples
, count
, processed
);
1437 static HRESULT WINAPI
ddraw_meminput_ReceiveCanBlock(IMemInputPin
*iface
)
1439 TRACE("iface %p.\n", iface
);
1443 static const IMemInputPinVtbl ddraw_meminput_vtbl
=
1445 ddraw_meminput_QueryInterface
,
1446 ddraw_meminput_AddRef
,
1447 ddraw_meminput_Release
,
1448 ddraw_meminput_GetAllocator
,
1449 ddraw_meminput_NotifyAllocator
,
1450 ddraw_meminput_GetAllocatorRequirements
,
1451 ddraw_meminput_Receive
,
1452 ddraw_meminput_ReceiveMultiple
,
1453 ddraw_meminput_ReceiveCanBlock
,
1456 HRESULT
ddraw_stream_create(IUnknown
*outer
, void **out
)
1458 struct ddraw_stream
*object
;
1461 return CLASS_E_NOAGGREGATION
;
1463 if (!(object
= calloc(1, sizeof(*object
))))
1464 return E_OUTOFMEMORY
;
1466 object
->IAMMediaStream_iface
.lpVtbl
= &ddraw_IAMMediaStream_vtbl
;
1467 object
->IDirectDrawMediaStream_iface
.lpVtbl
= &ddraw_IDirectDrawMediaStream_Vtbl
;
1468 object
->IMemInputPin_iface
.lpVtbl
= &ddraw_meminput_vtbl
;
1469 object
->IPin_iface
.lpVtbl
= &ddraw_sink_vtbl
;
1472 object
->format
.width
= 100;
1473 object
->format
.height
= 100;
1475 InitializeCriticalSection(&object
->cs
);
1476 InitializeConditionVariable(&object
->update_queued_cv
);
1477 list_init(&object
->update_queue
);
1479 TRACE("Created ddraw stream %p.\n", object
);
1481 *out
= &object
->IAMMediaStream_iface
;
1486 static inline struct ddraw_sample
*impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample
*iface
)
1488 return CONTAINING_RECORD(iface
, struct ddraw_sample
, IDirectDrawStreamSample_iface
);
1491 /*** IUnknown methods ***/
1492 static HRESULT WINAPI
ddraw_sample_QueryInterface(IDirectDrawStreamSample
*iface
,
1493 REFIID riid
, void **ret_iface
)
1495 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(riid
), ret_iface
);
1497 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1498 IsEqualGUID(riid
, &IID_IStreamSample
) ||
1499 IsEqualGUID(riid
, &IID_IDirectDrawStreamSample
))
1501 IDirectDrawStreamSample_AddRef(iface
);
1508 ERR("(%p)->(%s,%p),not found\n", iface
, debugstr_guid(riid
), ret_iface
);
1509 return E_NOINTERFACE
;
1512 static ULONG WINAPI
ddraw_sample_AddRef(IDirectDrawStreamSample
*iface
)
1514 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1515 ULONG ref
= InterlockedIncrement(&sample
->ref
);
1517 TRACE("(%p)->(): new ref = %lu\n", iface
, ref
);
1522 static ULONG WINAPI
ddraw_sample_Release(IDirectDrawStreamSample
*iface
)
1524 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1525 ULONG ref
= InterlockedDecrement(&sample
->ref
);
1527 TRACE("(%p)->(): new ref = %lu\n", iface
, ref
);
1531 EnterCriticalSection(&sample
->parent
->cs
);
1532 --sample
->parent
->sample_refs
;
1533 LeaveCriticalSection(&sample
->parent
->cs
);
1535 if (sample
->mmstream
)
1536 IMultiMediaStream_Release(sample
->mmstream
);
1537 IAMMediaStream_Release(&sample
->parent
->IAMMediaStream_iface
);
1539 if (sample
->surface
)
1540 IDirectDrawSurface_Release(sample
->surface
);
1547 /*** IStreamSample methods ***/
1548 static HRESULT WINAPI
ddraw_sample_GetMediaStream(IDirectDrawStreamSample
*iface
, IMediaStream
**media_stream
)
1550 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1552 TRACE("sample %p, media_stream %p.\n", sample
, media_stream
);
1557 IAMMediaStream_AddRef(&sample
->parent
->IAMMediaStream_iface
);
1558 *media_stream
= (IMediaStream
*)&sample
->parent
->IAMMediaStream_iface
;
1563 static HRESULT WINAPI
ddraw_sample_GetSampleTimes(IDirectDrawStreamSample
*iface
, STREAM_TIME
*start_time
,
1564 STREAM_TIME
*end_time
, STREAM_TIME
*current_time
)
1566 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1568 TRACE("sample %p, start_time %p, end_time %p, current_time %p.\n", sample
, start_time
, end_time
, current_time
);
1571 IMediaStreamFilter_GetCurrentStreamTime(sample
->parent
->filter
, current_time
);
1574 *start_time
= sample
->start_time
;
1576 *end_time
= sample
->end_time
;
1581 static HRESULT WINAPI
ddraw_sample_SetSampleTimes(IDirectDrawStreamSample
*iface
, const STREAM_TIME
*start_time
,
1582 const STREAM_TIME
*end_time
)
1584 FIXME("(%p)->(%p,%p): stub\n", iface
, start_time
, end_time
);
1589 static HRESULT WINAPI
ddraw_sample_Update(IDirectDrawStreamSample
*iface
,
1590 DWORD flags
, HANDLE event
, PAPCFUNC apc_func
, DWORD apc_data
)
1592 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1594 TRACE("sample %p, flags %#lx, event %p, apc_func %p, apc_data %#lx.\n",
1595 sample
, flags
, event
, apc_func
, apc_data
);
1597 if (event
&& apc_func
)
1598 return E_INVALIDARG
;
1602 FIXME("APC support is not implemented!\n");
1606 EnterCriticalSection(&sample
->parent
->cs
);
1608 if (sample
->parent
->state
!= State_Running
)
1610 LeaveCriticalSection(&sample
->parent
->cs
);
1611 return MS_E_NOTRUNNING
;
1613 if (!sample
->parent
->peer
|| sample
->parent
->eos
)
1615 sample
->update_hr
= MS_S_ENDOFSTREAM
;
1616 LeaveCriticalSection(&sample
->parent
->cs
);
1617 return MS_S_ENDOFSTREAM
;
1621 LeaveCriticalSection(&sample
->parent
->cs
);
1625 sample
->continuous_update
= (flags
& SSUPDATE_ASYNC
) && (flags
& SSUPDATE_CONTINUOUS
);
1627 sample
->update_hr
= MS_S_NOUPDATE
;
1628 sample
->busy
= TRUE
;
1629 sample
->external_event
= event
;
1630 list_add_tail(&sample
->parent
->update_queue
, &sample
->entry
);
1631 WakeConditionVariable(&sample
->parent
->update_queued_cv
);
1633 if ((flags
& SSUPDATE_ASYNC
) || event
)
1635 LeaveCriticalSection(&sample
->parent
->cs
);
1636 return MS_S_PENDING
;
1639 while (sample
->busy
)
1640 SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, INFINITE
);
1642 LeaveCriticalSection(&sample
->parent
->cs
);
1644 return sample
->update_hr
;
1647 static HRESULT WINAPI
ddraw_sample_CompletionStatus(IDirectDrawStreamSample
*iface
, DWORD flags
, DWORD milliseconds
)
1649 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1652 TRACE("sample %p, flags %#lx, milliseconds %lu.\n", sample
, flags
, milliseconds
);
1654 EnterCriticalSection(&sample
->parent
->cs
);
1658 if (flags
& (COMPSTAT_NOUPDATEOK
| COMPSTAT_ABORT
))
1660 remove_queued_update(sample
);
1662 else if (flags
& COMPSTAT_WAIT
)
1664 DWORD start_time
= GetTickCount();
1666 sample
->continuous_update
= FALSE
;
1667 while (sample
->busy
&& elapsed
< milliseconds
)
1669 DWORD sleep_time
= milliseconds
- elapsed
;
1670 if (!SleepConditionVariableCS(&sample
->update_cv
, &sample
->parent
->cs
, sleep_time
))
1672 elapsed
= GetTickCount() - start_time
;
1677 hr
= sample
->busy
? MS_S_PENDING
: sample
->update_hr
;
1679 LeaveCriticalSection(&sample
->parent
->cs
);
1684 /*** IDirectDrawStreamSample methods ***/
1685 static HRESULT WINAPI
ddraw_sample_GetSurface(IDirectDrawStreamSample
*iface
, IDirectDrawSurface
**ddraw_surface
,
1688 struct ddraw_sample
*sample
= impl_from_IDirectDrawStreamSample(iface
);
1690 TRACE("(%p)->(%p,%p)\n", iface
, ddraw_surface
, rect
);
1694 *ddraw_surface
= sample
->surface
;
1696 IDirectDrawSurface_AddRef(*ddraw_surface
);
1700 *rect
= sample
->rect
;
1705 static HRESULT WINAPI
ddraw_sample_SetRect(IDirectDrawStreamSample
*iface
, const RECT
*rect
)
1707 FIXME("(%p)->(%p): stub\n", iface
, rect
);
1712 static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl
=
1714 /*** IUnknown methods ***/
1715 ddraw_sample_QueryInterface
,
1716 ddraw_sample_AddRef
,
1717 ddraw_sample_Release
,
1718 /*** IStreamSample methods ***/
1719 ddraw_sample_GetMediaStream
,
1720 ddraw_sample_GetSampleTimes
,
1721 ddraw_sample_SetSampleTimes
,
1722 ddraw_sample_Update
,
1723 ddraw_sample_CompletionStatus
,
1724 /*** IDirectDrawStreamSample methods ***/
1725 ddraw_sample_GetSurface
,
1726 ddraw_sample_SetRect
1729 static HRESULT
ddrawstreamsample_create(struct ddraw_stream
*parent
, IDirectDrawSurface
*surface
,
1730 const RECT
*rect
, IDirectDrawStreamSample
**ddraw_stream_sample
)
1732 struct ddraw_sample
*object
;
1736 TRACE("(%p)\n", ddraw_stream_sample
);
1738 if (!(object
= calloc(1, sizeof(*object
))))
1739 return E_OUTOFMEMORY
;
1741 object
->IDirectDrawStreamSample_iface
.lpVtbl
= &DirectDrawStreamSample_Vtbl
;
1743 object
->parent
= parent
;
1744 object
->mmstream
= parent
->parent
;
1745 InitializeConditionVariable(&object
->update_cv
);
1746 IAMMediaStream_AddRef(&parent
->IAMMediaStream_iface
);
1747 if (object
->mmstream
)
1748 IMultiMediaStream_AddRef(object
->mmstream
);
1749 ++parent
->sample_refs
;
1753 object
->surface
= surface
;
1754 IDirectDrawSurface_AddRef(surface
);
1760 hr
= IDirectDrawMediaStream_GetDirectDraw(&parent
->IDirectDrawMediaStream_iface
, &ddraw
);
1763 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1767 desc
.dwSize
= sizeof(desc
);
1768 desc
.dwFlags
= DDSD_CAPS
|DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
;
1769 desc
.dwHeight
= parent
->format
.height
;
1770 desc
.dwWidth
= parent
->format
.width
;
1771 if (parent
->format
.flags
& DDSD_PIXELFORMAT
)
1773 desc
.ddpfPixelFormat
= parent
->format
.pf
;
1777 desc
.ddpfPixelFormat
.dwSize
= sizeof(desc
.ddpfPixelFormat
);
1778 desc
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
1779 desc
.ddpfPixelFormat
.u1
.dwRGBBitCount
= 32;
1780 desc
.ddpfPixelFormat
.u2
.dwRBitMask
= 0xff0000;
1781 desc
.ddpfPixelFormat
.u3
.dwGBitMask
= 0x00ff00;
1782 desc
.ddpfPixelFormat
.u4
.dwBBitMask
= 0x0000ff;
1783 desc
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
= 0;
1785 desc
.ddsCaps
.dwCaps
= DDSCAPS_SYSTEMMEMORY
|DDSCAPS_OFFSCREENPLAIN
;
1786 desc
.lpSurface
= NULL
;
1788 hr
= IDirectDraw_CreateSurface(ddraw
, &desc
, &object
->surface
, NULL
);
1789 IDirectDraw_Release(ddraw
);
1792 ERR("failed to create surface, 0x%08lx\n", hr
);
1793 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1798 desc
.dwSize
= sizeof(desc
);
1799 hr
= IDirectDrawSurface_GetSurfaceDesc(object
->surface
, &desc
);
1802 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1808 object
->rect
= *rect
;
1809 desc
.dwWidth
= rect
->right
- rect
->left
;
1810 desc
.dwHeight
= rect
->bottom
- rect
->top
;
1814 SetRect(&object
->rect
, 0, 0, desc
.dwWidth
, desc
.dwHeight
);
1817 hr
= IDirectDrawMediaStream_SetFormat(&parent
->IDirectDrawMediaStream_iface
, &desc
, NULL
);
1820 IDirectDrawStreamSample_Release(&object
->IDirectDrawStreamSample_iface
);
1824 *ddraw_stream_sample
= &object
->IDirectDrawStreamSample_iface
;