From: Santino Mazza smazza@codeweavers.com
--- dlls/amstream/ddrawstream.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 10e63681c9e..c67bcd1fc1b 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -677,21 +677,18 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr
if (stream->peer && !is_format_compatible(stream, old_format.width, old_format.height, &old_format.pf)) { - if (stream->using_private_allocator && - (IPin_QueryAccept(stream->peer, &stream->mt) == S_OK)) + if (FAILED(hr = CopyMediaType(&old_media_type, &stream->mt))) { - set_mt_from_desc(&stream->mt, format); + stream->format = old_format; + LeaveCriticalSection(&stream->cs); + return hr; } - else + + set_mt_from_desc(&stream->mt, format); + + if (!stream->using_private_allocator || IPin_QueryAccept(stream->peer, &stream->mt) != S_OK) { /* Reconnect. */ - if (FAILED(hr = CopyMediaType(&old_media_type, &stream->mt))) - { - stream->format = old_format; - LeaveCriticalSection(&stream->cs); - return hr; - } - old_peer = stream->peer; IPin_AddRef(old_peer);
@@ -707,8 +704,9 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr return DDERR_INVALIDSURFACETYPE; } IPin_Release(old_peer); - FreeMediaType(&old_media_type); } + + FreeMediaType(&old_media_type); }
LeaveCriticalSection(&stream->cs);
From: Santino Mazza smazza@codeweavers.com
--- dlls/amstream/tests/amstream.c | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 70876ed07cf..e3a7b1a7fae 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -8535,6 +8535,70 @@ static void test_ddrawstream_mem_allocator(void) hr = IMediaStream_QueryInterface(stream, &IID_IMemAllocator, (void **)&ddraw_allocator); ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ /* Check default properties. */ + hr = IMemAllocator_GetProperties(ddraw_allocator, &props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(props.cbBuffer == 10000, "Got size %ld.\n", props.cbBuffer); + todo_wine ok(props.cBuffers == 1, "Got %ld buffers\n", props.cBuffers); + todo_wine ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + + /* Try changing allocator properties. */ + props.cbAlign = 1; + props.cbBuffer = 1000; + props.cBuffers = 4; + props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(ret_props.cbBuffer == 10000, "Got size %ld.\n", ret_props.cbBuffer); + ok(ret_props.cBuffers == 4, "Got %ld buffers.\n", ret_props.cBuffers); + ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + + /* Check how allocator properties change when setting a new format. */ + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMemAllocator_GetProperties(ddraw_allocator, &props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(props.cbBuffer == 40000, "Got size %ld.\n", props.cbBuffer); + ok(props.cBuffers == 4, "Got %ld buffers.\n", props.cBuffers); + ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + + props.cbAlign = 1; + props.cbBuffer = 1000; + props.cBuffers = 0; + props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); + todo_wine ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); + ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + + /* Try setting a larger buffer size. */ + props.cbAlign = 1; + props.cbBuffer = 50000; + props.cBuffers = 1; + props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); + ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); + ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + + hr = IMemAllocator_Commit(ddraw_allocator); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMemAllocator_GetProperties(ddraw_allocator, &props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(ret_props.cbBuffer == 20000, "Got size %ld.\n", ret_props.cbBuffer); + ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); + ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + + hr = IMemAllocator_Decommit(ddraw_allocator); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + mem_allocator = NULL; hr = IMemInputPin_GetAllocator(mem_input, &mem_allocator); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -8588,6 +8652,25 @@ static void test_ddrawstream_mem_allocator(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ props.cbAlign = 1; + props.cbBuffer = 50000; + props.cBuffers = 1; + props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); + ok(hr == VFW_E_ALREADY_COMMITTED, "Got hr %#lx.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMemAllocator_GetProperties(ddraw_allocator, &props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(props.cbBuffer == 333 * 444 * 4, "Got size %ld.\n", props.cbBuffer); + ok(props.cBuffers == 2, "Got %ld buffers.\n", props.cBuffers); + ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample1); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IDirectDrawStreamSample_Update(ddraw_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/amstream/tests/amstream.c | 272 +++++++++++++++++++++++++++++++-- 1 file changed, 257 insertions(+), 15 deletions(-)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index e3a7b1a7fae..89e6102deab 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -8504,12 +8504,14 @@ static void test_ddrawstream_qc(void)
static void test_ddrawstream_mem_allocator(void) { + IDirectDrawStreamSample *ddraw_sample1, *ddraw_sample2, *ddraw_sample3; IMemAllocator *ddraw_allocator, *mem_allocator, *new_allocator; IAMMultiMediaStream *mmstream = create_ammultimediastream(); - IDirectDrawStreamSample *ddraw_sample1, *ddraw_sample2; - IMediaSample *media_sample1, *media_sample2; + IMediaSample *media_sample1, *media_sample2, *media_sample3; ALLOCATOR_PROPERTIES props, ret_props; IDirectDrawMediaStream *ddraw_stream; + VIDEOINFOHEADER *video_info; + REFERENCE_TIME start, end; AM_MEDIA_TYPE *sample_mt; struct testfilter source; IMemInputPin *mem_input; @@ -8518,6 +8520,19 @@ static void test_ddrawstream_mem_allocator(void) HRESULT hr; ULONG ref; IPin *pin; + LONG size; + + static const VIDEOINFO expect_video_info = + { + .rcSource = {0, 0, 333, 444}, + .rcTarget = {0, 0, 333, 444}, + .bmiHeader.biSize = sizeof(BITMAPINFOHEADER), + .bmiHeader.biWidth = 336, + .bmiHeader.biHeight = -444, + .bmiHeader.biPlanes = 1, + .bmiHeader.biBitCount = 16, + .bmiHeader.biSizeImage = 336 * 444 * 2, + };
hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -8541,17 +8556,19 @@ static void test_ddrawstream_mem_allocator(void) todo_wine ok(props.cbBuffer == 10000, "Got size %ld.\n", props.cbBuffer); todo_wine ok(props.cBuffers == 1, "Got %ld buffers\n", props.cBuffers); todo_wine ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix);
/* Try changing allocator properties. */ - props.cbAlign = 1; + props.cbAlign = 2; props.cbBuffer = 1000; props.cBuffers = 4; - props.cbPrefix = 0; + props.cbPrefix = 2; hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); ok(hr == S_OK, "Got hr %#lx.\n", hr); todo_wine ok(ret_props.cbBuffer == 10000, "Got size %ld.\n", ret_props.cbBuffer); ok(ret_props.cBuffers == 4, "Got %ld buffers.\n", ret_props.cBuffers); - ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + todo_wine ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + todo_wine ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix);
/* Check how allocator properties change when setting a new format. */ hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); @@ -8561,7 +8578,15 @@ static void test_ddrawstream_mem_allocator(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); todo_wine ok(props.cbBuffer == 40000, "Got size %ld.\n", props.cbBuffer); ok(props.cBuffers == 4, "Got %ld buffers.\n", props.cBuffers); - ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + todo_wine ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + todo_wine ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix); + + props.cbAlign = 0; + props.cbBuffer = 1000; + props.cBuffers = 0; + props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); + ok(hr == VFW_E_BADALIGN, "Got hr %#lx.\n", hr);
props.cbAlign = 1; props.cbBuffer = 1000; @@ -8572,6 +8597,7 @@ static void test_ddrawstream_mem_allocator(void) todo_wine ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); todo_wine ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix);
/* Try setting a larger buffer size. */ props.cbAlign = 1; @@ -8583,6 +8609,10 @@ static void test_ddrawstream_mem_allocator(void) todo_wine ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix); + + hr = IMemAllocator_GetBuffer(ddraw_allocator, &media_sample1, NULL, NULL, 0); + ok(hr == VFW_E_NOT_COMMITTED, "Got hr %#lx.\n", hr);
hr = IMemAllocator_Commit(ddraw_allocator); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -8592,13 +8622,19 @@ static void test_ddrawstream_mem_allocator(void)
hr = IMemAllocator_GetProperties(ddraw_allocator, &props); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ret_props.cbBuffer == 20000, "Got size %ld.\n", ret_props.cbBuffer); - ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); - ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + todo_wine ok(props.cbBuffer == 20000, "Got size %ld.\n", props.cbBuffer); + ok(props.cBuffers == 1, "Got %ld buffers.\n", props.cBuffers); + ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix); + + /* GetBuffer() hangs here, even with AM_GBF_NOWAIT. */
hr = IMemAllocator_Decommit(ddraw_allocator); ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ hr = IMemAllocator_GetBuffer(ddraw_allocator, &media_sample1, NULL, NULL, 0); + ok(hr == VFW_E_NOT_COMMITTED, "Got hr %#lx.\n", hr); + mem_allocator = NULL; hr = IMemInputPin_GetAllocator(mem_input, &mem_allocator); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -8667,35 +8703,241 @@ static void test_ddrawstream_mem_allocator(void) todo_wine ok(props.cbBuffer == 333 * 444 * 4, "Got size %ld.\n", props.cbBuffer); ok(props.cBuffers == 2, "Got %ld buffers.\n", props.cBuffers); ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix);
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL); ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample1); ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); + todo_wine ok(hr == MS_E_SAMPLEALLOC, "Got hr %#lx.\n", hr); + + /* We cannot retrieve the sample from GetBuffer() without calling Update(). + * Otherwise GetBuffer() will hang as there are no samples to return. */ hr = IDirectDrawStreamSample_Update(ddraw_sample1, SSUPDATE_ASYNC, NULL, NULL, 0); ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample2); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IDirectDrawStreamSample_Update(ddraw_sample2, SSUPDATE_ASYNC, NULL, NULL, 0); ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample3); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectDrawStreamSample_Update(ddraw_sample3, SSUPDATE_ASYNC, NULL, NULL, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample1, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_GetMediaType(media_sample1, &sample_mt); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), "Got subtype %s.\n", wine_dbgstr_guid(&sample_mt->subtype)); + ok(IsEqualGUID(&sample_mt->majortype, &MEDIATYPE_Video), + "Got major type %s.\n", debugstr_guid(&sample_mt->majortype)); + todo_wine ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), + "Got subtype %s.\n", debugstr_guid(&sample_mt->subtype)); + todo_wine ok(sample_mt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", sample_mt->bFixedSizeSamples); + ok(!sample_mt->bTemporalCompression, "Got temporal compression %d.\n", sample_mt->bTemporalCompression); + todo_wine ok(sample_mt->lSampleSize == 336 * 444 * 2, "Got sample size %lu.\n", sample_mt->lSampleSize); + ok(IsEqualGUID(&sample_mt->formattype, &FORMAT_VideoInfo), + "Got format type %s.\n", debugstr_guid(&sample_mt->formattype)); + ok(!sample_mt->pUnk, "Got pUnk %p.\n", sample_mt->pUnk); + ok(sample_mt->cbFormat == sizeof(VIDEOINFO), "Got format size %lu.\n", sample_mt->cbFormat); + todo_wine ok(!memcmp(sample_mt->pbFormat, &expect_video_info, sizeof(VIDEOINFO)), "Format blocks didn't match.\n"); + + sample_mt->lSampleSize = 123; + hr = IMediaSample_SetMediaType(media_sample1, sample_mt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + DeleteMediaType(sample_mt); + + hr = IMediaSample_GetMediaType(media_sample1, &sample_mt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(sample_mt->lSampleSize == 336 * 444 * 2, "Got sample size %lu.\n", sample_mt->lSampleSize); + + video_info = (VIDEOINFOHEADER *)sample_mt->pbFormat; + video_info->bmiHeader.biWidth = 400; + video_info->bmiHeader.biHeight = -400; + video_info->bmiHeader.biSizeImage = 400 * 400 * 2; + SetRect(&video_info->rcSource, 0, 0, 400, 400); + SetRect(&video_info->rcTarget, 0, 0, 400, 400); + hr = IMediaSample_SetMediaType(media_sample1, sample_mt); + todo_wine ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr); + DeleteMediaType(sample_mt); + hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample2, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_GetMediaType(media_sample2, &sample_mt); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), "Got subtype %s.\n", wine_dbgstr_guid(&sample_mt->subtype)); + todo_wine ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), + "Got subtype %s.\n", wine_dbgstr_guid(&sample_mt->subtype)); DeleteMediaType(sample_mt); - IMediaSample_Release(media_sample1); - IMediaSample_Release(media_sample2); - IDirectDrawStreamSample_Release(ddraw_sample1); - IDirectDrawStreamSample_Release(ddraw_sample2); + + hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample3, NULL, NULL, AM_GBF_NOWAIT); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + /* GetBuffer() again blocks, even with AM_GBF_NOWAIT. */ + + ok(media_sample1 != media_sample2, "Expected different samples.\n"); + + check_interface(media_sample1, &IID_IDirectDrawStreamSample, FALSE); + todo_wine check_interface(media_sample1, &IID_IMediaSample2, FALSE); + + hr = IMemAllocator_GetProperties(ddraw_allocator, &props); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(props.cBuffers == 2, "Expected 2 samples got %ld\n", props.cBuffers); + + size = IMediaSample_GetSize(media_sample1); + todo_wine ok(size == 336 * 444 * 2, "Got size %ld.\n", size); + size = IMediaSample_GetActualDataLength(media_sample1); + todo_wine ok(size == 336 * 444 * 2, "Got size %ld.\n", size); + hr = IMediaSample_SetActualDataLength(media_sample1, size); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetActualDataLength(media_sample1, size + 1); + todo_wine ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetActualDataLength(media_sample1, size - 1); + todo_wine ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + + start = end = 0xdeadbeef; + hr = IMediaSample_GetTime(media_sample1, &start, &end); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(!start, "Got start %I64d.\n", start); + todo_wine ok(!end, "Got end %I64d.\n", end); + + start = end = 0xdeadbeef; + hr = IMediaSample_GetMediaTime(media_sample1, &start, &end); + todo_wine ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); + ok(start == 0xdeadbeef, "Got start %I64d.\n", start); + ok(end == 0xdeadbeef, "Got end %I64d.\n", end); + + hr = IMediaSample_IsSyncPoint(media_sample1); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_IsPreroll(media_sample1); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IMediaSample_IsDiscontinuity(media_sample1); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + start = 123; + end = 456; + hr = IMediaSample_SetMediaTime(media_sample1, &start, &end); + todo_wine ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetTime(media_sample1, &start, &end); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + start = end = 0xdeadbeef; + hr = IMediaSample_GetTime(media_sample1, &start, &end); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(start == 123, "Got start %I64d.\n", start); + ok(end == 456, "Got end %I64d.\n", end); + + /* SetTime() does not correctly handle NULL parameters. Instead they are + * interpreted as "no change". */ + start = 555; + end = 666; + hr = IMediaSample_SetTime(media_sample1, &start, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetTime(media_sample1, NULL, &end); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetTime(media_sample1, NULL, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + start = end = 0xdeadbeef; + hr = IMediaSample_GetTime(media_sample1, &start, &end); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(start == 555, "Got start %I64d.\n", start); + todo_wine ok(end == 666, "Got end %I64d.\n", end); + + start = end = 0xdeadbeef; + hr = IDirectDrawStreamSample_GetSampleTimes(ddraw_sample1, &start, &end, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(start == 555, "Got start %I64d.\n", start); + todo_wine ok(end == 666, "Got end %I64d.\n", end); + + hr = IMediaSample_SetSyncPoint(media_sample1, FALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetDiscontinuity(media_sample1, TRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_SetPreroll(media_sample1, TRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaSample_IsSyncPoint(media_sample1); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IMediaSample_IsPreroll(media_sample1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_IsDiscontinuity(media_sample1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ref = IMediaSample_Release(media_sample1); + ok(!ref, "Got refcount %ld.\n", ref); + + hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample1, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + start = end = 0xdeadbeef; + hr = IMediaSample_GetTime(media_sample1, &start, &end); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(start == 555, "Got start %I64d.\n", start); + todo_wine ok(end == 666, "Got end %I64d.\n", end); + hr = IMediaSample_IsSyncPoint(media_sample1); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_IsPreroll(media_sample1); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSample_IsDiscontinuity(media_sample1); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample2, 0, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + + hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample2); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample2, 0, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + hr = IDirectDrawStreamSample_Update(ddraw_sample2, SSUPDATE_ASYNC, NULL, NULL, 0); + ok(hr == MS_E_BUSY, "Got hr %#lx.\n", hr); + + ref = IMediaSample_Release(media_sample2); + ok(!ref, "Got refcount %ld.\n", ref); + + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample2, 0, 0); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMemAllocator_SetProperties(mem_allocator, &props, &ret_props); + todo_wine ok(hr == VFW_E_ALREADY_COMMITTED, "Got hr %#lx.\n", hr); + hr = IMemAllocator_Decommit(mem_allocator); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMemAllocator_SetProperties(mem_allocator, &props, &ret_props); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + if (media_sample3) + { + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, COMPSTAT_NOUPDATEOK, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + + ref = IMediaSample_Release(media_sample3); + ok(!ref, "Got refcount %ld.\n", ref); + + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, 0, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, COMPSTAT_NOUPDATEOK, 0); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + } + + hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample3, NULL, NULL, 0); + ok(hr == VFW_E_NOT_COMMITTED, "Got hr %#lx.\n", hr); + + ref = IMediaSample_Release(media_sample1); + ok(!ref, "Got refcount %ld.\n", ref); + + /* The sample does need to be received before it's considered updated. */ + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample1, 0, 0); + todo_wine ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + + ref = IDirectDrawStreamSample_Release(ddraw_sample1); + ok(!ref, "Got refcount %ld.\n", ref); + ref = IDirectDrawStreamSample_Release(ddraw_sample2); + ok(!ref, "Got refcount %ld.\n", ref); + ref = IDirectDrawStreamSample_Release(ddraw_sample3); + ok(!ref, "Got refcount %ld.\n", ref); + IMemAllocator_Release(mem_allocator);
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/amstream/ddrawstream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index c67bcd1fc1b..37a3094208c 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -1484,7 +1484,7 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac return E_NOTIMPL; }
-static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *sample) +static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *buffer) { struct ddraw_stream *stream = impl_from_IMemInputPin(iface); BITMAPINFOHEADER *bitmap_info; @@ -1501,13 +1501,13 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample * int stride; HRESULT hr;
- TRACE("stream %p, sample %p.\n", stream, sample); + TRACE("stream %p, buffer %p.\n", stream, buffer);
- hr = IMediaSample_GetPointer(sample, &pointer); + hr = IMediaSample_GetPointer(buffer, &pointer); if (FAILED(hr)) return hr;
- IMediaSample_GetTime(sample, &start_time, &end_time); + IMediaSample_GetTime(buffer, &start_time, &end_time);
EnterCriticalSection(&stream->cs);
From: Elizabeth Figura zfigura@codeweavers.com
This is a slightly more intuitive name. --- dlls/amstream/amstream_private.h | 1 + dlls/amstream/ddrawstream.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/amstream/amstream_private.h b/dlls/amstream/amstream_private.h index a030d8847d5..5d411c8dc71 100644 --- a/dlls/amstream/amstream_private.h +++ b/dlls/amstream/amstream_private.h @@ -22,6 +22,7 @@ #define __AMSTREAM_PRIVATE_INCLUDED__
#include <stdarg.h> +#include <stdbool.h>
#include "windef.h" #include "winbase.h" diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 37a3094208c..9292a86d7f6 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -83,7 +83,7 @@ struct ddraw_sample
struct list entry; HRESULT update_hr; - BOOL busy; + bool pending; };
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, @@ -91,7 +91,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw
static void remove_queued_update(struct ddraw_sample *sample) { - sample->busy = FALSE; + sample->pending = false; list_remove(&sample->entry); WakeConditionVariable(&sample->update_cv); if (sample->external_event) @@ -1791,7 +1791,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, LeaveCriticalSection(&sample->parent->cs); return MS_S_ENDOFSTREAM; } - if (sample->busy) + if (sample->pending) { LeaveCriticalSection(&sample->parent->cs); return MS_E_BUSY; @@ -1800,7 +1800,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, sample->continuous_update = (flags & SSUPDATE_ASYNC) && (flags & SSUPDATE_CONTINUOUS);
sample->update_hr = MS_S_NOUPDATE; - sample->busy = TRUE; + sample->pending = true; sample->external_event = event; list_add_tail(&sample->parent->update_queue, &sample->entry); WakeConditionVariable(&sample->parent->update_queued_cv); @@ -1811,7 +1811,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, return MS_S_PENDING; }
- while (sample->busy) + while (sample->pending) SleepConditionVariableCS(&sample->update_cv, &sample->parent->cs, INFINITE);
LeaveCriticalSection(&sample->parent->cs); @@ -1828,7 +1828,7 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa
EnterCriticalSection(&sample->parent->cs);
- if (sample->busy) + if (sample->pending) { if (flags & (COMPSTAT_NOUPDATEOK | COMPSTAT_ABORT)) { @@ -1839,7 +1839,7 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa DWORD start_time = GetTickCount(); DWORD elapsed = 0; sample->continuous_update = FALSE; - while (sample->busy && elapsed < milliseconds) + while (sample->pending && elapsed < milliseconds) { DWORD sleep_time = milliseconds - elapsed; if (!SleepConditionVariableCS(&sample->update_cv, &sample->parent->cs, sleep_time)) @@ -1849,7 +1849,7 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa } }
- hr = sample->busy ? MS_S_PENDING : sample->update_hr; + hr = sample->pending ? MS_S_PENDING : sample->update_hr;
LeaveCriticalSection(&sample->parent->cs);
From: Elizabeth Figura zfigura@codeweavers.com
The allocator has a lot of custom behaviour that is very visible in how it interacts with Update().
Naturally this has the benefit of writing directly into the mapped surfaces. --- dlls/amstream/ddrawstream.c | 526 +++++++++++++++++++++++++++++---- dlls/amstream/tests/amstream.c | 97 +++--- 2 files changed, 513 insertions(+), 110 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 9292a86d7f6..6e0cbb8b91e 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -56,7 +56,6 @@ struct ddraw_stream
IPin *peer; BOOL using_private_allocator; - IMemAllocator *private_allocator; AM_MEDIA_TYPE mt; struct format format; FILTER_STATE state; @@ -65,6 +64,10 @@ struct ddraw_stream BOOL flushing; CONDITION_VARIABLE update_queued_cv; struct list update_queue; + + CONDITION_VARIABLE allocator_cv; + bool committed; + LONG buffer_count; /* Only used for properties. */ };
struct ddraw_sample @@ -74,6 +77,7 @@ struct ddraw_sample struct ddraw_stream *parent; IMultiMediaStream *mmstream; IDirectDrawSurface *surface; + DDSURFACEDESC surface_desc; RECT rect; STREAM_TIME start_time; STREAM_TIME end_time; @@ -81,6 +85,10 @@ struct ddraw_sample CONDITION_VARIABLE update_cv; HANDLE external_event;
+ IMediaSample IMediaSample_iface; + unsigned int media_sample_refcount; + bool sync_point, preroll, discontinuity; + struct list entry; HRESULT update_hr; bool pending; @@ -109,7 +117,7 @@ static void flush_update_queue(struct ddraw_stream *stream, HRESULT update_hr) } }
-static HRESULT process_update(struct ddraw_sample *sample, int stride, BYTE *pointer, +static HRESULT copy_sample(struct ddraw_sample *sample, int stride, BYTE *pointer, STREAM_TIME start_time, STREAM_TIME end_time) { DDSURFACEDESC desc; @@ -236,7 +244,6 @@ static ULONG WINAPI ddraw_IAMMediaStream_Release(IAMMediaStream *iface) DeleteCriticalSection(&stream->cs); if (stream->ddraw) IDirectDraw_Release(stream->ddraw); - IMemAllocator_Release(stream->private_allocator); free(stream); }
@@ -1365,7 +1372,27 @@ static HRESULT WINAPI ddraw_mem_allocator_SetProperties(IMemAllocator *iface,
TRACE("stream %p, req_props %p, ret_props %p.\n", stream, req_props, ret_props);
- return IMemAllocator_SetProperties(stream->private_allocator, req_props, ret_props); + if (!req_props->cbAlign) + return VFW_E_BADALIGN; + + EnterCriticalSection(&stream->cs); + + if (stream->committed) + { + LeaveCriticalSection(&stream->cs); + return VFW_E_ALREADY_COMMITTED; + } + + stream->buffer_count = max(req_props->cBuffers, 1); + + ret_props->cBuffers = stream->buffer_count; + ret_props->cbBuffer = stream->format.width * stream->format.height * stream->format.pf.dwRGBBitCount / 8; + ret_props->cbAlign = 1; + ret_props->cbPrefix = 0; + + LeaveCriticalSection(&stream->cs); + + return S_OK; }
static HRESULT WINAPI ddraw_mem_allocator_GetProperties(IMemAllocator *iface, ALLOCATOR_PROPERTIES *props) @@ -1374,7 +1401,14 @@ static HRESULT WINAPI ddraw_mem_allocator_GetProperties(IMemAllocator *iface, AL
TRACE("stream %p, props %p.\n", stream, props);
- return IMemAllocator_GetProperties(stream->private_allocator, props); + EnterCriticalSection(&stream->cs); + props->cBuffers = stream->buffer_count; + props->cbBuffer = stream->format.width * stream->format.height * stream->format.pf.dwRGBBitCount / 8; + props->cbAlign = 1; + props->cbPrefix = 0; + LeaveCriticalSection(&stream->cs); + + return S_OK; }
static HRESULT WINAPI ddraw_mem_allocator_Commit(IMemAllocator *iface) @@ -1383,7 +1417,13 @@ static HRESULT WINAPI ddraw_mem_allocator_Commit(IMemAllocator *iface)
TRACE("stream %p.\n", stream);
- return IMemAllocator_Commit(stream->private_allocator); + EnterCriticalSection(&stream->cs); + stream->committed = true; + /* We have nothing to actually commit; all of our samples are created by + * CreateSample(). */ + LeaveCriticalSection(&stream->cs); + + return S_OK; }
static HRESULT WINAPI ddraw_mem_allocator_Decommit(IMemAllocator *iface) @@ -1392,30 +1432,75 @@ static HRESULT WINAPI ddraw_mem_allocator_Decommit(IMemAllocator *iface)
TRACE("stream %p.\n", stream);
- return IMemAllocator_Decommit(stream->private_allocator); + EnterCriticalSection(&stream->cs); + stream->committed = false; + /* We have nothing to actually decommit; all of our samples are created by + * CreateSample(). */ + LeaveCriticalSection(&stream->cs); + + return S_OK; +} + +static struct ddraw_sample *get_pending_sample(struct ddraw_stream *stream) +{ + struct ddraw_sample *sample; + + LIST_FOR_EACH_ENTRY(sample, &stream->update_queue, struct ddraw_sample, entry) + { + if (!sample->media_sample_refcount) + return sample; + } + + return NULL; }
static HRESULT WINAPI ddraw_mem_allocator_GetBuffer(IMemAllocator *iface, - IMediaSample **sample, REFERENCE_TIME *start, REFERENCE_TIME *end, DWORD flags) + IMediaSample **ret_sample, REFERENCE_TIME *start, REFERENCE_TIME *end, DWORD flags) { struct ddraw_stream *stream = impl_from_IMemAllocator(iface); + struct ddraw_sample *sample; HRESULT hr;
- TRACE("stream %p, sample %p, start %p, end %p, flags %#lx.\n", stream, sample, start, end, flags); + TRACE("stream %p, ret_sample %p, start %p, end %p, flags %#lx.\n", stream, ret_sample, start, end, flags); + + EnterCriticalSection(&stream->cs);
- if (FAILED(hr = IMemAllocator_GetBuffer(stream->private_allocator, sample, start, end, flags))) + if (!stream->committed) + { + LeaveCriticalSection(&stream->cs); + return VFW_E_NOT_COMMITTED; + } + + while (!(sample = get_pending_sample(stream))) + SleepConditionVariableCS(&stream->allocator_cv, &stream->cs, INFINITE); + + sample->surface_desc.dwSize = sizeof(DDSURFACEDESC); + if ((FAILED(hr = IDirectDrawSurface_Lock(sample->surface, + &sample->rect, &sample->surface_desc, DDLOCK_WAIT, NULL)))) + { + LeaveCriticalSection(&stream->cs); return hr; + } + + /* Only these fields are reset. */ + sample->sync_point = true; + sample->discontinuity = false;
- return IMediaSample_SetMediaType(*sample, &stream->mt); + sample->media_sample_refcount = 1; + + LeaveCriticalSection(&stream->cs); + + *ret_sample = &sample->IMediaSample_iface; + return S_OK; }
static HRESULT WINAPI ddraw_mem_allocator_ReleaseBuffer(IMemAllocator *iface, IMediaSample *sample) { struct ddraw_stream *stream = impl_from_IMemAllocator(iface);
- TRACE("stream %p, sample %p.\n", stream, sample); + FIXME("stream %p, sample %p, stub!\n", stream, sample);
- return IMemAllocator_ReleaseBuffer(stream->private_allocator, sample); + return E_NOTIMPL; }
static const IMemAllocatorVtbl ddraw_mem_allocator_vtbl = @@ -1484,28 +1569,69 @@ static HRESULT WINAPI ddraw_meminput_GetAllocatorRequirements(IMemInputPin *ifac return E_NOTIMPL; }
-static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *buffer) +static struct ddraw_sample *get_update_sample(struct ddraw_stream *stream, IMediaSample *buffer) { - struct ddraw_stream *stream = impl_from_IMemInputPin(iface); - BITMAPINFOHEADER *bitmap_info; - REFERENCE_TIME start_time = 0; - REFERENCE_TIME end_time = 0; - STREAM_TIME start_stream_time; - STREAM_TIME end_stream_time; - IMediaStreamFilter *filter; - STREAM_TIME current_time; + const BITMAPINFOHEADER *bitmap_info = &((VIDEOINFOHEADER *)stream->mt.pbFormat)->bmiHeader; + STREAM_TIME start_stream_time, end_stream_time; + REFERENCE_TIME start_time = 0, end_time = 0; + struct ddraw_sample *sample; BYTE *top_down_pointer; int top_down_stride; BYTE *pointer; - BOOL top_down; int stride; - HRESULT hr;
- TRACE("stream %p, buffer %p.\n", stream, buffer); + /* Is it any of the samples we gave out from GetBuffer()? */ + LIST_FOR_EACH_ENTRY(sample, &stream->update_queue, struct ddraw_sample, entry) + { + if (buffer == &sample->IMediaSample_iface) + { + sample->update_hr = S_OK; + return sample; + } + }
- hr = IMediaSample_GetPointer(buffer, &pointer); - if (FAILED(hr)) - return hr; + /* Find an unused sample and blit to it. */ + + IMediaSample_GetPointer(buffer, &pointer); + IMediaSample_GetTime(buffer, &start_time, &end_time); + + start_stream_time = start_time + stream->segment_start; + end_stream_time = end_time + stream->segment_start; + + stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) & ~31) / 8; + if (bitmap_info->biHeight < 0) + { + top_down_stride = stride; + top_down_pointer = pointer; + } + else + { + top_down_stride = -stride; + top_down_pointer = pointer + stride * (bitmap_info->biHeight - 1); + } + + LIST_FOR_EACH_ENTRY(sample, &stream->update_queue, struct ddraw_sample, entry) + { + if (!sample->media_sample_refcount) + { + sample->update_hr = copy_sample(sample, top_down_stride, top_down_pointer, + start_stream_time, end_stream_time); + return sample; + } + } + + /* We don't have a sample yet. */ + return NULL; +} + +static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *buffer) +{ + struct ddraw_stream *stream = impl_from_IMemInputPin(iface); + REFERENCE_TIME start_time = 0, end_time = 0; + IMediaStreamFilter *filter; + STREAM_TIME current_time; + + TRACE("stream %p, buffer %p.\n", stream, buffer);
IMediaSample_GetTime(buffer, &start_time, &end_time);
@@ -1522,17 +1648,6 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample * return S_FALSE; }
- 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); - - start_stream_time = start_time + stream->segment_start; - end_stream_time = end_time + stream->segment_start; - filter = stream->filter;
LeaveCriticalSection(&stream->cs); @@ -1543,6 +1658,9 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *
for (;;) { + struct ddraw_sample *sample; + IQualityControl *qc; + if (stream->state == State_Stopped) { LeaveCriticalSection(&stream->cs); @@ -1553,14 +1671,9 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample * LeaveCriticalSection(&stream->cs); return S_FALSE; } - if (!list_empty(&stream->update_queue)) - { - struct ddraw_sample *sample = LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry); - IQualityControl *qc; - - sample->update_hr = process_update(sample, top_down_stride, top_down_pointer, - start_stream_time, end_stream_time);
+ if ((sample = get_update_sample(stream, buffer))) + { if (sample->continuous_update && SUCCEEDED(sample->update_hr)) { list_remove(&sample->entry); @@ -1571,7 +1684,7 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample * remove_queued_update(sample); }
- if (S_OK == IMediaStreamFilter_GetCurrentStreamTime(filter, ¤t_time) + if (IMediaStreamFilter_GetCurrentStreamTime(filter, ¤t_time) == S_OK && SUCCEEDED(IPin_QueryInterface(stream->peer, &IID_IQualityControl, (void **)&qc))) { Quality q; @@ -1620,7 +1733,6 @@ static const IMemInputPinVtbl ddraw_meminput_vtbl = HRESULT ddraw_stream_create(IUnknown *outer, void **out) { struct ddraw_stream *object; - HRESULT hr;
if (outer) return CLASS_E_NOAGGREGATION; @@ -1640,12 +1752,8 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out) object->format.height = 100;
object->using_private_allocator = TRUE; - if (FAILED(hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, - &IID_IMemAllocator, (void **)&object->private_allocator))) - { - free(object); - return hr; - } + InitializeConditionVariable(&object->allocator_cv); + object->buffer_count = 1;
InitializeCriticalSection(&object->cs); InitializeConditionVariable(&object->update_queued_cv); @@ -1704,6 +1812,10 @@ static ULONG WINAPI ddraw_sample_Release(IDirectDrawStreamSample *iface) if (!ref) { EnterCriticalSection(&sample->parent->cs); + + while (sample->media_sample_refcount) + SleepConditionVariableCS(&sample->parent->allocator_cv, &sample->parent->cs, INFINITE); + --sample->parent->sample_refs; LeaveCriticalSection(&sample->parent->cs);
@@ -1791,7 +1903,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, LeaveCriticalSection(&sample->parent->cs); return MS_S_ENDOFSTREAM; } - if (sample->pending) + if (sample->pending || sample->media_sample_refcount) { LeaveCriticalSection(&sample->parent->cs); return MS_E_BUSY; @@ -1804,6 +1916,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, sample->external_event = event; list_add_tail(&sample->parent->update_queue, &sample->entry); WakeConditionVariable(&sample->parent->update_queued_cv); + WakeConditionVariable(&sample->parent->allocator_cv);
if ((flags & SSUPDATE_ASYNC) || event) { @@ -1811,7 +1924,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface, return MS_S_PENDING; }
- while (sample->pending) + while (sample->pending || sample->media_sample_refcount) SleepConditionVariableCS(&sample->update_cv, &sample->parent->cs, INFINITE);
LeaveCriticalSection(&sample->parent->cs); @@ -1828,18 +1941,19 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa
EnterCriticalSection(&sample->parent->cs);
- if (sample->pending) + if (sample->pending || sample->media_sample_refcount) { if (flags & (COMPSTAT_NOUPDATEOK | COMPSTAT_ABORT)) { - remove_queued_update(sample); + if (!sample->media_sample_refcount) + remove_queued_update(sample); } else if (flags & COMPSTAT_WAIT) { DWORD start_time = GetTickCount(); DWORD elapsed = 0; sample->continuous_update = FALSE; - while (sample->pending && elapsed < milliseconds) + while ((sample->pending || sample->media_sample_refcount) && elapsed < milliseconds) { DWORD sleep_time = milliseconds - elapsed; if (!SleepConditionVariableCS(&sample->update_cv, &sample->parent->cs, sleep_time)) @@ -1849,7 +1963,10 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa } }
- hr = sample->pending ? MS_S_PENDING : sample->update_hr; + if (sample->pending || sample->media_sample_refcount) + hr = MS_S_PENDING; + else + hr = sample->update_hr;
LeaveCriticalSection(&sample->parent->cs);
@@ -1901,6 +2018,294 @@ static const struct IDirectDrawStreamSampleVtbl DirectDrawStreamSample_Vtbl = ddraw_sample_SetRect };
+static struct ddraw_sample *impl_from_IMediaSample(IMediaSample *iface) +{ + return CONTAINING_RECORD(iface, struct ddraw_sample, IMediaSample_iface); +} + +static HRESULT WINAPI media_sample_QueryInterface(IMediaSample *iface, REFIID iid, void **out) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, iid %s, out %p.\n", sample, debugstr_guid(iid), out); + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IMediaSample)) + { + IMediaSample_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_sample_AddRef(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + ULONG refcount; + + EnterCriticalSection(&sample->parent->cs); + refcount = ++sample->media_sample_refcount; + LeaveCriticalSection(&sample->parent->cs); + + TRACE("%p increasing refcount to %lu.\n", sample, refcount); + + return refcount; +} + +static ULONG WINAPI media_sample_Release(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + ULONG refcount; + + EnterCriticalSection(&sample->parent->cs); + + /* This is not InterlockedDecrement(), because it's used in GetBuffer() + * among other functions and therefore needs to be protected by the CS + * anyway. */ + refcount = --sample->media_sample_refcount; + + TRACE("%p decreasing refcount to %lu.\n", sample, refcount); + + if (!refcount) + { + IDirectDrawSurface_Unlock(sample->surface, NULL); + + WakeConditionVariable(&sample->update_cv); + + /* This sample is not released back to the pool if it's no longer + * pending an update. + * + * Use WakeAll, even though we're only releasing one sample, because we + * also potentially need to wake up a thread stuck in + * IDirectDrawStreamSample::Release(). + * This is arguably wasteful, but in practice we're unlikely to have + * more than one thread in GetBuffer() at a time anyway. */ + if (sample->pending) + WakeAllConditionVariable(&sample->parent->allocator_cv); + } + + LeaveCriticalSection(&sample->parent->cs); + return refcount; +} + +static unsigned int get_sample_size(struct ddraw_sample *sample) +{ + return sample->surface_desc.lPitch * sample->surface_desc.dwHeight; +} + +static HRESULT WINAPI media_sample_GetPointer(IMediaSample *iface, BYTE **data) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, data %p.\n", sample, data); + + *data = sample->surface_desc.lpSurface; + return S_OK; +} + +static LONG WINAPI media_sample_GetSize(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p.\n", sample); + + return get_sample_size(sample); +} + +static HRESULT WINAPI media_sample_GetTime(IMediaSample *iface, REFERENCE_TIME *start, REFERENCE_TIME *end) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, start %p, end %p.\n", sample, start, end); + + EnterCriticalSection(&sample->parent->cs); + *start = sample->start_time; + *end = sample->end_time; + LeaveCriticalSection(&sample->parent->cs); + + return S_OK; +} + +static HRESULT WINAPI media_sample_SetTime(IMediaSample *iface, REFERENCE_TIME *start, REFERENCE_TIME *end) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, start %p, end %p.\n", sample, start, end); + + EnterCriticalSection(&sample->parent->cs); + if (start) + sample->start_time = *start; + if (end) + sample->end_time = *end; + LeaveCriticalSection(&sample->parent->cs); + + return S_OK; +} + +static HRESULT WINAPI media_sample_IsSyncPoint(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + HRESULT hr; + + TRACE("sample %p.\n", sample); + + EnterCriticalSection(&sample->parent->cs); + hr = sample->sync_point ? S_OK : S_FALSE; + LeaveCriticalSection(&sample->parent->cs); + + return hr; +} + +static HRESULT WINAPI media_sample_SetSyncPoint(IMediaSample *iface, BOOL sync_point) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, sync_point %d.\n", sample, sync_point); + + EnterCriticalSection(&sample->parent->cs); + sample->sync_point = sync_point; + LeaveCriticalSection(&sample->parent->cs); + + return S_OK; +} + +static HRESULT WINAPI media_sample_IsPreroll(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + HRESULT hr; + + TRACE("sample %p.\n", sample); + + EnterCriticalSection(&sample->parent->cs); + hr = sample->preroll ? S_OK : S_FALSE; + LeaveCriticalSection(&sample->parent->cs); + + return hr; +} + +static HRESULT WINAPI media_sample_SetPreroll(IMediaSample *iface, BOOL preroll) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, preroll %d.\n", sample, preroll); + + EnterCriticalSection(&sample->parent->cs); + sample->preroll = preroll; + LeaveCriticalSection(&sample->parent->cs); + + return S_OK; +} + +static LONG WINAPI media_sample_GetActualDataLength(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p.\n", sample); + + return get_sample_size(sample); +} + +static HRESULT WINAPI media_sample_SetActualDataLength(IMediaSample *iface, LONG length) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, length %ld.\n", sample, length); + + return (length == get_sample_size(sample) ? S_OK : E_FAIL); +} + +static HRESULT WINAPI media_sample_GetMediaType(IMediaSample *iface, AM_MEDIA_TYPE **ret_mt) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, ret_mt %p.\n", sample, ret_mt); + + if (!(*ret_mt = CreateMediaType(&sample->parent->mt))) + return E_OUTOFMEMORY; + return S_OK; +} + +static HRESULT WINAPI media_sample_SetMediaType(IMediaSample *iface, AM_MEDIA_TYPE *mt) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + FIXME("sample %p, mt %p, stub!\n", sample, mt); + strmbase_dump_media_type(mt); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_sample_IsDiscontinuity(IMediaSample *iface) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + HRESULT hr; + + TRACE("sample %p.\n", sample); + + EnterCriticalSection(&sample->parent->cs); + hr = sample->discontinuity ? S_OK : S_FALSE; + LeaveCriticalSection(&sample->parent->cs); + + return hr; +} + +static HRESULT WINAPI media_sample_SetDiscontinuity(IMediaSample *iface, BOOL discontinuity) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, discontinuity %d.\n", sample, discontinuity); + + EnterCriticalSection(&sample->parent->cs); + sample->discontinuity = discontinuity; + LeaveCriticalSection(&sample->parent->cs); + + return S_OK; +} + +static HRESULT WINAPI media_sample_GetMediaTime(IMediaSample *iface, LONGLONG *start, LONGLONG *end) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, start %p, end %p, not implemented.\n", sample, start, end); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_sample_SetMediaTime(IMediaSample *iface, LONGLONG *start, LONGLONG *end) +{ + struct ddraw_sample *sample = impl_from_IMediaSample(iface); + + TRACE("sample %p, start %p, end %p, not implemented.\n", sample, start, end); + + return E_NOTIMPL; +} + +static const struct IMediaSampleVtbl media_sample_vtbl = +{ + media_sample_QueryInterface, + media_sample_AddRef, + media_sample_Release, + media_sample_GetPointer, + media_sample_GetSize, + media_sample_GetTime, + media_sample_SetTime, + media_sample_IsSyncPoint, + media_sample_SetSyncPoint, + media_sample_IsPreroll, + media_sample_SetPreroll, + media_sample_GetActualDataLength, + media_sample_SetActualDataLength, + media_sample_GetMediaType, + media_sample_SetMediaType, + media_sample_IsDiscontinuity, + media_sample_SetDiscontinuity, + media_sample_GetMediaTime, + media_sample_SetMediaTime, +}; + static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample) { @@ -1914,6 +2319,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw return E_OUTOFMEMORY;
object->IDirectDrawStreamSample_iface.lpVtbl = &DirectDrawStreamSample_Vtbl; + object->IMediaSample_iface.lpVtbl = &media_sample_vtbl; object->ref = 1; object->parent = parent; object->mmstream = parent->parent; diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 89e6102deab..24a90cce0d1 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -8554,8 +8554,8 @@ static void test_ddrawstream_mem_allocator(void) hr = IMemAllocator_GetProperties(ddraw_allocator, &props); ok(hr == S_OK, "Got hr %#lx.\n", hr); todo_wine ok(props.cbBuffer == 10000, "Got size %ld.\n", props.cbBuffer); - todo_wine ok(props.cBuffers == 1, "Got %ld buffers\n", props.cBuffers); - todo_wine ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + ok(props.cBuffers == 1, "Got %ld buffers\n", props.cBuffers); + ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix);
/* Try changing allocator properties. */ @@ -8567,8 +8567,8 @@ static void test_ddrawstream_mem_allocator(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); todo_wine ok(ret_props.cbBuffer == 10000, "Got size %ld.\n", ret_props.cbBuffer); ok(ret_props.cBuffers == 4, "Got %ld buffers.\n", ret_props.cBuffers); - todo_wine ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); - todo_wine ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix); + ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); + ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix);
/* Check how allocator properties change when setting a new format. */ hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); @@ -8576,10 +8576,10 @@ static void test_ddrawstream_mem_allocator(void)
hr = IMemAllocator_GetProperties(ddraw_allocator, &props); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(props.cbBuffer == 40000, "Got size %ld.\n", props.cbBuffer); + ok(props.cbBuffer == 40000, "Got size %ld.\n", props.cbBuffer); ok(props.cBuffers == 4, "Got %ld buffers.\n", props.cBuffers); - todo_wine ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); - todo_wine ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix); + ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix);
props.cbAlign = 0; props.cbBuffer = 1000; @@ -8594,8 +8594,8 @@ static void test_ddrawstream_mem_allocator(void) props.cbPrefix = 0; hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); - todo_wine ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); + ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); + ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix);
@@ -8606,7 +8606,7 @@ static void test_ddrawstream_mem_allocator(void) props.cbPrefix = 0; hr = IMemAllocator_SetProperties(ddraw_allocator, &props, &ret_props); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); + ok(ret_props.cbBuffer == 40000, "Got size %ld.\n", ret_props.cbBuffer); ok(ret_props.cBuffers == 1, "Got %ld buffers.\n", ret_props.cBuffers); ok(ret_props.cbAlign == 1, "Got alignment %ld.\n", ret_props.cbAlign); ok(!ret_props.cbPrefix, "Got prefix %ld.\n", ret_props.cbPrefix); @@ -8622,7 +8622,7 @@ static void test_ddrawstream_mem_allocator(void)
hr = IMemAllocator_GetProperties(ddraw_allocator, &props); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(props.cbBuffer == 20000, "Got size %ld.\n", props.cbBuffer); + ok(props.cbBuffer == 20000, "Got size %ld.\n", props.cbBuffer); ok(props.cBuffers == 1, "Got %ld buffers.\n", props.cBuffers); ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix); @@ -8700,7 +8700,7 @@ static void test_ddrawstream_mem_allocator(void)
hr = IMemAllocator_GetProperties(ddraw_allocator, &props); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(props.cbBuffer == 333 * 444 * 4, "Got size %ld.\n", props.cbBuffer); + ok(props.cbBuffer == 333 * 444 * 4, "Got size %ld.\n", props.cbBuffer); ok(props.cBuffers == 2, "Got %ld buffers.\n", props.cBuffers); ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign); ok(!props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix); @@ -8746,7 +8746,7 @@ static void test_ddrawstream_mem_allocator(void)
sample_mt->lSampleSize = 123; hr = IMediaSample_SetMediaType(media_sample1, sample_mt); - ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr);
DeleteMediaType(sample_mt);
@@ -8774,44 +8774,44 @@ static void test_ddrawstream_mem_allocator(void) DeleteMediaType(sample_mt);
hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample3, NULL, NULL, AM_GBF_NOWAIT); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
/* GetBuffer() again blocks, even with AM_GBF_NOWAIT. */
ok(media_sample1 != media_sample2, "Expected different samples.\n");
check_interface(media_sample1, &IID_IDirectDrawStreamSample, FALSE); - todo_wine check_interface(media_sample1, &IID_IMediaSample2, FALSE); + check_interface(media_sample1, &IID_IMediaSample2, FALSE);
hr = IMemAllocator_GetProperties(ddraw_allocator, &props); ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(props.cBuffers == 2, "Expected 2 samples got %ld\n", props.cBuffers);
size = IMediaSample_GetSize(media_sample1); - todo_wine ok(size == 336 * 444 * 2, "Got size %ld.\n", size); + ok(size == 336 * 444 * 2, "Got size %ld.\n", size); size = IMediaSample_GetActualDataLength(media_sample1); - todo_wine ok(size == 336 * 444 * 2, "Got size %ld.\n", size); + ok(size == 336 * 444 * 2, "Got size %ld.\n", size); hr = IMediaSample_SetActualDataLength(media_sample1, size); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_SetActualDataLength(media_sample1, size + 1); - todo_wine ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + ok(hr == E_FAIL, "Got hr %#lx.\n", hr); hr = IMediaSample_SetActualDataLength(media_sample1, size - 1); - todo_wine ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
start = end = 0xdeadbeef; hr = IMediaSample_GetTime(media_sample1, &start, &end); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(!start, "Got start %I64d.\n", start); - todo_wine ok(!end, "Got end %I64d.\n", end); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(!start, "Got start %I64d.\n", start); + ok(!end, "Got end %I64d.\n", end);
start = end = 0xdeadbeef; hr = IMediaSample_GetMediaTime(media_sample1, &start, &end); - todo_wine ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); + ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); ok(start == 0xdeadbeef, "Got start %I64d.\n", start); ok(end == 0xdeadbeef, "Got end %I64d.\n", end);
hr = IMediaSample_IsSyncPoint(media_sample1); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_IsPreroll(media_sample1); ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IMediaSample_IsDiscontinuity(media_sample1); @@ -8820,7 +8820,7 @@ static void test_ddrawstream_mem_allocator(void) start = 123; end = 456; hr = IMediaSample_SetMediaTime(media_sample1, &start, &end); - todo_wine ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); + ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); hr = IMediaSample_SetTime(media_sample1, &start, &end); ok(hr == S_OK, "Got hr %#lx.\n", hr); start = end = 0xdeadbeef; @@ -8841,15 +8841,15 @@ static void test_ddrawstream_mem_allocator(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); start = end = 0xdeadbeef; hr = IMediaSample_GetTime(media_sample1, &start, &end); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(start == 555, "Got start %I64d.\n", start); - todo_wine ok(end == 666, "Got end %I64d.\n", end); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(start == 555, "Got start %I64d.\n", start); + ok(end == 666, "Got end %I64d.\n", end);
start = end = 0xdeadbeef; hr = IDirectDrawStreamSample_GetSampleTimes(ddraw_sample1, &start, &end, NULL); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(start == 555, "Got start %I64d.\n", start); - todo_wine ok(end == 666, "Got end %I64d.\n", end); + ok(start == 555, "Got start %I64d.\n", start); + ok(end == 666, "Got end %I64d.\n", end);
hr = IMediaSample_SetSyncPoint(media_sample1, FALSE); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -8873,13 +8873,13 @@ static void test_ddrawstream_mem_allocator(void)
start = end = 0xdeadbeef; hr = IMediaSample_GetTime(media_sample1, &start, &end); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(start == 555, "Got start %I64d.\n", start); - todo_wine ok(end == 666, "Got end %I64d.\n", end); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(start == 555, "Got start %I64d.\n", start); + ok(end == 666, "Got end %I64d.\n", end); hr = IMediaSample_IsSyncPoint(media_sample1); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_IsPreroll(media_sample1); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_IsDiscontinuity(media_sample1); ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
@@ -8898,28 +8898,25 @@ static void test_ddrawstream_mem_allocator(void) ok(!ref, "Got refcount %ld.\n", ref);
hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample2, 0, 0); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IMemAllocator_SetProperties(mem_allocator, &props, &ret_props); - todo_wine ok(hr == VFW_E_ALREADY_COMMITTED, "Got hr %#lx.\n", hr); + ok(hr == VFW_E_ALREADY_COMMITTED, "Got hr %#lx.\n", hr); hr = IMemAllocator_Decommit(mem_allocator); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMemAllocator_SetProperties(mem_allocator, &props, &ret_props); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
- if (media_sample3) - { - hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, COMPSTAT_NOUPDATEOK, 0); - ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, COMPSTAT_NOUPDATEOK, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
- ref = IMediaSample_Release(media_sample3); - ok(!ref, "Got refcount %ld.\n", ref); + ref = IMediaSample_Release(media_sample3); + ok(!ref, "Got refcount %ld.\n", ref);
- hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, 0, 0); - ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); - hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, COMPSTAT_NOUPDATEOK, 0); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - } + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, 0, 0); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample3, COMPSTAT_NOUPDATEOK, 0); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IMemAllocator_GetBuffer(mem_allocator, &media_sample3, NULL, NULL, 0); ok(hr == VFW_E_NOT_COMMITTED, "Got hr %#lx.\n", hr); @@ -8929,7 +8926,7 @@ static void test_ddrawstream_mem_allocator(void)
/* The sample does need to be received before it's considered updated. */ hr = IDirectDrawStreamSample_CompletionStatus(ddraw_sample1, 0, 0); - todo_wine ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr); + ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
ref = IDirectDrawStreamSample_Release(ddraw_sample1); ok(!ref, "Got refcount %ld.\n", ref);
From: Santino Mazza smazza@codeweavers.com
--- dlls/amstream/ddrawstream.c | 7 +++++++ dlls/amstream/tests/amstream.c | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 6e0cbb8b91e..4e0b1323619 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -684,6 +684,13 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr
if (stream->peer && !is_format_compatible(stream, old_format.width, old_format.height, &old_format.pf)) { + if (stream->sample_refs > 0) + { + stream->format = old_format; + LeaveCriticalSection(&stream->cs); + return MS_E_SAMPLEALLOC; + } + if (FAILED(hr = CopyMediaType(&old_media_type, &stream->mt))) { stream->format = old_format; diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 24a90cce0d1..0991e902dcc 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -8712,7 +8712,7 @@ static void test_ddrawstream_mem_allocator(void) ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); - todo_wine ok(hr == MS_E_SAMPLEALLOC, "Got hr %#lx.\n", hr); + ok(hr == MS_E_SAMPLEALLOC, "Got hr %#lx.\n", hr);
/* We cannot retrieve the sample from GetBuffer() without calling Update(). * Otherwise GetBuffer() will hang as there are no samples to return. */ @@ -8733,7 +8733,7 @@ static void test_ddrawstream_mem_allocator(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(IsEqualGUID(&sample_mt->majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&sample_mt->majortype)); - todo_wine ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), + ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), "Got subtype %s.\n", debugstr_guid(&sample_mt->subtype)); todo_wine ok(sample_mt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", sample_mt->bFixedSizeSamples); ok(!sample_mt->bTemporalCompression, "Got temporal compression %d.\n", sample_mt->bTemporalCompression); @@ -8769,7 +8769,7 @@ static void test_ddrawstream_mem_allocator(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IMediaSample_GetMediaType(media_sample2, &sample_mt); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), + ok(IsEqualGUID(&sample_mt->subtype, &MEDIASUBTYPE_RGB555), "Got subtype %s.\n", wine_dbgstr_guid(&sample_mt->subtype)); DeleteMediaType(sample_mt);
This merge request was approved by Elizabeth Figura.
Anton Baskanov (@baskanov) commented about dlls/amstream/ddrawstream.c:
- start_stream_time = start_time + stream->segment_start;
- end_stream_time = end_time + stream->segment_start;
- stride = ((bitmap_info->biWidth * bitmap_info->biBitCount + 31) & ~31) / 8;
- if (bitmap_info->biHeight < 0)
- {
top_down_stride = stride;
top_down_pointer = pointer;
- }
- else
- {
top_down_stride = -stride;
top_down_pointer = pointer + stride * (bitmap_info->biHeight - 1);
- }
- LIST_FOR_EACH_ENTRY(sample, &stream->update_queue, struct ddraw_sample, entry)
Can't we use `get_pending_sample` here?