Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/ddrawstream.c | 24 ++++++++++--- dlls/amstream/tests/amstream.c | 66 +++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index fdfe0374ab1..679da1bd2d3 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -1449,14 +1449,30 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw } }
- if (rect) - object->rect = *rect; - else if (object->surface) { DDSURFACEDESC desc = { sizeof(desc) }; hr = IDirectDrawSurface_GetSurfaceDesc(object->surface, &desc); - if (hr == S_OK) + if (FAILED(hr)) + { + IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface); + return hr; + } + if (rect) + { + object->rect = *rect; + desc.dwWidth = rect->right - rect->left; + desc.dwHeight = rect->bottom - rect->top; + } + else + { SetRect(&object->rect, 0, 0, desc.dwWidth, desc.dwHeight); + } + hr = IDirectDrawMediaStream_SetFormat(&parent->IDirectDrawMediaStream_iface, &desc, NULL); + if (FAILED(hr)) + { + IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface); + return hr; + } }
*ddraw_stream_sample = &object->IDirectDrawStreamSample_iface; diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 1c0b36ea6c5..d2126a15db3 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -6495,6 +6495,7 @@ static void get_ddrawstream_create_sample_desc_(int line, const DDSURFACEDESC *f static void test_ddrawstream_create_sample(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); + DDSURFACEDESC desc2 = { sizeof(desc2) }; IDirectDrawSurface *surface, *surface2; DDSURFACEDESC desc = { sizeof(desc) }; IDirectDrawMediaStream *ddraw_stream; @@ -6591,11 +6592,74 @@ static void test_ddrawstream_create_sample(void) hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample); ok(hr == S_OK, "Got hr %#x.\n", hr);
- IDirectDrawMediaStream_Release(ddraw_stream); ref = IDirectDrawStreamSample_Release(sample); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IDirectDrawSurface_Release(surface); ok(!ref, "Got outstanding refcount %d.\n", ref); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; + desc.dwWidth = 444; + desc.dwHeight = 400; + desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + desc.ddpfPixelFormat.dwRGBBitCount = 32; + desc.ddpfPixelFormat.dwRBitMask = 0xff0000; + desc.ddpfPixelFormat.dwGBitMask = 0x00ff00; + desc.ddpfPixelFormat.dwBBitMask = 0x0000ff; + desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000; + desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + SetRect(&rect, 111, 100, 333, 300); + + hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = IDirectDrawStreamSample_Release(sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample); + ok(hr == S_OK, "Got hr %#x.\n", hr); + surface2 = NULL; + hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IDirectDrawSurface_GetSurfaceDesc(surface2, &desc2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(desc2.dwWidth == 222, "Got width %u.\n", desc2.dwWidth); + ok(desc2.dwHeight == 200, "Got height %u.\n", desc2.dwHeight); + ok(memcmp(&desc2.ddpfPixelFormat, &desc.ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0, + "Pixel format didn't match.\n"); + + ref = IDirectDrawStreamSample_Release(sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IDirectDrawSurface_Release(surface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IDirectDrawSurface_Release(surface2); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; + desc.dwWidth = 444; + desc.dwHeight = 400; + desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED4; + desc.ddpfPixelFormat.dwRGBBitCount = 4; + desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample); + ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#x.\n", hr); + + IDirectDrawMediaStream_Release(ddraw_stream); + ref = IDirectDrawSurface_Release(surface); + ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IAMMultiMediaStream_Release(mmstream); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IMediaStream_Release(stream);
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/ddrawstream.c | 13 ++++-- dlls/amstream/tests/amstream.c | 76 ++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 38 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 679da1bd2d3..871a65b6538 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -57,6 +57,7 @@ struct ddraw_stream IMemAllocator *allocator; AM_MEDIA_TYPE mt; struct format format; + FILTER_STATE state; };
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, @@ -260,11 +261,17 @@ static HRESULT WINAPI ddraw_IAMMediaStream_Initialize(IAMMediaStream *iface, IUn
static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTER_STATE state) { - struct ddraw_stream *This = impl_from_IAMMediaStream(iface); + struct ddraw_stream *stream = impl_from_IAMMediaStream(iface);
- FIXME("(%p/%p)->(%u) stub!\n", This, iface, state); + TRACE("stream %p, state %u.\n", stream, state);
- return S_FALSE; + EnterCriticalSection(&stream->cs); + + stream->state = state; + + LeaveCriticalSection(&stream->cs); + + return S_OK; }
static HRESULT WINAPI ddraw_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream) diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index d2126a15db3..af2d77d813e 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3613,40 +3613,6 @@ static void test_ddrawstream_receive_connection(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
-static void test_audiostream_set_state(void) -{ - IAMMultiMediaStream *mmstream = create_ammultimediastream(); - IAMMediaStream *am_stream; - IMediaStream *stream; - HRESULT hr; - ULONG ref; - - hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IMediaStream_QueryInterface(stream, &IID_IAMMediaStream, (void **)&am_stream); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IAMMediaStream_SetState(am_stream, 4); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IAMMediaStream_SetState(am_stream, State_Running); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IAMMediaStream_SetState(am_stream, State_Paused); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IAMMediaStream_SetState(am_stream, State_Stopped); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - ref = IAMMultiMediaStream_Release(mmstream); - ok(!ref, "Got outstanding refcount %d.\n", ref); - IAMMediaStream_Release(am_stream); - ref = IMediaStream_Release(stream); - ok(!ref, "Got outstanding refcount %d.\n", ref); -} - void test_audiostream_end_of_stream(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); @@ -5358,6 +5324,46 @@ static void test_ammediastream_join_filter_graph(void) check_ammediastream_join_filter_graph(&MSPID_PrimaryVideo); }
+static void check_ammediastream_set_state(const MSPID *id) +{ + IAMMultiMediaStream *mmstream = create_ammultimediastream(); + IAMMediaStream *am_stream; + IMediaStream *stream; + HRESULT hr; + ULONG ref; + + hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, &stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStream_QueryInterface(stream, &IID_IAMMediaStream, (void **)&am_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMMediaStream_SetState(am_stream, 4); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMMediaStream_SetState(am_stream, State_Running); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMMediaStream_SetState(am_stream, State_Paused); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMMediaStream_SetState(am_stream, State_Stopped); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ref = IAMMultiMediaStream_Release(mmstream); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IAMMediaStream_Release(am_stream); + ref = IMediaStream_Release(stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + +static void test_ammediastream_set_state(void) +{ + check_ammediastream_set_state(&MSPID_PrimaryAudio); + check_ammediastream_set_state(&MSPID_PrimaryVideo); +} + void test_mediastreamfilter_get_state(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); @@ -6851,7 +6857,6 @@ START_TEST(amstream) test_audiostream_get_format(); test_audiostream_set_format(); test_audiostream_receive_connection(); - test_audiostream_set_state(); test_audiostream_end_of_stream(); test_audiostream_receive(); test_audiostream_initialize(); @@ -6876,6 +6881,7 @@ START_TEST(amstream) test_ammediastream_join_am_multi_media_stream(); test_ammediastream_join_filter(); test_ammediastream_join_filter_graph(); + test_ammediastream_set_state();
test_mediastreamfilter_get_state(); test_mediastreamfilter_stop_pause_run();
Signed-off-by: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/ddrawstream.c | 23 +++++- dlls/amstream/tests/amstream.c | 126 +++++++++++++++++---------------- 2 files changed, 87 insertions(+), 62 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 871a65b6538..e706841c8fc 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -58,6 +58,7 @@ struct ddraw_stream AM_MEDIA_TYPE mt; struct format format; FILTER_STATE state; + BOOL eos; };
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, @@ -267,6 +268,9 @@ static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTE
EnterCriticalSection(&stream->cs);
+ if (stream->state == State_Stopped) + stream->eos = FALSE; + stream->state = state;
LeaveCriticalSection(&stream->cs); @@ -1061,8 +1065,23 @@ static HRESULT WINAPI ddraw_sink_QueryInternalConnections(IPin *iface, IPin **pi
static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface) { - FIXME("iface %p, stub!\n", iface); - return E_NOTIMPL; + struct ddraw_stream *stream = impl_from_IPin(iface); + + TRACE("stream %p.\n", stream); + + EnterCriticalSection(&stream->cs); + + if (stream->eos) + { + LeaveCriticalSection(&stream->cs); + return E_FAIL; + } + + stream->eos = TRUE; + + LeaveCriticalSection(&stream->cs); + + return S_OK; }
static HRESULT WINAPI ddraw_sink_BeginFlush(IPin *iface) diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index af2d77d813e..df9d148493f 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3613,65 +3613,6 @@ static void test_ddrawstream_receive_connection(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
-void test_audiostream_end_of_stream(void) -{ - IAMMultiMediaStream *mmstream = create_ammultimediastream(); - struct testfilter source; - IGraphBuilder *graph; - IMediaStream *stream; - HRESULT hr; - ULONG ref; - IPin *pin; - - hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(!!graph, "Expected non-NULL graph.\n"); - testfilter_init(&source); - hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IPin_EndOfStream(pin); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IPin_EndOfStream(pin); - ok(hr == E_FAIL, "Got hr %#x.\n", hr); - - hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IPin_EndOfStream(pin); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IPin_EndOfStream(pin); - ok(hr == E_FAIL, "Got hr %#x.\n", hr); - - hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); - ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IPin_EndOfStream(pin); - ok(hr == E_FAIL, "Got hr %#x.\n", hr); - - IGraphBuilder_Disconnect(graph, pin); - IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface); - - ref = IAMMultiMediaStream_Release(mmstream); - ok(!ref, "Got outstanding refcount %d.\n", ref); - ref = IGraphBuilder_Release(graph); - ok(!ref, "Got outstanding refcount %d.\n", ref); - IPin_Release(pin); - ref = IMediaStream_Release(stream); - ok(!ref, "Got outstanding refcount %d.\n", ref); -} - static void test_audiostream_receive(void) { ALLOCATOR_PROPERTIES properties = @@ -5364,6 +5305,71 @@ static void test_ammediastream_set_state(void) check_ammediastream_set_state(&MSPID_PrimaryVideo); }
+static void check_ammediastream_end_of_stream(const MSPID *id, const AM_MEDIA_TYPE *mt) +{ + IAMMultiMediaStream *mmstream = create_ammultimediastream(); + struct testfilter source; + IGraphBuilder *graph; + IMediaStream *stream; + HRESULT hr; + ULONG ref; + IPin *pin; + + hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, &stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!!graph, "Expected non-NULL graph.\n"); + testfilter_init(&source); + hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + IGraphBuilder_Disconnect(graph, pin); + IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface); + + ref = IAMMultiMediaStream_Release(mmstream); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IGraphBuilder_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IPin_Release(pin); + ref = IMediaStream_Release(stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + +static void test_ammediastream_end_of_stream(void) +{ + check_ammediastream_end_of_stream(&MSPID_PrimaryAudio, &audio_mt); + check_ammediastream_end_of_stream(&MSPID_PrimaryVideo, &rgb32_mt); +} + void test_mediastreamfilter_get_state(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); @@ -6857,7 +6863,6 @@ START_TEST(amstream) test_audiostream_get_format(); test_audiostream_set_format(); test_audiostream_receive_connection(); - test_audiostream_end_of_stream(); test_audiostream_receive(); test_audiostream_initialize(); test_audiostream_begin_flush_end_flush(); @@ -6882,6 +6887,7 @@ START_TEST(amstream) test_ammediastream_join_filter(); test_ammediastream_join_filter_graph(); test_ammediastream_set_state(); + test_ammediastream_end_of_stream();
test_mediastreamfilter_get_state(); test_mediastreamfilter_stop_pause_run();
Signed-off-by: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/ddrawstream.c | 25 ++++++- dlls/amstream/tests/amstream.c | 118 +++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index e706841c8fc..856c8775445 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -59,6 +59,7 @@ struct ddraw_stream struct format format; FILTER_STATE state; BOOL eos; + HANDLE update_queued_event; };
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, @@ -150,6 +151,7 @@ static ULONG WINAPI ddraw_IAMMediaStream_Release(IAMMediaStream *iface) DeleteCriticalSection(&stream->cs); if (stream->ddraw) IDirectDraw_Release(stream->ddraw); + CloseHandle(stream->update_queued_event); HeapFree(GetProcessHeap(), 0, stream); }
@@ -268,6 +270,8 @@ static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTE
EnterCriticalSection(&stream->cs);
+ if (state == State_Stopped) + SetEvent(stream->update_queued_event); if (stream->state == State_Stopped) stream->eos = FALSE;
@@ -1190,8 +1194,24 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac
static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) { - FIXME("iface %p, sample %p, stub!\n", iface, sample); - return E_NOTIMPL; + struct ddraw_stream *stream = impl_from_IMemInputPin(iface); + + TRACE("stream %p, sample %p.\n", stream, sample); + + EnterCriticalSection(&stream->cs); + + for (;;) + { + if (stream->state == State_Stopped) + { + LeaveCriticalSection(&stream->cs); + return S_OK; + } + + LeaveCriticalSection(&stream->cs); + WaitForSingleObject(stream->update_queued_event, INFINITE); + EnterCriticalSection(&stream->cs); + } }
static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface, @@ -1236,6 +1256,7 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) object->IMemInputPin_iface.lpVtbl = &ddraw_meminput_vtbl; object->IPin_iface.lpVtbl = &ddraw_sink_vtbl; object->ref = 1; + object->update_queued_event = CreateEventW(NULL, FALSE, FALSE, NULL);
object->format.width = 100; object->format.height = 100; diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index df9d148493f..d0c20f6253a 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -5076,6 +5076,123 @@ static void test_ddrawstream_set_format(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static IAMMultiMediaStream *ddrawstream_mmstream; +static STREAM_STATE ddrawstream_state; + +static DWORD CALLBACK ddrawstream_set_state(void *param) +{ + HRESULT hr; + + Sleep(100); + hr = IAMMultiMediaStream_SetState(ddrawstream_mmstream, ddrawstream_state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + return 0; +} + +static void test_ddrawstream_receive(void) +{ + ALLOCATOR_PROPERTIES properties = + { + .cBuffers = 1, + .cbBuffer = 16, + .cbAlign = 1, + }; + + IAMMultiMediaStream *mmstream = create_ammultimediastream(); + ALLOCATOR_PROPERTIES actual; + IMediaStreamFilter *filter; + struct testfilter source; + IMemAllocator *allocator; + IGraphBuilder *graph; + IMediaStream *stream; + IMediaSample *sample; + FILTER_STATE state; + HANDLE thread; + HRESULT hr; + ULONG ref; + IPin *pin; + + hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_GetFilter(mmstream, &filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!!filter, "Expected non-null filter.\n"); + hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(graph != NULL, "Expected non-NULL graph.\n"); + testfilter_init(&source); + hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)&allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_SetProperties(allocator, &properties, &actual); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb32_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemInputPin_Receive(source.source.pMemInputPin, sample); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = IMediaSample_Release(sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ddrawstream_mmstream = mmstream; + ddrawstream_state = STREAMSTATE_STOP; + thread = CreateThread(NULL, 0, ddrawstream_set_state, NULL, 0, NULL); + + hr = IMemInputPin_Receive(source.source.pMemInputPin, sample); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStreamFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Stopped, "Got state %#x.\n", state); + + ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n"); + CloseHandle(thread); + + ref = IMediaSample_Release(sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemInputPin_Receive(source.source.pMemInputPin, sample); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = IMediaSample_Release(sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + IGraphBuilder_Disconnect(graph, pin); + IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface); + + hr = IMemAllocator_Decommit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ref = IAMMultiMediaStream_Release(mmstream); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IGraphBuilder_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IMediaStreamFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IPin_Release(pin); + ref = IMediaStream_Release(stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IMemAllocator_Release(allocator); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); @@ -6880,6 +6997,7 @@ START_TEST(amstream) test_ddrawstream_create_sample(); test_ddrawstream_get_format(); test_ddrawstream_set_format(); + test_ddrawstream_receive();
test_ddrawstreamsample_get_media_stream();
On 9/23/20 1:54 PM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/ddrawstream.c | 25 ++++++- dlls/amstream/tests/amstream.c | 118 +++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index e706841c8fc..856c8775445 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -59,6 +59,7 @@ struct ddraw_stream struct format format; FILTER_STATE state; BOOL eos;
- HANDLE update_queued_event;
};
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, @@ -150,6 +151,7 @@ static ULONG WINAPI ddraw_IAMMediaStream_Release(IAMMediaStream *iface) DeleteCriticalSection(&stream->cs); if (stream->ddraw) IDirectDraw_Release(stream->ddraw);
}CloseHandle(stream->update_queued_event); HeapFree(GetProcessHeap(), 0, stream);
@@ -268,6 +270,8 @@ static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTE
EnterCriticalSection(&stream->cs);
- if (state == State_Stopped)
if (stream->state == State_Stopped) stream->eos = FALSE;SetEvent(stream->update_queued_event);
@@ -1190,8 +1194,24 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac
static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) {
- FIXME("iface %p, sample %p, stub!\n", iface, sample);
- return E_NOTIMPL;
- struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
- TRACE("stream %p, sample %p.\n", stream, sample);
- EnterCriticalSection(&stream->cs);
- for (;;)
- {
if (stream->state == State_Stopped)
{
LeaveCriticalSection(&stream->cs);
return S_OK;
}
LeaveCriticalSection(&stream->cs);
WaitForSingleObject(stream->update_queued_event, INFINITE);
EnterCriticalSection(&stream->cs);
- }
}
This is the sort of pattern that makes me think that a condition variable would be a good choice here.
On a sort of related note, the point of the event is not exactly clear with this patch. I think it may make sense to merge this patch with the next; the two functions are pretty tightly tied together.
static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface, @@ -1236,6 +1256,7 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) object->IMemInputPin_iface.lpVtbl = &ddraw_meminput_vtbl; object->IPin_iface.lpVtbl = &ddraw_sink_vtbl; object->ref = 1;
object->update_queued_event = CreateEventW(NULL, FALSE, FALSE, NULL);
object->format.width = 100; object->format.height = 100;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index df9d148493f..d0c20f6253a 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -5076,6 +5076,123 @@ static void test_ddrawstream_set_format(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static IAMMultiMediaStream *ddrawstream_mmstream; +static STREAM_STATE ddrawstream_state;
+static DWORD CALLBACK ddrawstream_set_state(void *param) +{
- HRESULT hr;
- Sleep(100);
- hr = IAMMultiMediaStream_SetState(ddrawstream_mmstream, ddrawstream_state);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- return 0;
+}
I'm inclined to think it makes things clearer to make Receive() asynchronous, since that's the thing that blocks. It also allows you to explicitly test that the function blocks, and to avoid the Sleep().
+static void test_ddrawstream_receive(void) +{
- ALLOCATOR_PROPERTIES properties =
- {
.cBuffers = 1,
.cbBuffer = 16,
.cbAlign = 1,
- };
- IAMMultiMediaStream *mmstream = create_ammultimediastream();
- ALLOCATOR_PROPERTIES actual;
- IMediaStreamFilter *filter;
- struct testfilter source;
- IMemAllocator *allocator;
- IGraphBuilder *graph;
- IMediaStream *stream;
- IMediaSample *sample;
- FILTER_STATE state;
- HANDLE thread;
- HRESULT hr;
- ULONG ref;
- IPin *pin;
- hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!!filter, "Expected non-null filter.\n");
- hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(graph != NULL, "Expected non-NULL graph.\n");
- testfilter_init(&source);
- hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)&allocator);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMemAllocator_SetProperties(allocator, &properties, &actual);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMemAllocator_Commit(allocator);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb32_mt);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ref = IMediaSample_Release(sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ddrawstream_mmstream = mmstream;
- ddrawstream_state = STREAMSTATE_STOP;
- thread = CreateThread(NULL, 0, ddrawstream_set_state, NULL, 0, NULL);
- hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStreamFilter_GetState(filter, 0, &state);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(state == State_Stopped, "Got state %#x.\n", state);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ref = IMediaSample_Release(sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- hr = IMemAllocator_Decommit(allocator);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ref = IAMMultiMediaStream_Release(mmstream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IGraphBuilder_Release(graph);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IMediaStreamFilter_Release(filter);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IPin_Release(pin);
- ref = IMediaStream_Release(stream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IMemAllocator_Release(allocator);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); @@ -6880,6 +6997,7 @@ START_TEST(amstream) test_ddrawstream_create_sample(); test_ddrawstream_get_format(); test_ddrawstream_set_format();
test_ddrawstream_receive();
test_ddrawstreamsample_get_media_stream();
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/ddrawstream.c | 167 ++++++++++++++-- dlls/amstream/tests/amstream.c | 342 ++++++++++++++++++++++++++++++--- 2 files changed, 470 insertions(+), 39 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 856c8775445..84f11d3758d 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -60,11 +60,73 @@ struct ddraw_stream FILTER_STATE state; BOOL eos; HANDLE update_queued_event; + struct list update_queue; +}; + +struct ddraw_sample +{ + IDirectDrawStreamSample IDirectDrawStreamSample_iface; + LONG ref; + struct ddraw_stream *parent; + IDirectDrawSurface *surface; + RECT rect; + HANDLE update_event; + + struct list entry; + HRESULT update_hr; };
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
+static void remove_queued_update(struct ddraw_sample *sample) +{ + list_remove(&sample->entry); + SetEvent(sample->update_event); +} + +static void flush_update_queue(struct ddraw_stream *stream, HRESULT update_hr) +{ + struct list *entry; + while ((entry = list_head(&stream->update_queue))) + { + struct ddraw_sample *sample = LIST_ENTRY(entry, struct ddraw_sample, entry); + sample->update_hr = update_hr; + remove_queued_update(sample); + } +} + +static HRESULT process_update(struct ddraw_sample *sample, int stride, BYTE *pointer) +{ + DDSURFACEDESC desc; + DWORD row_size; + const BYTE *src_row; + BYTE *dst_row; + DWORD row; + HRESULT hr; + + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface_Lock(sample->surface, &sample->rect, &desc, DDLOCK_WAIT, NULL); + if (FAILED(hr)) + return hr; + + row_size = (sample->rect.right - sample->rect.left) * desc.ddpfPixelFormat.u1.dwRGBBitCount >> 3; + src_row = pointer; + dst_row = desc.lpSurface; + for (row = sample->rect.top; row < sample->rect.bottom; ++row) + { + memcpy(dst_row, src_row, row_size); + src_row += stride; + dst_row += desc.u1.lPitch; + } + + hr = IDirectDrawSurface_Unlock(sample->surface, desc.lpSurface); + if (FAILED(hr)) + return hr; + + return S_OK; +} + static BOOL is_format_compatible(struct ddraw_stream *stream, DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf) { @@ -1083,6 +1145,8 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
stream->eos = TRUE;
+ flush_update_queue(stream, MS_S_ENDOFSTREAM); + LeaveCriticalSection(&stream->cs);
return S_OK; @@ -1195,11 +1259,30 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) { struct ddraw_stream *stream = impl_from_IMemInputPin(iface); + BITMAPINFOHEADER *bitmap_info; + BYTE *top_down_pointer; + int top_down_stride; + BYTE *pointer; + BOOL top_down; + int stride; + HRESULT hr;
TRACE("stream %p, sample %p.\n", stream, sample);
+ hr = IMediaSample_GetPointer(sample, &pointer); + if (FAILED(hr)) + return hr; + EnterCriticalSection(&stream->cs);
+ bitmap_info = &((VIDEOINFOHEADER *)stream->mt.pbFormat)->bmiHeader; + + stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) & ~31) >> 3; + top_down = (bitmap_info->biHeight < 0); + + top_down_stride = top_down ? stride : -stride; + top_down_pointer = top_down ? pointer : pointer + stride * (bitmap_info->biHeight - 1); + for (;;) { if (stream->state == State_Stopped) @@ -1207,6 +1290,16 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample * LeaveCriticalSection(&stream->cs); return S_OK; } + if (!list_empty(&stream->update_queue)) + { + struct ddraw_sample *sample = LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry); + + sample->update_hr = process_update(sample, top_down_stride, top_down_pointer); + + remove_queued_update(sample); + LeaveCriticalSection(&stream->cs); + return S_OK; + }
LeaveCriticalSection(&stream->cs); WaitForSingleObject(stream->update_queued_event, INFINITE); @@ -1262,6 +1355,7 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) object->format.height = 100;
InitializeCriticalSection(&object->cs); + list_init(&object->update_queue);
TRACE("Created ddraw stream %p.\n", object);
@@ -1270,15 +1364,6 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) return S_OK; }
-struct ddraw_sample -{ - IDirectDrawStreamSample IDirectDrawStreamSample_iface; - LONG ref; - struct ddraw_stream *parent; - IDirectDrawSurface *surface; - RECT rect; -}; - static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface) { return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface); @@ -1332,6 +1417,7 @@ static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)
if (sample->surface) IDirectDrawSurface_Release(sample->surface); + CloseHandle(sample->update_event); HeapFree(GetProcessHeap(), 0, sample); }
@@ -1370,12 +1456,66 @@ static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface return E_NOTIMPL; }
-static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event, - PAPCFUNC func_APC, DWORD APC_data) +static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, + DWORD flags, HANDLE event, PAPCFUNC apc_func, DWORD apc_data) { - FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC, APC_data); + struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
- return S_OK; + TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n", + sample, flags, event, apc_func, apc_data); + + if (event && apc_func) + return E_INVALIDARG; + + if (apc_func) + { + FIXME("APC support is not implemented!\n"); + return E_NOTIMPL; + } + + if (event) + { + FIXME("Event parameter support is not implemented!\n"); + return E_NOTIMPL; + } + + if (flags & ~SSUPDATE_ASYNC) + { + FIXME("Unsupported flags %#x.\n", flags); + return E_NOTIMPL; + } + + EnterCriticalSection(&sample->parent->cs); + + if (sample->parent->state != State_Running) + { + LeaveCriticalSection(&sample->parent->cs); + return MS_E_NOTRUNNING; + } + if (!sample->parent->peer || sample->parent->eos) + { + LeaveCriticalSection(&sample->parent->cs); + return MS_S_ENDOFSTREAM; + } + if (MS_S_PENDING == sample->update_hr) + { + LeaveCriticalSection(&sample->parent->cs); + return MS_E_BUSY; + } + + sample->update_hr = MS_S_PENDING; + ResetEvent(sample->update_event); + list_add_tail(&sample->parent->update_queue, &sample->entry); + SetEvent(sample->parent->update_queued_event); + + LeaveCriticalSection(&sample->parent->cs); + + if (flags & SSUPDATE_ASYNC) + return MS_S_PENDING; + + WaitForSingleObject(sample->update_event, INFINITE); + + return sample->update_hr; }
static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds) @@ -1445,6 +1585,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl; object->ref = 1; object->parent = parent; + object->update_event = CreateEventW(NULL, FALSE, FALSE, NULL); IAMMediaStream_AddRef(&parent->IAMMediaStream_iface); ++parent->sample_refs;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index d0c20f6253a..73d69452536 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3867,7 +3867,7 @@ static void test_audiostream_begin_flush_end_flush(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
-static IMediaSample *audiostream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) +static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) { IMediaSample *sample; BYTE *sample_data; @@ -3936,7 +3936,7 @@ static void test_audiostream_new_segment(void) hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5); + media_sample = ammediastream_allocate_sample(&source, test_data, 5); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time); @@ -3958,7 +3958,7 @@ static void test_audiostream_new_segment(void) hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5); + media_sample = ammediastream_allocate_sample(&source, test_data, 5); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time); @@ -4001,27 +4001,28 @@ static void CALLBACK apc_func(ULONG_PTR param) { }
-static IPin *audiostream_pin; -static IMemInputPin *audiostream_mem_input_pin; -static IMediaSample *audiostream_media_sample; +static IPin *ammediastream_pin; +static IMemInputPin *ammediastream_mem_input_pin; +static IMediaSample *ammediastream_media_sample; +static DWORD ammediastream_sleep_time;
-static DWORD CALLBACK audiostream_end_of_stream(void *param) +static DWORD CALLBACK ammediastream_end_of_stream(void *param) { HRESULT hr;
- Sleep(100); - hr = IPin_EndOfStream(audiostream_pin); + Sleep(ammediastream_sleep_time); + hr = IPin_EndOfStream(ammediastream_pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0; }
-static DWORD CALLBACK audiostream_receive(void *param) +static DWORD CALLBACK ammediastream_receive(void *param) { HRESULT hr;
- Sleep(100); - hr = IMemInputPin_Receive(audiostream_mem_input_pin, audiostream_media_sample); + Sleep(ammediastream_sleep_time); + hr = IMemInputPin_Receive(ammediastream_mem_input_pin, ammediastream_media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0; @@ -4102,7 +4103,7 @@ static void test_audiostreamsample_update(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 8); + media_sample1 = ammediastream_allocate_sample(&source, test_data, 8); hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample1); @@ -4120,7 +4121,7 @@ static void test_audiostreamsample_update(void) ref = get_refcount(media_sample1); ok(ref == 2, "Got unexpected refcount %d.\n", ref);
- media_sample2 = audiostream_allocate_sample(&source, test_data, 8); + media_sample2 = ammediastream_allocate_sample(&source, test_data, 8); hr = IMemInputPin_Receive(mem_input_pin, media_sample2); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample2); @@ -4162,7 +4163,7 @@ static void test_audiostreamsample_update(void) hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6); + media_sample1 = ammediastream_allocate_sample(&source, test_data, 6); hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample1); @@ -4176,11 +4177,12 @@ static void test_audiostreamsample_update(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6); + media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
- audiostream_mem_input_pin = mem_input_pin; - audiostream_media_sample = media_sample1; - thread = CreateThread(NULL, 0, audiostream_receive, NULL, 0, NULL); + ammediastream_mem_input_pin = mem_input_pin; + ammediastream_media_sample = media_sample1; + ammediastream_sleep_time = 100; + thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -4197,8 +4199,9 @@ static void test_audiostreamsample_update(void) ref = IMediaSample_Release(media_sample1); ok(!ref, "Got outstanding refcount %d.\n", ref);
- audiostream_pin = pin; - thread = CreateThread(NULL, 0, audiostream_end_of_stream, NULL, 0, NULL); + ammediastream_pin = pin; + ammediastream_sleep_time = 100; + thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr); @@ -4312,7 +4315,7 @@ void test_audiostreamsample_completion_status(void) hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6); + media_sample = ammediastream_allocate_sample(&source, test_data, 6); hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample); @@ -4327,7 +4330,7 @@ void test_audiostreamsample_completion_status(void) hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 12); + media_sample = ammediastream_allocate_sample(&source, test_data, 12); hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample); @@ -4365,7 +4368,7 @@ void test_audiostreamsample_completion_status(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6); + media_sample = ammediastream_allocate_sample(&source, test_data, 6); hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample); @@ -4506,7 +4509,7 @@ static void test_audiostreamsample_get_sample_times(void) ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
- media_sample = audiostream_allocate_sample(&source, test_data, 8); + media_sample = ammediastream_allocate_sample(&source, test_data, 8); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time); @@ -4525,7 +4528,7 @@ static void test_audiostreamsample_get_sample_times(void) ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 12347946, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
- media_sample = audiostream_allocate_sample(&source, test_data, 6); + media_sample = ammediastream_allocate_sample(&source, test_data, 6); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time); @@ -6946,6 +6949,292 @@ static void test_ddrawstreamsample_get_media_stream(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static void test_ddrawstreamsample_update(void) +{ + static const BYTE initial_data[] = + { + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + }; + static const BYTE test_data[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + }; + IAMMultiMediaStream *mmstream = create_ammultimediastream(); + IDirectDrawStreamSample *stream_sample; + IDirectDrawMediaStream *ddraw_stream; + IMediaControl *media_control; + IDirectDrawSurface *surface; + IMemInputPin *mem_input_pin; + IMediaSample *media_sample; + IMediaFilter *media_filter; + struct testfilter source; + IGraphBuilder *graph; + IMediaStream *stream; + VIDEOINFO video_info; + DDSURFACEDESC desc; + IDirectDraw *ddraw; + AM_MEDIA_TYPE mt; + HANDLE thread; + HANDLE event; + HRESULT hr; + ULONG ref; + IPin *pin; + RECT rect; + int i; + + hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(graph != NULL, "Expected non-NULL graph.\n"); + hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + testfilter_init(&source); + hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(event != NULL, "Expected non-NULL event."); + + hr = IMediaFilter_SetSyncSource(media_filter, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + desc = rgb24_format; + desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + desc.dwWidth = 4; + desc.dwHeight = 5; + desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + /* Make the rect width equal to the surface width, as the native + * implementation incorrectly handles rects that are not full-width + * when the ddraw stream's custom allocator is not used. */ + SetRect(&rect, 0, 1, 4, 3); + hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &stream_sample); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, event, apc_func, 0); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + video_info = rgb24_video_info; + video_info.bmiHeader.biWidth = 4; + video_info.bmiHeader.biHeight = -2; + mt = rgb24_mt; + mt.pbFormat = (BYTE *)&video_info; + hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + for (i = 0; i < 5; ++i) + memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data, 12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data)); + + ammediastream_mem_input_pin = mem_input_pin; + ammediastream_media_sample = media_sample; + ammediastream_sleep_time = 0; + thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL); + + Sleep(100); + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n"); + CloseHandle(thread); + + ref = IMediaSample_Release(media_sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IGraphBuilder_Disconnect(graph, pin); + IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface); + video_info = rgb24_video_info; + video_info.bmiHeader.biWidth = 4; + video_info.bmiHeader.biHeight = 2; + mt = rgb24_mt; + mt.pbFormat = (BYTE *)&video_info; + hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + for (i = 0; i < 5; ++i) + memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data, 12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data)); + + ammediastream_mem_input_pin = mem_input_pin; + ammediastream_media_sample = media_sample; + ammediastream_sleep_time = 0; + thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL); + + Sleep(100); + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n"); + CloseHandle(thread); + + ref = IMediaSample_Release(media_sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Pause(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + for (i = 0; i < 5; ++i) + memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data, 12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data)); + + ammediastream_mem_input_pin = mem_input_pin; + ammediastream_media_sample = media_sample; + ammediastream_sleep_time = 100; + thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n"); + CloseHandle(thread); + + ref = IMediaSample_Release(media_sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + ammediastream_pin = pin; + ammediastream_sleep_time = 100; + thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr); + + ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n"); + CloseHandle(thread); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0); + ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr); + EXPECT_REF(stream_sample, 1); + + hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0); + ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IGraphBuilder_Disconnect(graph, pin); + IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface); + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0); + ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + + CloseHandle(event); + ref = IDirectDrawStreamSample_Release(stream_sample); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IDirectDrawSurface_Release(surface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IAMMultiMediaStream_Release(mmstream); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IMediaControl_Release(media_control); + IMediaFilter_Release(media_filter); + ref = IGraphBuilder_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IPin_Release(pin); + IMemInputPin_Release(mem_input_pin); + IDirectDrawMediaStream_Release(ddraw_stream); + ref = IMediaStream_Release(stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IDirectDraw_Release(ddraw); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + START_TEST(amstream) { const WCHAR *test_avi_path; @@ -7000,6 +7289,7 @@ START_TEST(amstream) test_ddrawstream_receive();
test_ddrawstreamsample_get_media_stream(); + test_ddrawstreamsample_update();
test_ammediastream_join_am_multi_media_stream(); test_ammediastream_join_filter();
Just a few nitpicks here...
On 9/23/20 1:55 PM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/ddrawstream.c | 167 ++++++++++++++-- dlls/amstream/tests/amstream.c | 342 ++++++++++++++++++++++++++++++--- 2 files changed, 470 insertions(+), 39 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 856c8775445..84f11d3758d 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -60,11 +60,73 @@ struct ddraw_stream FILTER_STATE state; BOOL eos; HANDLE update_queued_event;
- struct list update_queue;
+};
+struct ddraw_sample +{
- IDirectDrawStreamSample IDirectDrawStreamSample_iface;
- LONG ref;
- struct ddraw_stream *parent;
- IDirectDrawSurface *surface;
- RECT rect;
- HANDLE update_event;
- struct list entry;
- HRESULT update_hr;
};
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
+static void remove_queued_update(struct ddraw_sample *sample) +{
- list_remove(&sample->entry);
- SetEvent(sample->update_event);
+}
+static void flush_update_queue(struct ddraw_stream *stream, HRESULT update_hr) +{
- struct list *entry;
- while ((entry = list_head(&stream->update_queue)))
- {
struct ddraw_sample *sample = LIST_ENTRY(entry, struct ddraw_sample, entry);
sample->update_hr = update_hr;
remove_queued_update(sample);
- }
+}
+static HRESULT process_update(struct ddraw_sample *sample, int stride, BYTE *pointer) +{
- DDSURFACEDESC desc;
- DWORD row_size;
- const BYTE *src_row;
- BYTE *dst_row;
- DWORD row;
- HRESULT hr;
- desc.dwSize = sizeof(desc);
- hr = IDirectDrawSurface_Lock(sample->surface, &sample->rect, &desc, DDLOCK_WAIT, NULL);
- if (FAILED(hr))
return hr;
- row_size = (sample->rect.right - sample->rect.left) * desc.ddpfPixelFormat.u1.dwRGBBitCount >> 3;
"/ 8" is clearer and should compile to the same thing.
- src_row = pointer;
- dst_row = desc.lpSurface;
- for (row = sample->rect.top; row < sample->rect.bottom; ++row)
- {
memcpy(dst_row, src_row, row_size);
src_row += stride;
dst_row += desc.u1.lPitch;
- }
- hr = IDirectDrawSurface_Unlock(sample->surface, desc.lpSurface);
- if (FAILED(hr))
return hr;
- return S_OK;
+}
static BOOL is_format_compatible(struct ddraw_stream *stream, DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf) { @@ -1083,6 +1145,8 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
stream->eos = TRUE;
flush_update_queue(stream, MS_S_ENDOFSTREAM);
LeaveCriticalSection(&stream->cs);
return S_OK;
@@ -1195,11 +1259,30 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) { struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
BITMAPINFOHEADER *bitmap_info;
BYTE *top_down_pointer;
int top_down_stride;
BYTE *pointer;
BOOL top_down;
int stride;
HRESULT hr;
TRACE("stream %p, sample %p.\n", stream, sample);
hr = IMediaSample_GetPointer(sample, &pointer);
if (FAILED(hr))
return hr;
EnterCriticalSection(&stream->cs);
bitmap_info = &((VIDEOINFOHEADER *)stream->mt.pbFormat)->bmiHeader;
stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) & ~31) >> 3;
Same here.
- top_down = (bitmap_info->biHeight < 0);
- top_down_stride = top_down ? stride : -stride;
- top_down_pointer = top_down ? pointer : pointer + stride * (bitmap_info->biHeight - 1);
- for (;;) { if (stream->state == State_Stopped)
@@ -1207,6 +1290,16 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample * LeaveCriticalSection(&stream->cs); return S_OK; }
if (!list_empty(&stream->update_queue))
{
struct ddraw_sample *sample = LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry);
sample->update_hr = process_update(sample, top_down_stride, top_down_pointer);
remove_queued_update(sample);
LeaveCriticalSection(&stream->cs);
return S_OK;
} LeaveCriticalSection(&stream->cs); WaitForSingleObject(stream->update_queued_event, INFINITE);
@@ -1262,6 +1355,7 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) object->format.height = 100;
InitializeCriticalSection(&object->cs);
list_init(&object->update_queue);
TRACE("Created ddraw stream %p.\n", object);
@@ -1270,15 +1364,6 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) return S_OK; }
-struct ddraw_sample -{
- IDirectDrawStreamSample IDirectDrawStreamSample_iface;
- LONG ref;
- struct ddraw_stream *parent;
- IDirectDrawSurface *surface;
- RECT rect;
-};
static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface) { return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface); @@ -1332,6 +1417,7 @@ static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)
if (sample->surface) IDirectDrawSurface_Release(sample->surface);
}CloseHandle(sample->update_event); HeapFree(GetProcessHeap(), 0, sample);
@@ -1370,12 +1456,66 @@ static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface return E_NOTIMPL; }
-static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event,
PAPCFUNC func_APC, DWORD APC_data)
+static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface,
DWORD flags, HANDLE event, PAPCFUNC apc_func, DWORD apc_data)
{
- FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC, APC_data);
- struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
- return S_OK;
- TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n",
sample, flags, event, apc_func, apc_data);
- if (event && apc_func)
return E_INVALIDARG;
- if (apc_func)
- {
FIXME("APC support is not implemented!\n");
return E_NOTIMPL;
- }
- if (event)
- {
FIXME("Event parameter support is not implemented!\n");
return E_NOTIMPL;
- }
- if (flags & ~SSUPDATE_ASYNC)
- {
FIXME("Unsupported flags %#x.\n", flags);
return E_NOTIMPL;
- }
- EnterCriticalSection(&sample->parent->cs);
- if (sample->parent->state != State_Running)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_E_NOTRUNNING;
- }
- if (!sample->parent->peer || sample->parent->eos)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_S_ENDOFSTREAM;
- }
- if (MS_S_PENDING == sample->update_hr)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_E_BUSY;
- }
- sample->update_hr = MS_S_PENDING;
- ResetEvent(sample->update_event);
- list_add_tail(&sample->parent->update_queue, &sample->entry);
- SetEvent(sample->parent->update_queued_event);
- LeaveCriticalSection(&sample->parent->cs);
- if (flags & SSUPDATE_ASYNC)
return MS_S_PENDING;
- WaitForSingleObject(sample->update_event, INFINITE);
- return sample->update_hr;
}
static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds) @@ -1445,6 +1585,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl; object->ref = 1; object->parent = parent;
- object->update_event = CreateEventW(NULL, FALSE, FALSE, NULL); IAMMediaStream_AddRef(&parent->IAMMediaStream_iface); ++parent->sample_refs;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index d0c20f6253a..73d69452536 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3867,7 +3867,7 @@ static void test_audiostream_begin_flush_end_flush(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
-static IMediaSample *audiostream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) +static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) { IMediaSample *sample; BYTE *sample_data; @@ -3936,7 +3936,7 @@ static void test_audiostream_new_segment(void) hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5);
- media_sample = ammediastream_allocate_sample(&source, test_data, 5); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -3958,7 +3958,7 @@ static void test_audiostream_new_segment(void) hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5);
- media_sample = ammediastream_allocate_sample(&source, test_data, 5); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -4001,27 +4001,28 @@ static void CALLBACK apc_func(ULONG_PTR param) { }
-static IPin *audiostream_pin; -static IMemInputPin *audiostream_mem_input_pin; -static IMediaSample *audiostream_media_sample; +static IPin *ammediastream_pin; +static IMemInputPin *ammediastream_mem_input_pin; +static IMediaSample *ammediastream_media_sample; +static DWORD ammediastream_sleep_time;
-static DWORD CALLBACK audiostream_end_of_stream(void *param) +static DWORD CALLBACK ammediastream_end_of_stream(void *param) { HRESULT hr;
- Sleep(100);
- hr = IPin_EndOfStream(audiostream_pin);
Sleep(ammediastream_sleep_time);
hr = IPin_EndOfStream(ammediastream_pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0;
}
-static DWORD CALLBACK audiostream_receive(void *param) +static DWORD CALLBACK ammediastream_receive(void *param) { HRESULT hr;
- Sleep(100);
- hr = IMemInputPin_Receive(audiostream_mem_input_pin, audiostream_media_sample);
Sleep(ammediastream_sleep_time);
hr = IMemInputPin_Receive(ammediastream_mem_input_pin, ammediastream_media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0;
@@ -4102,7 +4103,7 @@ static void test_audiostreamsample_update(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 8);
- media_sample1 = ammediastream_allocate_sample(&source, test_data, 8); hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample1);
@@ -4120,7 +4121,7 @@ static void test_audiostreamsample_update(void) ref = get_refcount(media_sample1); ok(ref == 2, "Got unexpected refcount %d.\n", ref);
- media_sample2 = audiostream_allocate_sample(&source, test_data, 8);
- media_sample2 = ammediastream_allocate_sample(&source, test_data, 8); hr = IMemInputPin_Receive(mem_input_pin, media_sample2); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample2);
@@ -4162,7 +4163,7 @@ static void test_audiostreamsample_update(void) hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6);
- media_sample1 = ammediastream_allocate_sample(&source, test_data, 6); hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample1);
@@ -4176,11 +4177,12 @@ static void test_audiostreamsample_update(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6);
- media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
- audiostream_mem_input_pin = mem_input_pin;
- audiostream_media_sample = media_sample1;
- thread = CreateThread(NULL, 0, audiostream_receive, NULL, 0, NULL);
ammediastream_mem_input_pin = mem_input_pin;
ammediastream_media_sample = media_sample1;
ammediastream_sleep_time = 100;
thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -4197,8 +4199,9 @@ static void test_audiostreamsample_update(void) ref = IMediaSample_Release(media_sample1); ok(!ref, "Got outstanding refcount %d.\n", ref);
- audiostream_pin = pin;
- thread = CreateThread(NULL, 0, audiostream_end_of_stream, NULL, 0, NULL);
ammediastream_pin = pin;
ammediastream_sleep_time = 100;
thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
@@ -4312,7 +4315,7 @@ void test_audiostreamsample_completion_status(void) hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
- media_sample = ammediastream_allocate_sample(&source, test_data, 6); hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4327,7 +4330,7 @@ void test_audiostreamsample_completion_status(void) hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 12);
- media_sample = ammediastream_allocate_sample(&source, test_data, 12); hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4365,7 +4368,7 @@ void test_audiostreamsample_completion_status(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
- media_sample = ammediastream_allocate_sample(&source, test_data, 6); hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4506,7 +4509,7 @@ static void test_audiostreamsample_get_sample_times(void) ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
- media_sample = audiostream_allocate_sample(&source, test_data, 8);
- media_sample = ammediastream_allocate_sample(&source, test_data, 8); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -4525,7 +4528,7 @@ static void test_audiostreamsample_get_sample_times(void) ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 12347946, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
- media_sample = ammediastream_allocate_sample(&source, test_data, 6); start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -6946,6 +6949,292 @@ static void test_ddrawstreamsample_get_media_stream(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static void test_ddrawstreamsample_update(void) +{
- static const BYTE initial_data[] =
- {
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
- };
- static const BYTE test_data[] =
- {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- };
- IAMMultiMediaStream *mmstream = create_ammultimediastream();
- IDirectDrawStreamSample *stream_sample;
- IDirectDrawMediaStream *ddraw_stream;
- IMediaControl *media_control;
- IDirectDrawSurface *surface;
- IMemInputPin *mem_input_pin;
- IMediaSample *media_sample;
- IMediaFilter *media_filter;
- struct testfilter source;
- IGraphBuilder *graph;
- IMediaStream *stream;
- VIDEOINFO video_info;
- DDSURFACEDESC desc;
- IDirectDraw *ddraw;
- AM_MEDIA_TYPE mt;
- HANDLE thread;
- HANDLE event;
- HRESULT hr;
- ULONG ref;
- IPin *pin;
- RECT rect;
- int i;
- hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(graph != NULL, "Expected non-NULL graph.\n");
- hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- testfilter_init(&source);
- hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- event = CreateEventW(NULL, FALSE, FALSE, NULL);
- ok(event != NULL, "Expected non-NULL event.");
- hr = IMediaFilter_SetSyncSource(media_filter, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- desc = rgb24_format;
- desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
- desc.dwWidth = 4;
- desc.dwHeight = 5;
- desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
- hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- /* Make the rect width equal to the surface width, as the native
* implementation incorrectly handles rects that are not full-width
* when the ddraw stream's custom allocator is not used. */
- SetRect(&rect, 0, 1, 4, 3);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &stream_sample);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, event, apc_func, 0);
- ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- video_info = rgb24_video_info;
- video_info.bmiHeader.biWidth = 4;
- video_info.bmiHeader.biHeight = -2;
- mt = rgb24_mt;
- mt.pbFormat = (BYTE *)&video_info;
- hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data, 12);
- hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 0;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- Sleep(100);
You're not using SSUPDATE_ASYNC, so you can get rid of the Sleep() call here, right?
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- video_info = rgb24_video_info;
- video_info.bmiHeader.biWidth = 4;
- video_info.bmiHeader.biHeight = 2;
- mt = rgb24_mt;
- mt.pbFormat = (BYTE *)&video_info;
- hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data, 12);
- hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 0;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- Sleep(100);
And here.
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IPin_EndOfStream(pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaControl_Pause(media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
- hr = IMediaControl_Stop(media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data, 12);
- hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
- hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ammediastream_pin = pin;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
- ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- EXPECT_REF(stream_sample, 1);
- hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
- ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
hr isn't checked here (though omitting the call or assignment is also fine, I think.)
- CloseHandle(event);
- ref = IDirectDrawStreamSample_Release(stream_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDrawSurface_Release(surface);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IAMMultiMediaStream_Release(mmstream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IMediaControl_Release(media_control);
- IMediaFilter_Release(media_filter);
- ref = IGraphBuilder_Release(graph);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IPin_Release(pin);
- IMemInputPin_Release(mem_input_pin);
- IDirectDrawMediaStream_Release(ddraw_stream);
- ref = IMediaStream_Release(stream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDraw_Release(ddraw);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
START_TEST(amstream) { const WCHAR *test_avi_path; @@ -7000,6 +7289,7 @@ START_TEST(amstream) test_ddrawstream_receive();
test_ddrawstreamsample_get_media_stream();
test_ddrawstreamsample_update();
test_ammediastream_join_am_multi_media_stream(); test_ammediastream_join_filter();
On Thursday, 24 September 2020 03:37:41 +07 you wrote:
Just a few nitpicks here...
On 9/23/20 1:55 PM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/ddrawstream.c | 167 ++++++++++++++-- dlls/amstream/tests/amstream.c | 342 ++++++++++++++++++++++++++++++--- 2 files changed, 470 insertions(+), 39 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 856c8775445..84f11d3758d 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -60,11 +60,73 @@ struct ddraw_stream
FILTER_STATE state; BOOL eos; HANDLE update_queued_event;
- struct list update_queue;
+};
+struct ddraw_sample +{
- IDirectDrawStreamSample IDirectDrawStreamSample_iface;
- LONG ref;
- struct ddraw_stream *parent;
- IDirectDrawSurface *surface;
- RECT rect;
- HANDLE update_event;
- struct list entry;
- HRESULT update_hr;
};
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,> const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
+static void remove_queued_update(struct ddraw_sample *sample) +{
- list_remove(&sample->entry);
- SetEvent(sample->update_event);
+}
+static void flush_update_queue(struct ddraw_stream *stream, HRESULT update_hr) +{
- struct list *entry;
- while ((entry = list_head(&stream->update_queue)))
- {
struct ddraw_sample *sample = LIST_ENTRY(entry, struct
ddraw_sample, entry); + sample->update_hr = update_hr;
remove_queued_update(sample);
- }
+}
+static HRESULT process_update(struct ddraw_sample *sample, int stride, BYTE *pointer) +{
- DDSURFACEDESC desc;
- DWORD row_size;
- const BYTE *src_row;
- BYTE *dst_row;
- DWORD row;
- HRESULT hr;
- desc.dwSize = sizeof(desc);
- hr = IDirectDrawSurface_Lock(sample->surface, &sample->rect, &desc,
DDLOCK_WAIT, NULL); + if (FAILED(hr))
return hr;
- row_size = (sample->rect.right - sample->rect.left) *
desc.ddpfPixelFormat.u1.dwRGBBitCount >> 3;
"/ 8" is clearer and should compile to the same thing.
- src_row = pointer;
- dst_row = desc.lpSurface;
- for (row = sample->rect.top; row < sample->rect.bottom; ++row)
- {
memcpy(dst_row, src_row, row_size);
src_row += stride;
dst_row += desc.u1.lPitch;
- }
- hr = IDirectDrawSurface_Unlock(sample->surface, desc.lpSurface);
- if (FAILED(hr))
return hr;
- return S_OK;
+}
static BOOL is_format_compatible(struct ddraw_stream *stream,
DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf)
{
@@ -1083,6 +1145,8 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)> stream->eos = TRUE;
flush_update_queue(stream, MS_S_ENDOFSTREAM);
LeaveCriticalSection(&stream->cs);
return S_OK;
@@ -1195,11 +1259,30 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac> static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) {
struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
BITMAPINFOHEADER *bitmap_info;
BYTE *top_down_pointer;
int top_down_stride;
BYTE *pointer;
BOOL top_down;
int stride;
HRESULT hr;
TRACE("stream %p, sample %p.\n", stream, sample);
hr = IMediaSample_GetPointer(sample, &pointer);
if (FAILED(hr))
return hr;
EnterCriticalSection(&stream->cs);
bitmap_info = &((VIDEOINFOHEADER *)stream->mt.pbFormat)->bmiHeader;
stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) &
~31) >> 3;
Same here.
- top_down = (bitmap_info->biHeight < 0);
- top_down_stride = top_down ? stride : -stride;
- top_down_pointer = top_down ? pointer : pointer + stride *
(bitmap_info->biHeight - 1); +
for (;;) { if (stream->state == State_Stopped)
@@ -1207,6 +1290,16 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *> LeaveCriticalSection(&stream->cs); return S_OK;
}
if (!list_empty(&stream->update_queue))
{
struct ddraw_sample *sample =
LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry);
sample->update_hr = process_update(sample, top_down_stride,
top_down_pointer); +
remove_queued_update(sample);
LeaveCriticalSection(&stream->cs);
return S_OK;
} LeaveCriticalSection(&stream->cs); WaitForSingleObject(stream->update_queued_event, INFINITE);
@@ -1262,6 +1355,7 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)> object->format.height = 100;
InitializeCriticalSection(&object->cs);
list_init(&object->update_queue);
TRACE("Created ddraw stream %p.\n", object);
@@ -1270,15 +1364,6 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)> return S_OK;
}
-struct ddraw_sample -{
- IDirectDrawStreamSample IDirectDrawStreamSample_iface;
- LONG ref;
- struct ddraw_stream *parent;
- IDirectDrawSurface *surface;
- RECT rect;
-};
static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface) {
return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface);>
@@ -1332,6 +1417,7 @@ static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)> if (sample->surface)
IDirectDrawSurface_Release(sample->surface);
CloseHandle(sample->update_event); HeapFree(GetProcessHeap(), 0, sample);
}
@@ -1370,12 +1456,66 @@ static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface> return E_NOTIMPL;
}
-static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event, - PAPCFUNC func_APC, DWORD APC_data) +static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, + DWORD flags, HANDLE event, PAPCFUNC apc_func, DWORD apc_data)> {
- FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC,
APC_data); + struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
- return S_OK;
- TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n",
sample, flags, event, apc_func, apc_data);
- if (event && apc_func)
return E_INVALIDARG;
- if (apc_func)
- {
FIXME("APC support is not implemented!\n");
return E_NOTIMPL;
- }
- if (event)
- {
FIXME("Event parameter support is not implemented!\n");
return E_NOTIMPL;
- }
- if (flags & ~SSUPDATE_ASYNC)
- {
FIXME("Unsupported flags %#x.\n", flags);
return E_NOTIMPL;
- }
- EnterCriticalSection(&sample->parent->cs);
- if (sample->parent->state != State_Running)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_E_NOTRUNNING;
- }
- if (!sample->parent->peer || sample->parent->eos)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_S_ENDOFSTREAM;
- }
- if (MS_S_PENDING == sample->update_hr)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_E_BUSY;
- }
- sample->update_hr = MS_S_PENDING;
- ResetEvent(sample->update_event);
- list_add_tail(&sample->parent->update_queue, &sample->entry);
- SetEvent(sample->parent->update_queued_event);
- LeaveCriticalSection(&sample->parent->cs);
- if (flags & SSUPDATE_ASYNC)
return MS_S_PENDING;
- WaitForSingleObject(sample->update_event, INFINITE);
- return sample->update_hr;
}
static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)> @@ -1445,6 +1585,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw> object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl; object->ref = 1; object->parent = parent;
object->update_event = CreateEventW(NULL, FALSE, FALSE, NULL);
IAMMediaStream_AddRef(&parent->IAMMediaStream_iface); ++parent->sample_refs;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index d0c20f6253a..73d69452536 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3867,7 +3867,7 @@ static void test_audiostream_begin_flush_end_flush(void)> ok(!ref, "Got outstanding refcount %d.\n", ref);
}
-static IMediaSample *audiostream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) +static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length)> {
IMediaSample *sample; BYTE *sample_data;
@@ -3936,7 +3936,7 @@ static void test_audiostream_new_segment(void)
hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5);
media_sample = ammediastream_allocate_sample(&source, test_data, 5);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -3958,7 +3958,7 @@ static void test_audiostream_new_segment(void)
hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5);
media_sample = ammediastream_allocate_sample(&source, test_data, 5);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -4001,27 +4001,28 @@ static void CALLBACK apc_func(ULONG_PTR param)
{ }
-static IPin *audiostream_pin; -static IMemInputPin *audiostream_mem_input_pin; -static IMediaSample *audiostream_media_sample; +static IPin *ammediastream_pin; +static IMemInputPin *ammediastream_mem_input_pin; +static IMediaSample *ammediastream_media_sample; +static DWORD ammediastream_sleep_time;
-static DWORD CALLBACK audiostream_end_of_stream(void *param) +static DWORD CALLBACK ammediastream_end_of_stream(void *param)
{
HRESULT hr;
- Sleep(100);
- hr = IPin_EndOfStream(audiostream_pin);
Sleep(ammediastream_sleep_time);
hr = IPin_EndOfStream(ammediastream_pin);
ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0;
}
-static DWORD CALLBACK audiostream_receive(void *param) +static DWORD CALLBACK ammediastream_receive(void *param)
{
HRESULT hr;
- Sleep(100);
- hr = IMemInputPin_Receive(audiostream_mem_input_pin,
audiostream_media_sample); + Sleep(ammediastream_sleep_time);
- hr = IMemInputPin_Receive(ammediastream_mem_input_pin,
ammediastream_media_sample);> ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0;
@@ -4102,7 +4103,7 @@ static void test_audiostreamsample_update(void)
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 8);
media_sample1 = ammediastream_allocate_sample(&source, test_data, 8);
hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample1);
@@ -4120,7 +4121,7 @@ static void test_audiostreamsample_update(void)
ref = get_refcount(media_sample1); ok(ref == 2, "Got unexpected refcount %d.\n", ref);
- media_sample2 = audiostream_allocate_sample(&source, test_data, 8);
media_sample2 = ammediastream_allocate_sample(&source, test_data, 8);
hr = IMemInputPin_Receive(mem_input_pin, media_sample2); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample2);
@@ -4162,7 +4163,7 @@ static void test_audiostreamsample_update(void)
hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6);
media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample1);
@@ -4176,11 +4177,12 @@ static void test_audiostreamsample_update(void)
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6);
- media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
- audiostream_mem_input_pin = mem_input_pin;
- audiostream_media_sample = media_sample1;
- thread = CreateThread(NULL, 0, audiostream_receive, NULL, 0, NULL);
ammediastream_mem_input_pin = mem_input_pin;
ammediastream_media_sample = media_sample1;
ammediastream_sleep_time = 100;
thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -4197,8 +4199,9 @@ static void test_audiostreamsample_update(void)
ref = IMediaSample_Release(media_sample1); ok(!ref, "Got outstanding refcount %d.\n", ref);
- audiostream_pin = pin;
- thread = CreateThread(NULL, 0, audiostream_end_of_stream, NULL, 0,
NULL); + ammediastream_pin = pin;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0,
NULL);> hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
@@ -4312,7 +4315,7 @@ void test_audiostreamsample_completion_status(void)
hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
media_sample = ammediastream_allocate_sample(&source, test_data, 6);
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4327,7 +4330,7 @@ void test_audiostreamsample_completion_status(void)
hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 12);
media_sample = ammediastream_allocate_sample(&source, test_data, 12);
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4365,7 +4368,7 @@ void test_audiostreamsample_completion_status(void)
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
media_sample = ammediastream_allocate_sample(&source, test_data, 6);
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4506,7 +4509,7 @@ static void test_audiostreamsample_get_sample_times(void)> ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));>
- media_sample = audiostream_allocate_sample(&source, test_data, 8);
media_sample = ammediastream_allocate_sample(&source, test_data, 8);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -4525,7 +4528,7 @@ static void test_audiostreamsample_get_sample_times(void)> ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 12347946, "Got end time %s.\n", wine_dbgstr_longlong(end_time));>
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
media_sample = ammediastream_allocate_sample(&source, test_data, 6);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -6946,6 +6949,292 @@ static void test_ddrawstreamsample_get_media_stream(void)> ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_ddrawstreamsample_update(void) +{
- static const BYTE initial_data[] =
- {
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
0xef, + };
- static const BYTE test_data[] =
- {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- };
- IAMMultiMediaStream *mmstream = create_ammultimediastream();
- IDirectDrawStreamSample *stream_sample;
- IDirectDrawMediaStream *ddraw_stream;
- IMediaControl *media_control;
- IDirectDrawSurface *surface;
- IMemInputPin *mem_input_pin;
- IMediaSample *media_sample;
- IMediaFilter *media_filter;
- struct testfilter source;
- IGraphBuilder *graph;
- IMediaStream *stream;
- VIDEOINFO video_info;
- DDSURFACEDESC desc;
- IDirectDraw *ddraw;
- AM_MEDIA_TYPE mt;
- HANDLE thread;
- HANDLE event;
- HRESULT hr;
- ULONG ref;
- IPin *pin;
- RECT rect;
- int i;
- hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0,
NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL,
&MSPID_PrimaryVideo, 0, &stream); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream,
(void **)&ddraw_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void
**)&mem_input_pin); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(graph != NULL, "Expected non-NULL graph.\n");
- hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void
**)&media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void
**)&media_filter); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- testfilter_init(&source);
- hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface,
NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- event = CreateEventW(NULL, FALSE, FALSE, NULL);
- ok(event != NULL, "Expected non-NULL event.");
- hr = IMediaFilter_SetSyncSource(media_filter, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- desc = rgb24_format;
- desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
- desc.dwWidth = 4;
- desc.dwHeight = 5;
- desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
- hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- /* Make the rect width equal to the surface width, as the native
* implementation incorrectly handles rects that are not full-width
* when the ddraw stream's custom allocator is not used. */
- SetRect(&rect, 0, 1, 4, 3);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface,
&rect, 0, &stream_sample); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, event,
apc_func, 0); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- video_info = rgb24_video_info;
- video_info.bmiHeader.biWidth = 4;
- video_info.bmiHeader.biHeight = -2;
- mt = rgb24_mt;
- mt.pbFormat = (BYTE *)&video_info;
- hr = IGraphBuilder_ConnectDirect(graph,
&source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data,
12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data,
sizeof(test_data)); +
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 0;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- Sleep(100);
You're not using SSUPDATE_ASYNC, so you can get rid of the Sleep() call here, right?
This test exercises the code path where Receive() has to wait for an update to be queued. I added the Sleep() call so that the thread has a chance to enter the Receive() function before Update() is called.
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12)
== 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- video_info = rgb24_video_info;
- video_info.bmiHeader.biWidth = 4;
- video_info.bmiHeader.biHeight = 2;
- mt = rgb24_mt;
- mt.pbFormat = (BYTE *)&video_info;
- hr = IGraphBuilder_ConnectDirect(graph,
&source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data,
12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data,
sizeof(test_data)); +
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 0;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- Sleep(100);
And here.
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12)
== 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface
- 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't
match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IPin_EndOfStream(pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaControl_Pause(media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
- hr = IMediaControl_Stop(media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data,
12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data,
sizeof(test_data)); +
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12)
== 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface
- 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't
match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ammediastream_pin = pin;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0,
NULL); +
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC,
NULL, NULL, 0); + ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- EXPECT_REF(stream_sample, 1);
- hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC,
NULL, NULL, 0); + ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
hr isn't checked here (though omitting the call or assignment is also fine, I think.)
- CloseHandle(event);
- ref = IDirectDrawStreamSample_Release(stream_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDrawSurface_Release(surface);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IAMMultiMediaStream_Release(mmstream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IMediaControl_Release(media_control);
- IMediaFilter_Release(media_filter);
- ref = IGraphBuilder_Release(graph);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IPin_Release(pin);
- IMemInputPin_Release(mem_input_pin);
- IDirectDrawMediaStream_Release(ddraw_stream);
- ref = IMediaStream_Release(stream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDraw_Release(ddraw);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
START_TEST(amstream) {
const WCHAR *test_avi_path;
@@ -7000,6 +7289,7 @@ START_TEST(amstream)
test_ddrawstream_receive(); test_ddrawstreamsample_get_media_stream();
test_ddrawstreamsample_update();
test_ammediastream_join_am_multi_media_stream(); test_ammediastream_join_filter();
On 9/24/20 2:07 PM, Anton Baskanov wrote:
On Thursday, 24 September 2020 03:37:41 +07 you wrote:
Just a few nitpicks here...
On 9/23/20 1:55 PM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/ddrawstream.c | 167 ++++++++++++++-- dlls/amstream/tests/amstream.c | 342 ++++++++++++++++++++++++++++++--- 2 files changed, 470 insertions(+), 39 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 856c8775445..84f11d3758d 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -60,11 +60,73 @@ struct ddraw_stream
FILTER_STATE state; BOOL eos; HANDLE update_queued_event;
- struct list update_queue;
+};
+struct ddraw_sample +{
- IDirectDrawStreamSample IDirectDrawStreamSample_iface;
- LONG ref;
- struct ddraw_stream *parent;
- IDirectDrawSurface *surface;
- RECT rect;
- HANDLE update_event;
- struct list entry;
- HRESULT update_hr;
};
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,> const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
+static void remove_queued_update(struct ddraw_sample *sample) +{
- list_remove(&sample->entry);
- SetEvent(sample->update_event);
+}
+static void flush_update_queue(struct ddraw_stream *stream, HRESULT update_hr) +{
- struct list *entry;
- while ((entry = list_head(&stream->update_queue)))
- {
struct ddraw_sample *sample = LIST_ENTRY(entry, struct
ddraw_sample, entry); + sample->update_hr = update_hr;
remove_queued_update(sample);
- }
+}
+static HRESULT process_update(struct ddraw_sample *sample, int stride, BYTE *pointer) +{
- DDSURFACEDESC desc;
- DWORD row_size;
- const BYTE *src_row;
- BYTE *dst_row;
- DWORD row;
- HRESULT hr;
- desc.dwSize = sizeof(desc);
- hr = IDirectDrawSurface_Lock(sample->surface, &sample->rect, &desc,
DDLOCK_WAIT, NULL); + if (FAILED(hr))
return hr;
- row_size = (sample->rect.right - sample->rect.left) *
desc.ddpfPixelFormat.u1.dwRGBBitCount >> 3;
"/ 8" is clearer and should compile to the same thing.
- src_row = pointer;
- dst_row = desc.lpSurface;
- for (row = sample->rect.top; row < sample->rect.bottom; ++row)
- {
memcpy(dst_row, src_row, row_size);
src_row += stride;
dst_row += desc.u1.lPitch;
- }
- hr = IDirectDrawSurface_Unlock(sample->surface, desc.lpSurface);
- if (FAILED(hr))
return hr;
- return S_OK;
+}
static BOOL is_format_compatible(struct ddraw_stream *stream,
DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf)
{
@@ -1083,6 +1145,8 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)> stream->eos = TRUE;
flush_update_queue(stream, MS_S_ENDOFSTREAM);
LeaveCriticalSection(&stream->cs);
return S_OK;
@@ -1195,11 +1259,30 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac> static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) {
struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
BITMAPINFOHEADER *bitmap_info;
BYTE *top_down_pointer;
int top_down_stride;
BYTE *pointer;
BOOL top_down;
int stride;
HRESULT hr;
TRACE("stream %p, sample %p.\n", stream, sample);
hr = IMediaSample_GetPointer(sample, &pointer);
if (FAILED(hr))
return hr;
EnterCriticalSection(&stream->cs);
bitmap_info = &((VIDEOINFOHEADER *)stream->mt.pbFormat)->bmiHeader;
stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) &
~31) >> 3;
Same here.
- top_down = (bitmap_info->biHeight < 0);
- top_down_stride = top_down ? stride : -stride;
- top_down_pointer = top_down ? pointer : pointer + stride *
(bitmap_info->biHeight - 1); +
for (;;) { if (stream->state == State_Stopped)
@@ -1207,6 +1290,16 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *> LeaveCriticalSection(&stream->cs); return S_OK;
}
if (!list_empty(&stream->update_queue))
{
struct ddraw_sample *sample =
LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry);
sample->update_hr = process_update(sample, top_down_stride,
top_down_pointer); +
remove_queued_update(sample);
LeaveCriticalSection(&stream->cs);
return S_OK;
} LeaveCriticalSection(&stream->cs); WaitForSingleObject(stream->update_queued_event, INFINITE);
@@ -1262,6 +1355,7 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)> object->format.height = 100;
InitializeCriticalSection(&object->cs);
list_init(&object->update_queue);
TRACE("Created ddraw stream %p.\n", object);
@@ -1270,15 +1364,6 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)> return S_OK;
}
-struct ddraw_sample -{
- IDirectDrawStreamSample IDirectDrawStreamSample_iface;
- LONG ref;
- struct ddraw_stream *parent;
- IDirectDrawSurface *surface;
- RECT rect;
-};
static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface) {
return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface);>
@@ -1332,6 +1417,7 @@ static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)> if (sample->surface)
IDirectDrawSurface_Release(sample->surface);
CloseHandle(sample->update_event); HeapFree(GetProcessHeap(), 0, sample);
}
@@ -1370,12 +1456,66 @@ static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface> return E_NOTIMPL;
}
-static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event, - PAPCFUNC func_APC, DWORD APC_data) +static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, + DWORD flags, HANDLE event, PAPCFUNC apc_func, DWORD apc_data)> {
- FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface, flags, event, func_APC,
APC_data); + struct ddraw_sample *sample = impl_from_IDirectDrawStreamSample(iface);
- return S_OK;
- TRACE("sample %p, flags %#x, event %p, apc_func %p, apc_data %#x.\n",
sample, flags, event, apc_func, apc_data);
- if (event && apc_func)
return E_INVALIDARG;
- if (apc_func)
- {
FIXME("APC support is not implemented!\n");
return E_NOTIMPL;
- }
- if (event)
- {
FIXME("Event parameter support is not implemented!\n");
return E_NOTIMPL;
- }
- if (flags & ~SSUPDATE_ASYNC)
- {
FIXME("Unsupported flags %#x.\n", flags);
return E_NOTIMPL;
- }
- EnterCriticalSection(&sample->parent->cs);
- if (sample->parent->state != State_Running)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_E_NOTRUNNING;
- }
- if (!sample->parent->peer || sample->parent->eos)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_S_ENDOFSTREAM;
- }
- if (MS_S_PENDING == sample->update_hr)
- {
LeaveCriticalSection(&sample->parent->cs);
return MS_E_BUSY;
- }
- sample->update_hr = MS_S_PENDING;
- ResetEvent(sample->update_event);
- list_add_tail(&sample->parent->update_queue, &sample->entry);
- SetEvent(sample->parent->update_queued_event);
- LeaveCriticalSection(&sample->parent->cs);
- if (flags & SSUPDATE_ASYNC)
return MS_S_PENDING;
- WaitForSingleObject(sample->update_event, INFINITE);
- return sample->update_hr;
}
static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)> @@ -1445,6 +1585,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw> object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl; object->ref = 1; object->parent = parent;
object->update_event = CreateEventW(NULL, FALSE, FALSE, NULL);
IAMMediaStream_AddRef(&parent->IAMMediaStream_iface); ++parent->sample_refs;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index d0c20f6253a..73d69452536 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3867,7 +3867,7 @@ static void test_audiostream_begin_flush_end_flush(void)> ok(!ref, "Got outstanding refcount %d.\n", ref);
}
-static IMediaSample *audiostream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) +static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length)> {
IMediaSample *sample; BYTE *sample_data;
@@ -3936,7 +3936,7 @@ static void test_audiostream_new_segment(void)
hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5);
media_sample = ammediastream_allocate_sample(&source, test_data, 5);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -3958,7 +3958,7 @@ static void test_audiostream_new_segment(void)
hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 5);
media_sample = ammediastream_allocate_sample(&source, test_data, 5);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -4001,27 +4001,28 @@ static void CALLBACK apc_func(ULONG_PTR param)
{ }
-static IPin *audiostream_pin; -static IMemInputPin *audiostream_mem_input_pin; -static IMediaSample *audiostream_media_sample; +static IPin *ammediastream_pin; +static IMemInputPin *ammediastream_mem_input_pin; +static IMediaSample *ammediastream_media_sample; +static DWORD ammediastream_sleep_time;
-static DWORD CALLBACK audiostream_end_of_stream(void *param) +static DWORD CALLBACK ammediastream_end_of_stream(void *param)
{
HRESULT hr;
- Sleep(100);
- hr = IPin_EndOfStream(audiostream_pin);
Sleep(ammediastream_sleep_time);
hr = IPin_EndOfStream(ammediastream_pin);
ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0;
}
-static DWORD CALLBACK audiostream_receive(void *param) +static DWORD CALLBACK ammediastream_receive(void *param)
{
HRESULT hr;
- Sleep(100);
- hr = IMemInputPin_Receive(audiostream_mem_input_pin,
audiostream_media_sample); + Sleep(ammediastream_sleep_time);
- hr = IMemInputPin_Receive(ammediastream_mem_input_pin,
ammediastream_media_sample);> ok(hr == S_OK, "Got hr %#x.\n", hr);
return 0;
@@ -4102,7 +4103,7 @@ static void test_audiostreamsample_update(void)
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 8);
media_sample1 = ammediastream_allocate_sample(&source, test_data, 8);
hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample1);
@@ -4120,7 +4121,7 @@ static void test_audiostreamsample_update(void)
ref = get_refcount(media_sample1); ok(ref == 2, "Got unexpected refcount %d.\n", ref);
- media_sample2 = audiostream_allocate_sample(&source, test_data, 8);
media_sample2 = ammediastream_allocate_sample(&source, test_data, 8);
hr = IMemInputPin_Receive(mem_input_pin, media_sample2); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(media_sample2);
@@ -4162,7 +4163,7 @@ static void test_audiostreamsample_update(void)
hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6);
media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
hr = IMemInputPin_Receive(mem_input_pin, media_sample1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample1);
@@ -4176,11 +4177,12 @@ static void test_audiostreamsample_update(void)
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample1 = audiostream_allocate_sample(&source, test_data, 6);
- media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
- audiostream_mem_input_pin = mem_input_pin;
- audiostream_media_sample = media_sample1;
- thread = CreateThread(NULL, 0, audiostream_receive, NULL, 0, NULL);
ammediastream_mem_input_pin = mem_input_pin;
ammediastream_media_sample = media_sample1;
ammediastream_sleep_time = 100;
thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -4197,8 +4199,9 @@ static void test_audiostreamsample_update(void)
ref = IMediaSample_Release(media_sample1); ok(!ref, "Got outstanding refcount %d.\n", ref);
- audiostream_pin = pin;
- thread = CreateThread(NULL, 0, audiostream_end_of_stream, NULL, 0,
NULL); + ammediastream_pin = pin;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0,
NULL);> hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0); ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
@@ -4312,7 +4315,7 @@ void test_audiostreamsample_completion_status(void)
hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
media_sample = ammediastream_allocate_sample(&source, test_data, 6);
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4327,7 +4330,7 @@ void test_audiostreamsample_completion_status(void)
hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0); ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 12);
media_sample = ammediastream_allocate_sample(&source, test_data, 12);
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4365,7 +4368,7 @@ void test_audiostreamsample_completion_status(void)
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
media_sample = ammediastream_allocate_sample(&source, test_data, 6);
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = IMediaSample_Release(media_sample);
@@ -4506,7 +4509,7 @@ static void test_audiostreamsample_get_sample_times(void)> ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));>
- media_sample = audiostream_allocate_sample(&source, test_data, 8);
media_sample = ammediastream_allocate_sample(&source, test_data, 8);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -4525,7 +4528,7 @@ static void test_audiostreamsample_get_sample_times(void)> ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time)); ok(end_time == 12347946, "Got end time %s.\n", wine_dbgstr_longlong(end_time));>
- media_sample = audiostream_allocate_sample(&source, test_data, 6);
media_sample = ammediastream_allocate_sample(&source, test_data, 6);
start_time = 12345678; end_time = 23456789; hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
@@ -6946,6 +6949,292 @@ static void test_ddrawstreamsample_get_media_stream(void)> ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_ddrawstreamsample_update(void) +{
- static const BYTE initial_data[] =
- {
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
0xef, + };
- static const BYTE test_data[] =
- {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- };
- IAMMultiMediaStream *mmstream = create_ammultimediastream();
- IDirectDrawStreamSample *stream_sample;
- IDirectDrawMediaStream *ddraw_stream;
- IMediaControl *media_control;
- IDirectDrawSurface *surface;
- IMemInputPin *mem_input_pin;
- IMediaSample *media_sample;
- IMediaFilter *media_filter;
- struct testfilter source;
- IGraphBuilder *graph;
- IMediaStream *stream;
- VIDEOINFO video_info;
- DDSURFACEDESC desc;
- IDirectDraw *ddraw;
- AM_MEDIA_TYPE mt;
- HANDLE thread;
- HANDLE event;
- HRESULT hr;
- ULONG ref;
- IPin *pin;
- RECT rect;
- int i;
- hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0,
NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL,
&MSPID_PrimaryVideo, 0, &stream); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream,
(void **)&ddraw_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void
**)&mem_input_pin); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(graph != NULL, "Expected non-NULL graph.\n");
- hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void
**)&media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void
**)&media_filter); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- testfilter_init(&source);
- hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface,
NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- event = CreateEventW(NULL, FALSE, FALSE, NULL);
- ok(event != NULL, "Expected non-NULL event.");
- hr = IMediaFilter_SetSyncSource(media_filter, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- desc = rgb24_format;
- desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
- desc.dwWidth = 4;
- desc.dwHeight = 5;
- desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
- hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- /* Make the rect width equal to the surface width, as the native
* implementation incorrectly handles rects that are not full-width
* when the ddraw stream's custom allocator is not used. */
- SetRect(&rect, 0, 1, 4, 3);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface,
&rect, 0, &stream_sample); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, event,
apc_func, 0); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- video_info = rgb24_video_info;
- video_info.bmiHeader.biWidth = 4;
- video_info.bmiHeader.biHeight = -2;
- mt = rgb24_mt;
- mt.pbFormat = (BYTE *)&video_info;
- hr = IGraphBuilder_ConnectDirect(graph,
&source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data,
12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data,
sizeof(test_data)); +
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 0;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- Sleep(100);
You're not using SSUPDATE_ASYNC, so you can get rid of the Sleep() call here, right?
This test exercises the code path where Receive() has to wait for an update to be queued. I added the Sleep() call so that the thread has a chance to enter the Receive() function before Update() is called.
Thanks; that makes sense. It's a small enough sleep that I'll call it harmless.
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12)
== 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- video_info = rgb24_video_info;
- video_info.bmiHeader.biWidth = 4;
- video_info.bmiHeader.biHeight = 2;
- mt = rgb24_mt;
- mt.pbFormat = (BYTE *)&video_info;
- hr = IGraphBuilder_ConnectDirect(graph,
&source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data,
12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data,
sizeof(test_data)); +
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 0;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- Sleep(100);
And here.
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12)
== 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface
- 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't
match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IPin_EndOfStream(pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaControl_Pause(media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
- hr = IMediaControl_Stop(media_control);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- for (i = 0; i < 5; ++i)
memcpy((BYTE *)desc.lpSurface + i * desc.lPitch, initial_data,
12); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- media_sample = ammediastream_allocate_sample(&source, test_data,
sizeof(test_data)); +
- ammediastream_mem_input_pin = mem_input_pin;
- ammediastream_media_sample = media_sample;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.lPitch, initial_data, 12)
== 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n"); + ok(memcmp((BYTE *)desc.lpSurface
- 4 * desc.lPitch, initial_data, 12) == 0, "Sample data didn't
match.\n"); + hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- ref = IMediaSample_Release(media_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ammediastream_pin = pin;
- ammediastream_sleep_time = 100;
- thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0,
NULL); +
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC,
NULL, NULL, 0); + ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
- EXPECT_REF(stream_sample, 1);
- hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC,
NULL, NULL, 0); + ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
- ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
hr isn't checked here (though omitting the call or assignment is also fine, I think.)
- CloseHandle(event);
- ref = IDirectDrawStreamSample_Release(stream_sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDrawSurface_Release(surface);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IAMMultiMediaStream_Release(mmstream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IMediaControl_Release(media_control);
- IMediaFilter_Release(media_filter);
- ref = IGraphBuilder_Release(graph);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IPin_Release(pin);
- IMemInputPin_Release(mem_input_pin);
- IDirectDrawMediaStream_Release(ddraw_stream);
- ref = IMediaStream_Release(stream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDraw_Release(ddraw);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
START_TEST(amstream) {
const WCHAR *test_avi_path;
@@ -7000,6 +7289,7 @@ START_TEST(amstream)
test_ddrawstream_receive(); test_ddrawstreamsample_get_media_stream();
test_ddrawstreamsample_update();
test_ammediastream_join_am_multi_media_stream(); test_ammediastream_join_filter();
On 9/23/20 1:54 PM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/ddrawstream.c | 24 ++++++++++--- dlls/amstream/tests/amstream.c | 66 +++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index fdfe0374ab1..679da1bd2d3 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -1449,14 +1449,30 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw } }
- if (rect)
object->rect = *rect;
- else if (object->surface)
Removing the "if (object->surface)" check is correct regardless of whether it was intentional (it can't be NULL at this point), but can you please avoid using such empty scope blocks? Either by reducing the level of indentation or by using a helper function; either is fine.
{ DDSURFACEDESC desc = { sizeof(desc) }; hr = IDirectDrawSurface_GetSurfaceDesc(object->surface, &desc);
if (hr == S_OK)
if (FAILED(hr))
{
IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
return hr;
}
if (rect)
{
object->rect = *rect;
desc.dwWidth = rect->right - rect->left;
desc.dwHeight = rect->bottom - rect->top;
}
else
{ SetRect(&object->rect, 0, 0, desc.dwWidth, desc.dwHeight);
}
hr = IDirectDrawMediaStream_SetFormat(&parent->IDirectDrawMediaStream_iface, &desc, NULL);
if (FAILED(hr))
{
IDirectDrawStreamSample_Release(&object->IDirectDrawStreamSample_iface);
return hr;
}
}
*ddraw_stream_sample = &object->IDirectDrawStreamSample_iface;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 1c0b36ea6c5..d2126a15db3 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -6495,6 +6495,7 @@ static void get_ddrawstream_create_sample_desc_(int line, const DDSURFACEDESC *f static void test_ddrawstream_create_sample(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream();
- DDSURFACEDESC desc2 = { sizeof(desc2) }; IDirectDrawSurface *surface, *surface2; DDSURFACEDESC desc = { sizeof(desc) }; IDirectDrawMediaStream *ddraw_stream;
@@ -6591,11 +6592,74 @@ static void test_ddrawstream_create_sample(void) hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample); ok(hr == S_OK, "Got hr %#x.\n", hr);
- IDirectDrawMediaStream_Release(ddraw_stream); ref = IDirectDrawStreamSample_Release(sample); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IDirectDrawSurface_Release(surface); ok(!ref, "Got outstanding refcount %d.\n", ref);
- memset(&desc, 0, sizeof(desc));
- desc.dwSize = sizeof(desc);
- desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
- desc.dwWidth = 444;
- desc.dwHeight = 400;
- desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
- desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
- desc.ddpfPixelFormat.dwRGBBitCount = 32;
- desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
- desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
- desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
- desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
- desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
- hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- SetRect(&rect, 111, 100, 333, 300);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ref = IDirectDrawStreamSample_Release(sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- surface2 = NULL;
- hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawSurface_GetSurfaceDesc(surface2, &desc2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(desc2.dwWidth == 222, "Got width %u.\n", desc2.dwWidth);
- ok(desc2.dwHeight == 200, "Got height %u.\n", desc2.dwHeight);
- ok(memcmp(&desc2.ddpfPixelFormat, &desc.ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
"Pixel format didn't match.\n");
- ref = IDirectDrawStreamSample_Release(sample);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDrawSurface_Release(surface);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IDirectDrawSurface_Release(surface2);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- memset(&desc, 0, sizeof(desc));
- desc.dwSize = sizeof(desc);
- desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
- desc.dwWidth = 444;
- desc.dwHeight = 400;
- desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
- desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED4;
- desc.ddpfPixelFormat.dwRGBBitCount = 4;
- desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
- hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
- ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#x.\n", hr);
- IDirectDrawMediaStream_Release(ddraw_stream);
- ref = IDirectDrawSurface_Release(surface);
- ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IAMMultiMediaStream_Release(mmstream); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IMediaStream_Release(stream);