[PATCH 5/5] amstream: Implement IDirectDrawStreamSample::Update.
Anton Baskanov
baskanov at gmail.com
Thu Sep 24 14:07:07 CDT 2020
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 at 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();
More information about the wine-devel
mailing list