From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/quartz/avidec.c | 76 +++++++++++++++++++++++++++++++------- dlls/quartz/tests/avidec.c | 10 ++--- 2 files changed, 66 insertions(+), 20 deletions(-)
diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index e4ff86599ab..0bb526b6d65 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -47,7 +47,7 @@ struct avi_decompressor struct strmbase_sink sink;
HIC hvid; - BITMAPINFOHEADER *input_format; + BITMAPINFOHEADER *input_format, *output_format;
CRITICAL_SECTION late_cs; REFERENCE_TIME late; @@ -130,13 +130,13 @@ static int AVIDec_DropSample(struct avi_decompressor *This, REFERENCE_TIME tStar static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface, IMediaSample *pSample) { struct avi_decompressor *This = impl_from_strmbase_filter(iface->pin.filter); - VIDEOINFOHEADER *source_format; HRESULT hr; IMediaSample* pOutSample = NULL; LONG cbDstStream, cbSrcStream; LPBYTE pbDstStream; LPBYTE pbSrcStream; LONGLONG tStart, tStop; + AM_MEDIA_TYPE *mt; DWORD flags = 0; LRESULT res;
@@ -150,8 +150,6 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface, return VFW_E_NOT_CONNECTED; }
- source_format = (VIDEOINFOHEADER *)This->source.pin.mt.pbFormat; - if (This->filter.state == State_Stopped) return VFW_E_WRONG_STATE;
@@ -176,6 +174,46 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface, return hr; }
+ /* Handle dynamic format change. */ + if ((hr = IMediaSample_GetMediaType(pOutSample, &mt)) == S_OK) + { + if (!memcmp(This->output_format, get_bitmap_header(mt), get_bitmap_info_size(This->output_format))) + { + DeleteMediaType(mt); + } + else + { + if ((res = ICDecompressEnd(This->hvid))) + { + DeleteMediaType(mt); + ERR("ICDecompressEnd() failed, error %Id.\n", res); + IMediaSample_Release(pOutSample); + return E_FAIL; + } + + free(This->output_format); + if (!(This->output_format = copy_bitmap_header(mt))) + { + DeleteMediaType(mt); + IMediaSample_Release(pOutSample); + return E_OUTOFMEMORY; + } + + DeleteMediaType(mt); + + if ((res = ICDecompressBegin(This->hvid, This->input_format, This->output_format))) + { + ERR("ICDecompressBegin() failed, error %Id.\n", res); + IMediaSample_Release(pOutSample); + return E_FAIL; + } + } + } + else if (hr != S_FALSE) + { + ERR("Failed to get media type, hr %#lx.\n", hr); + } + hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); if (FAILED(hr)) { ERR("Failed to get output buffer pointer, hr %#lx.\n", hr); @@ -183,9 +221,9 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface, return hr; } cbDstStream = IMediaSample_GetSize(pOutSample); - if (cbDstStream < source_format->bmiHeader.biSizeImage) + if (cbDstStream < This->output_format->biSizeImage) { - ERR("Sample size is too small (%ld < %lu).\n", cbDstStream, source_format->bmiHeader.biSizeImage); + ERR("Sample size is too small (%ld < %lu).\n", cbDstStream, This->output_format->biSizeImage); IMediaSample_Release(pOutSample); return E_FAIL; } @@ -200,7 +238,7 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface, flags |= ICDECOMPRESS_HURRYUP; LeaveCriticalSection(&This->late_cs);
- res = ICDecompress(This->hvid, flags, This->input_format, pbSrcStream, &source_format->bmiHeader, pbDstStream); + res = ICDecompress(This->hvid, flags, This->input_format, pbSrcStream, This->output_format, pbDstStream); if (res != ICERR_OK) ERR("Failed to decompress, error %Id.\n", res);
@@ -210,7 +248,7 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface, return S_OK; }
- IMediaSample_SetActualDataLength(pOutSample, source_format->bmiHeader.biSizeImage); + IMediaSample_SetActualDataLength(pOutSample, This->output_format->biSizeImage);
IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK)); IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK)); @@ -447,14 +485,17 @@ static HRESULT avi_decompressor_source_get_media_type(struct strmbase_pin *iface static HRESULT WINAPI avi_decompressor_source_DecideBufferSize(struct strmbase_source *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) { - const VIDEOINFOHEADER *source_format = (VIDEOINFOHEADER *)iface->pin.mt.pbFormat; + struct avi_decompressor *filter = impl_from_strmbase_filter(iface->pin.filter); ALLOCATOR_PROPERTIES actual;
+ if (!(filter->output_format = copy_bitmap_header(&iface->pin.mt))) + return E_OUTOFMEMORY; + if (!ppropInputRequest->cbAlign) ppropInputRequest->cbAlign = 1;
- if (ppropInputRequest->cbBuffer < source_format->bmiHeader.biSizeImage) - ppropInputRequest->cbBuffer = source_format->bmiHeader.biSizeImage; + if (ppropInputRequest->cbBuffer < filter->output_format->biSizeImage) + ppropInputRequest->cbBuffer = filter->output_format->biSizeImage;
if (!ppropInputRequest->cBuffers) ppropInputRequest->cBuffers = 1; @@ -462,6 +503,14 @@ static HRESULT WINAPI avi_decompressor_source_DecideBufferSize(struct strmbase_s return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual); }
+static void avi_decompressor_source_disconnect(struct strmbase_source *iface) +{ + struct avi_decompressor *filter = impl_from_strmbase_filter(iface->pin.filter); + + free(filter->output_format); + filter->output_format = NULL; +} + static const struct strmbase_source_ops source_ops = { .base.pin_query_interface = avi_decompressor_source_query_interface, @@ -470,6 +519,7 @@ static const struct strmbase_source_ops source_ops = .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, .pfnDecideBufferSize = avi_decompressor_source_DecideBufferSize, + .source_disconnect = avi_decompressor_source_disconnect, };
static struct avi_decompressor *impl_from_source_IQualityControl(IQualityControl *iface) @@ -569,7 +619,6 @@ static void avi_decompressor_destroy(struct strmbase_filter *iface) static HRESULT avi_decompressor_init_stream(struct strmbase_filter *iface) { struct avi_decompressor *filter = impl_from_strmbase_filter(iface); - VIDEOINFOHEADER *source_format; LRESULT res; HRESULT hr;
@@ -580,8 +629,7 @@ static HRESULT avi_decompressor_init_stream(struct strmbase_filter *iface) filter->late = -1; LeaveCriticalSection(&filter->late_cs);
- source_format = (VIDEOINFOHEADER *)filter->source.pin.mt.pbFormat; - if ((res = ICDecompressBegin(filter->hvid, filter->input_format, &source_format->bmiHeader))) + if ((res = ICDecompressBegin(filter->hvid, filter->input_format, filter->output_format))) { ERR("ICDecompressBegin() failed, error %Id.\n", res); return E_FAIL; diff --git a/dlls/quartz/tests/avidec.c b/dlls/quartz/tests/avidec.c index 902b1566638..4a0f731fc66 100644 --- a/dlls/quartz/tests/avidec.c +++ b/dlls/quartz/tests/avidec.c @@ -153,9 +153,8 @@ static LRESULT CALLBACK vfw_driver_proc(DWORD_PTR id, HDRVR driver, UINT msg, expect_sink_format.biSizeImage = 200; ok(!memcmp(params->lpbiInput, &expect_sink_format, sizeof(BITMAPINFOHEADER)), "Input types didn't match.\n"); - todo_wine_if (testmode == 8) - ok(!memcmp(params->lpbiOutput, &source_bitmap_info, sizeof(BITMAPINFOHEADER)), - "Output types didn't match.\n"); + ok(!memcmp(params->lpbiOutput, &source_bitmap_info, sizeof(BITMAPINFOHEADER)), + "Output types didn't match.\n"); ok(!params->ckid, "Got chunk id %#lx.\n", params->ckid);
for (i = 0; i < 200; ++i) @@ -911,8 +910,7 @@ static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample else ok(size == source_bitmap_info.biSizeImage, "Got size %lu.\n", size); size = IMediaSample_GetActualDataLength(sample); - todo_wine_if (testmode == 8) - ok(size == source_bitmap_info.biSizeImage, "Got valid size %lu.\n", size); + ok(size == source_bitmap_info.biSizeImage, "Got valid size %lu.\n", size);
hr = IMediaSample_GetPointer(sample, &data); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -1098,7 +1096,7 @@ static HRESULT WINAPI sample_SetActualDataLength(IMediaSample *iface, LONG size)
if (winetest_debug > 1) trace("SetActualDataLength(%ld)\n", size);
- todo_wine ok(size == 222, "Got size %ld.\n", size); + ok(size == 222, "Got size %ld.\n", size);
IMediaSample_SetActualDataLength(filter->wrapped_sample, size); return E_FAIL;