amstream: Implement AMDirectDrawStream::Receive and IDirectDrawStreamSample::Update.
Signed-off-by: Anton Baskanov <baskanov@gmail.com> Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5f7e25c7b1
commit
dca38a84fb
|
@ -59,11 +59,74 @@ struct ddraw_stream
|
||||||
struct format format;
|
struct format format;
|
||||||
FILTER_STATE state;
|
FILTER_STATE state;
|
||||||
BOOL eos;
|
BOOL eos;
|
||||||
|
CONDITION_VARIABLE update_queued_cv;
|
||||||
|
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,
|
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
|
||||||
const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample);
|
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 / 8;
|
||||||
|
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,
|
static BOOL is_format_compatible(struct ddraw_stream *stream,
|
||||||
DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf)
|
DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf)
|
||||||
{
|
{
|
||||||
|
@ -268,6 +331,8 @@ static HRESULT WINAPI ddraw_IAMMediaStream_SetState(IAMMediaStream *iface, FILTE
|
||||||
|
|
||||||
EnterCriticalSection(&stream->cs);
|
EnterCriticalSection(&stream->cs);
|
||||||
|
|
||||||
|
if (state == State_Stopped)
|
||||||
|
WakeConditionVariable(&stream->update_queued_cv);
|
||||||
if (stream->state == State_Stopped)
|
if (stream->state == State_Stopped)
|
||||||
stream->eos = FALSE;
|
stream->eos = FALSE;
|
||||||
|
|
||||||
|
@ -1079,6 +1144,8 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
|
||||||
|
|
||||||
stream->eos = TRUE;
|
stream->eos = TRUE;
|
||||||
|
|
||||||
|
flush_update_queue(stream, MS_S_ENDOFSTREAM);
|
||||||
|
|
||||||
LeaveCriticalSection(&stream->cs);
|
LeaveCriticalSection(&stream->cs);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1190,8 +1257,51 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac
|
||||||
|
|
||||||
static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample)
|
static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample)
|
||||||
{
|
{
|
||||||
FIXME("iface %p, sample %p, stub!\n", iface, sample);
|
struct ddraw_stream *stream = impl_from_IMemInputPin(iface);
|
||||||
return E_NOTIMPL;
|
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) / 8;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
SleepConditionVariableCS(&stream->update_queued_cv, &stream->cs, INFINITE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface,
|
static HRESULT WINAPI ddraw_meminput_ReceiveMultiple(IMemInputPin *iface,
|
||||||
|
@ -1241,6 +1351,8 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)
|
||||||
object->format.height = 100;
|
object->format.height = 100;
|
||||||
|
|
||||||
InitializeCriticalSection(&object->cs);
|
InitializeCriticalSection(&object->cs);
|
||||||
|
InitializeConditionVariable(&object->update_queued_cv);
|
||||||
|
list_init(&object->update_queue);
|
||||||
|
|
||||||
TRACE("Created ddraw stream %p.\n", object);
|
TRACE("Created ddraw stream %p.\n", object);
|
||||||
|
|
||||||
|
@ -1249,15 +1361,6 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)
|
||||||
return S_OK;
|
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)
|
static inline struct ddraw_sample *impl_from_IDirectDrawStreamSample(IDirectDrawStreamSample *iface)
|
||||||
{
|
{
|
||||||
return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface);
|
return CONTAINING_RECORD(iface, struct ddraw_sample, IDirectDrawStreamSample_iface);
|
||||||
|
@ -1311,6 +1414,7 @@ static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface)
|
||||||
|
|
||||||
if (sample->surface)
|
if (sample->surface)
|
||||||
IDirectDrawSurface_Release(sample->surface);
|
IDirectDrawSurface_Release(sample->surface);
|
||||||
|
CloseHandle(sample->update_event);
|
||||||
HeapFree(GetProcessHeap(), 0, sample);
|
HeapFree(GetProcessHeap(), 0, sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,12 +1453,66 @@ static HRESULT WINAPI ddraw_sample_SetSampleTimes(IDirectDrawStreamSample *iface
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, DWORD flags, HANDLE event,
|
static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface,
|
||||||
PAPCFUNC func_APC, DWORD APC_data)
|
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);
|
||||||
|
WakeConditionVariable(&sample->parent->update_queued_cv);
|
||||||
|
|
||||||
|
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)
|
static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *iface, DWORD flags, DWORD milliseconds)
|
||||||
|
@ -1425,6 +1583,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw
|
||||||
object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl;
|
object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl;
|
||||||
object->ref = 1;
|
object->ref = 1;
|
||||||
object->parent = parent;
|
object->parent = parent;
|
||||||
|
object->update_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
IAMMediaStream_AddRef(&parent->IAMMediaStream_iface);
|
IAMMediaStream_AddRef(&parent->IAMMediaStream_iface);
|
||||||
++parent->sample_refs;
|
++parent->sample_refs;
|
||||||
|
|
||||||
|
|
|
@ -3867,7 +3867,7 @@ static void test_audiostream_begin_flush_end_flush(void)
|
||||||
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
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;
|
IMediaSample *sample;
|
||||||
BYTE *sample_data;
|
BYTE *sample_data;
|
||||||
|
@ -3936,7 +3936,7 @@ static void test_audiostream_new_segment(void)
|
||||||
hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0);
|
hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
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;
|
start_time = 12345678;
|
||||||
end_time = 23456789;
|
end_time = 23456789;
|
||||||
hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
|
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);
|
hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
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;
|
start_time = 12345678;
|
||||||
end_time = 23456789;
|
end_time = 23456789;
|
||||||
hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
|
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 IPin *ammediastream_pin;
|
||||||
static IMemInputPin *audiostream_mem_input_pin;
|
static IMemInputPin *ammediastream_mem_input_pin;
|
||||||
static IMediaSample *audiostream_media_sample;
|
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;
|
HRESULT hr;
|
||||||
|
|
||||||
Sleep(100);
|
Sleep(ammediastream_sleep_time);
|
||||||
hr = IPin_EndOfStream(audiostream_pin);
|
hr = IPin_EndOfStream(ammediastream_pin);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD CALLBACK audiostream_receive(void *param)
|
static DWORD CALLBACK ammediastream_receive(void *param)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
Sleep(100);
|
Sleep(ammediastream_sleep_time);
|
||||||
hr = IMemInputPin_Receive(audiostream_mem_input_pin, audiostream_media_sample);
|
hr = IMemInputPin_Receive(ammediastream_mem_input_pin, ammediastream_media_sample);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4102,7 +4103,7 @@ static void test_audiostreamsample_update(void)
|
||||||
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
|
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
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);
|
hr = IMemInputPin_Receive(mem_input_pin, media_sample1);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
ref = get_refcount(media_sample1);
|
ref = get_refcount(media_sample1);
|
||||||
|
@ -4120,7 +4121,7 @@ static void test_audiostreamsample_update(void)
|
||||||
ref = get_refcount(media_sample1);
|
ref = get_refcount(media_sample1);
|
||||||
ok(ref == 2, "Got unexpected refcount %d.\n", ref);
|
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);
|
hr = IMemInputPin_Receive(mem_input_pin, media_sample2);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
ref = get_refcount(media_sample2);
|
ref = get_refcount(media_sample2);
|
||||||
|
@ -4162,7 +4163,7 @@ static void test_audiostreamsample_update(void)
|
||||||
hr = IMediaControl_Pause(media_control);
|
hr = IMediaControl_Pause(media_control);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
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);
|
hr = IMemInputPin_Receive(mem_input_pin, media_sample1);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
ref = IMediaSample_Release(media_sample1);
|
ref = IMediaSample_Release(media_sample1);
|
||||||
|
@ -4176,11 +4177,12 @@ static void test_audiostreamsample_update(void)
|
||||||
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
|
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
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;
|
ammediastream_mem_input_pin = mem_input_pin;
|
||||||
audiostream_media_sample = media_sample1;
|
ammediastream_media_sample = media_sample1;
|
||||||
thread = CreateThread(NULL, 0, audiostream_receive, NULL, 0, NULL);
|
ammediastream_sleep_time = 100;
|
||||||
|
thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
|
||||||
|
|
||||||
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
|
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
|
@ -4197,8 +4199,9 @@ static void test_audiostreamsample_update(void)
|
||||||
ref = IMediaSample_Release(media_sample1);
|
ref = IMediaSample_Release(media_sample1);
|
||||||
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
||||||
|
|
||||||
audiostream_pin = pin;
|
ammediastream_pin = pin;
|
||||||
thread = CreateThread(NULL, 0, audiostream_end_of_stream, NULL, 0, NULL);
|
ammediastream_sleep_time = 100;
|
||||||
|
thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
|
||||||
|
|
||||||
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
|
hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
|
||||||
ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
|
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);
|
hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
|
||||||
ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
|
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);
|
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
ref = IMediaSample_Release(media_sample);
|
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);
|
hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
|
||||||
ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
|
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);
|
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
ref = IMediaSample_Release(media_sample);
|
ref = IMediaSample_Release(media_sample);
|
||||||
|
@ -4365,7 +4368,7 @@ void test_audiostreamsample_completion_status(void)
|
||||||
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
|
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
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);
|
hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
ref = IMediaSample_Release(media_sample);
|
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(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));
|
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;
|
start_time = 12345678;
|
||||||
end_time = 23456789;
|
end_time = 23456789;
|
||||||
hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
|
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(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));
|
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;
|
start_time = 12345678;
|
||||||
end_time = 23456789;
|
end_time = 23456789;
|
||||||
hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
|
hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
|
||||||
|
@ -5076,6 +5079,108 @@ static void test_ddrawstream_set_format(void)
|
||||||
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
|
||||||
|
ammediastream_mem_input_pin = source.source.pMemInputPin;
|
||||||
|
ammediastream_media_sample = sample;
|
||||||
|
ammediastream_sleep_time = 0;
|
||||||
|
thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
|
||||||
|
|
||||||
|
ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
|
||||||
|
|
||||||
|
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
|
||||||
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
|
|
||||||
|
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)
|
static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid)
|
||||||
{
|
{
|
||||||
IAMMultiMediaStream *mmstream = create_ammultimediastream();
|
IAMMultiMediaStream *mmstream = create_ammultimediastream();
|
||||||
|
@ -6829,6 +6934,293 @@ static void test_ddrawstreamsample_get_media_stream(void)
|
||||||
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
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);
|
||||||
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
|
|
||||||
|
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)
|
START_TEST(amstream)
|
||||||
{
|
{
|
||||||
const WCHAR *test_avi_path;
|
const WCHAR *test_avi_path;
|
||||||
|
@ -6880,8 +7272,10 @@ START_TEST(amstream)
|
||||||
test_ddrawstream_create_sample();
|
test_ddrawstream_create_sample();
|
||||||
test_ddrawstream_get_format();
|
test_ddrawstream_get_format();
|
||||||
test_ddrawstream_set_format();
|
test_ddrawstream_set_format();
|
||||||
|
test_ddrawstream_receive();
|
||||||
|
|
||||||
test_ddrawstreamsample_get_media_stream();
|
test_ddrawstreamsample_get_media_stream();
|
||||||
|
test_ddrawstreamsample_update();
|
||||||
|
|
||||||
test_ammediastream_join_am_multi_media_stream();
|
test_ammediastream_join_am_multi_media_stream();
|
||||||
test_ammediastream_join_filter();
|
test_ammediastream_join_filter();
|
||||||
|
|
Loading…
Reference in New Issue