Commit dca38a84 authored by Anton Baskanov's avatar Anton Baskanov Committed by Alexandre Julliard

amstream: Implement AMDirectDrawStream::Receive and IDirectDrawStreamSample::Update.

parent 5f7e25c7
...@@ -59,11 +59,74 @@ struct ddraw_stream ...@@ -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 ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment