From: Santino Mazza smazza@codeweavers.com
--- dlls/amstream/ddrawstream.c | 111 ++++++++++++++++++++++++++------- dlls/amstream/tests/amstream.c | 12 ++-- 2 files changed, 94 insertions(+), 29 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index f8dd77ec81f..41758aa987c 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -57,6 +57,7 @@ struct ddraw_stream IPin *peer; IMemAllocator *allocator; IMemAllocator *private_allocator; + IMediaSample *next_sample; AM_MEDIA_TYPE mt; struct format format; FILTER_STATE state; @@ -540,11 +541,34 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStr return S_OK; }
+static void create_mt_from_desc(AM_MEDIA_TYPE *mt, const DDSURFACEDESC *format) +{ + VIDEOINFOHEADER *videoinfo; + + videoinfo = (VIDEOINFOHEADER*)mt->pbFormat; + videoinfo->bmiHeader.biWidth = format->dwWidth; + videoinfo->bmiHeader.biHeight = format->dwHeight; + + if (format->ddpfPixelFormat.dwRGBBitCount == 16 && format->ddpfPixelFormat.dwRBitMask == 0x7c00) + mt->subtype = MEDIASUBTYPE_RGB555; + else if (format->ddpfPixelFormat.dwRGBBitCount == 16 && format->ddpfPixelFormat.dwRBitMask == 0x7c00) + mt->subtype = MEDIASUBTYPE_RGB565; + else if (format->ddpfPixelFormat.dwRGBBitCount == 24) + mt->subtype = MEDIASUBTYPE_RGB24; + else if (format->ddpfPixelFormat.dwRGBBitCount == 32) + mt->subtype = MEDIASUBTYPE_RGB32; +} + +static inline BOOL using_private_allocator(struct ddraw_stream *stream) { + return !(stream->allocator) || stream->allocator == &stream->IMemAllocator_iface; +} + static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream *iface, const DDSURFACEDESC *format, IDirectDrawPalette *palette) { struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface); - AM_MEDIA_TYPE old_media_type; + AM_MEDIA_TYPE old_media_type, new_media_type; + VIDEOINFO new_media_type_video; struct format old_format; IPin *old_peer; HRESULT hr; @@ -629,31 +653,40 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr
if (stream->peer && !is_format_compatible(stream, old_format.width, old_format.height, &old_format.pf)) { - hr = CopyMediaType(&old_media_type, &stream->mt); - if (FAILED(hr)) + memset(&new_media_type, 0, sizeof(new_media_type)); + new_media_type.pbFormat = (BYTE*)&new_media_type_video; + new_media_type.cbFormat = sizeof(VIDEOINFO); + create_mt_from_desc(&new_media_type, format); + if (!using_private_allocator(stream) || + (IPin_QueryAccept(stream->peer, &new_media_type) != S_OK) || + FAILED(hr = IMediaSample_SetMediaType(stream->next_sample, &new_media_type))) { - stream->format = old_format; - LeaveCriticalSection(&stream->cs); - return hr; - } - old_peer = stream->peer; - IPin_AddRef(old_peer); + /* Try re-connection */ + hr = CopyMediaType(&old_media_type, &stream->mt); + if (FAILED(hr)) + { + stream->format = old_format; + LeaveCriticalSection(&stream->cs); + return hr; + } + old_peer = stream->peer; + IPin_AddRef(old_peer);
- IFilterGraph_Disconnect(stream->graph, stream->peer); - IFilterGraph_Disconnect(stream->graph, &stream->IPin_iface); - hr = IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, NULL); - if (FAILED(hr)) - { - stream->format = old_format; - IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, &old_media_type); + IFilterGraph_Disconnect(stream->graph, stream->peer); + IFilterGraph_Disconnect(stream->graph, &stream->IPin_iface); + hr = IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, NULL); + if (FAILED(hr)) + { + stream->format = old_format; + IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, &old_media_type); + IPin_Release(old_peer); + FreeMediaType(&old_media_type); + LeaveCriticalSection(&stream->cs); + return DDERR_INVALIDSURFACETYPE; + } IPin_Release(old_peer); FreeMediaType(&old_media_type); - LeaveCriticalSection(&stream->cs); - return DDERR_INVALIDSURFACETYPE; } - - IPin_Release(old_peer); - FreeMediaType(&old_media_type); }
LeaveCriticalSection(&stream->cs); @@ -1322,14 +1355,37 @@ static HRESULT WINAPI ddraw_mem_allocator_GetProperties(IMemAllocator *iface,ALL static HRESULT WINAPI ddraw_mem_allocator_Commit(IMemAllocator *iface) { struct ddraw_stream *stream = impl_from_IMemAllocator(iface); + HRESULT hr;
- return IMemAllocator_Commit(stream->private_allocator); + EnterCriticalSection(&stream->cs); + hr = IMemAllocator_Commit(stream->private_allocator); + if (FAILED(hr)) { + LeaveCriticalSection(&stream->cs); + return hr; + } + + hr = IMemAllocator_GetBuffer(stream->private_allocator, &stream->next_sample, NULL, NULL, 0); + if (FAILED(hr)) + { + IMemAllocator_Decommit(stream->private_allocator); + LeaveCriticalSection(&stream->cs); + return hr; + } + + LeaveCriticalSection(&stream->cs); + return S_OK; }
static HRESULT WINAPI ddraw_mem_allocator_Decommit(IMemAllocator *iface) { struct ddraw_stream *stream = impl_from_IMemAllocator(iface);
+ if (stream->next_sample) + { + IMemAllocator_ReleaseBuffer(stream->private_allocator, stream->next_sample); + IMediaSample_Release(stream->next_sample); + } + return IMemAllocator_Decommit(stream->private_allocator); }
@@ -1338,8 +1394,17 @@ static HRESULT WINAPI ddraw_mem_allocator_GetBuffer(IMemAllocator *iface, IMedia DWORD flags) { struct ddraw_stream *stream = impl_from_IMemAllocator(iface); + HRESULT hr;
- return IMemAllocator_GetBuffer(stream->private_allocator, buf, start_time, end_time, flags); + EnterCriticalSection(&stream->cs); + + *buf = stream->next_sample; + IMediaSample_SetTime(*buf, start_time, end_time); + hr = IMemAllocator_GetBuffer(stream->private_allocator, &stream->next_sample, NULL, NULL, flags); + + LeaveCriticalSection(&stream->cs); + + return hr; }
static HRESULT WINAPI ddraw_mem_allocator_ReleaseBuffer(IMemAllocator *iface,IMediaSample *buf) diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 284d451b2a6..0a3199dc364 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -8628,10 +8628,10 @@ static void test_ddrawstream_set_format_dynamic(void) ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8), "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype)); hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, NULL, &desired_format, NULL); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, "Got rgb bit count %lu.\n", current_format.ddpfPixelFormat.u1.dwRGBBitCount); - todo_wine ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, + ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, "Got rgb bit count %lu.\n", desired_format.ddpfPixelFormat.u1.dwRGBBitCount);
format = rgb555_format; @@ -8651,10 +8651,10 @@ static void test_ddrawstream_set_format_dynamic(void) ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8), "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype)); hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, NULL, &desired_format, NULL); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, "Got rgb bit count %lu.\n", current_format.ddpfPixelFormat.u1.dwRGBBitCount); - todo_wine ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, + ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 16, "Got rgb bit count %lu.\n", desired_format.ddpfPixelFormat.u1.dwRGBBitCount);
video_info = rgb555_video_info;