Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/quartz/avidec.c | 105 +++++++++++++++++++++++++++++++++++-- dlls/quartz/tests/avidec.c | 19 +++++-- 2 files changed, 116 insertions(+), 8 deletions(-)
diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index 0837ae2b8da..7645b17558b 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -362,12 +362,111 @@ static HRESULT avi_decompressor_source_query_accept(struct strmbase_pin *iface, static HRESULT avi_decompressor_source_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt) { + static const struct + { + const GUID *subtype; + DWORD compression; + WORD bpp; + } + formats[] = + { + {&MEDIASUBTYPE_CLJR, mmioFOURCC('C','L','J','R'), 8}, + {&MEDIASUBTYPE_UYVY, mmioFOURCC('U','Y','V','Y'), 16}, + {&MEDIASUBTYPE_YUY2, mmioFOURCC('Y','U','Y','2'), 16}, + {&MEDIASUBTYPE_RGB32, BI_RGB, 32}, + {&MEDIASUBTYPE_RGB24, BI_RGB, 24}, + {&MEDIASUBTYPE_RGB565, BI_BITFIELDS, 16}, + {&MEDIASUBTYPE_RGB555, BI_RGB, 16}, + {&MEDIASUBTYPE_RGB8, BI_RGB, 8}, + }; + AVIDecImpl *filter = impl_from_strmbase_filter(iface->filter); + const VIDEOINFOHEADER *sink_format; + VIDEOINFO *format;
- if (index) + if (!filter->sink.pin.peer) return VFW_S_NO_MORE_ITEMS; - CopyMediaType(mt, &filter->mt); - return S_OK; + + sink_format = (VIDEOINFOHEADER *)filter->sink.pin.mt.pbFormat; + + memset(mt, 0, sizeof(AM_MEDIA_TYPE)); + + if (index < ARRAY_SIZE(formats)) + { + if (!(format = CoTaskMemAlloc(offsetof(VIDEOINFO, dwBitMasks[3])))) + return E_OUTOFMEMORY; + memset(format, 0, offsetof(VIDEOINFO, dwBitMasks[3])); + + format->rcSource = sink_format->rcSource; + format->rcTarget = sink_format->rcTarget; + format->dwBitRate = sink_format->dwBitRate; + format->dwBitErrorRate = sink_format->dwBitErrorRate; + format->AvgTimePerFrame = sink_format->AvgTimePerFrame; + + format->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + format->bmiHeader.biWidth = sink_format->bmiHeader.biWidth; + format->bmiHeader.biHeight = sink_format->bmiHeader.biHeight; + format->bmiHeader.biPlanes = sink_format->bmiHeader.biPlanes; + format->bmiHeader.biBitCount = formats[index].bpp; + format->bmiHeader.biCompression = formats[index].compression; + format->bmiHeader.biSizeImage = format->bmiHeader.biWidth + * format->bmiHeader.biHeight * formats[index].bpp / 8; + + if (IsEqualGUID(formats[index].subtype, &MEDIASUBTYPE_RGB565)) + { + format->dwBitMasks[iRED] = 0xf800; + format->dwBitMasks[iGREEN] = 0x07e0; + format->dwBitMasks[iBLUE] = 0x001f; + mt->cbFormat = offsetof(VIDEOINFO, dwBitMasks[3]); + } + else + mt->cbFormat = sizeof(VIDEOINFOHEADER); + + mt->majortype = MEDIATYPE_Video; + mt->subtype = *formats[index].subtype; + mt->bFixedSizeSamples = TRUE; + mt->lSampleSize = format->bmiHeader.biSizeImage; + mt->formattype = FORMAT_VideoInfo; + mt->pbFormat = (BYTE *)format; + + return S_OK; + } + + if (index == ARRAY_SIZE(formats)) + { + size_t size = ICDecompressGetFormatSize(filter->hvid, &sink_format->bmiHeader); + + if (!size) + return VFW_S_NO_MORE_ITEMS; + + mt->cbFormat = offsetof(VIDEOINFOHEADER, bmiHeader) + size; + if (!(format = CoTaskMemAlloc(mt->cbFormat))) + return E_OUTOFMEMORY; + + format->rcSource = sink_format->rcSource; + format->rcTarget = sink_format->rcTarget; + format->dwBitRate = sink_format->dwBitRate; + format->dwBitErrorRate = sink_format->dwBitErrorRate; + format->AvgTimePerFrame = sink_format->AvgTimePerFrame; + + if (ICDecompressGetFormat(filter->hvid, &sink_format->bmiHeader, &format->bmiHeader)) + { + CoTaskMemFree(format); + return VFW_S_NO_MORE_ITEMS; + } + + mt->majortype = MEDIATYPE_Video; + mt->subtype = MEDIATYPE_Video; + mt->subtype.Data1 = format->bmiHeader.biCompression; + mt->bFixedSizeSamples = TRUE; + mt->lSampleSize = format->bmiHeader.biSizeImage; + mt->formattype = FORMAT_VideoInfo; + mt->pbFormat = (BYTE *)format; + + return S_OK; + } + + return VFW_S_NO_MORE_ITEMS; }
static HRESULT WINAPI avi_decompressor_source_DecideBufferSize(struct strmbase_source *iface, diff --git a/dlls/quartz/tests/avidec.c b/dlls/quartz/tests/avidec.c index 725e034ae27..6c29d33df29 100644 --- a/dlls/quartz/tests/avidec.c +++ b/dlls/quartz/tests/avidec.c @@ -584,7 +584,7 @@ static void test_media_types(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr);
IEnumMediaTypes_Release(enummt); IPin_Release(pin); @@ -639,7 +639,7 @@ static void test_enum_media_types(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr);
hr = IEnumMediaTypes_Next(enum1, 1, mts, &count); ok(hr == S_FALSE, "Got hr %#x.\n", hr); @@ -649,7 +649,7 @@ static void test_enum_media_types(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr);
hr = IEnumMediaTypes_Clone(enum1, &enum2); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -970,11 +970,11 @@ static void test_connect_pin(void) ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n"); ok(compare_media_types(&testsource.source.pin.mt, &req_mt), "Media types didn't match.\n");
+ sink_bih = req_format.bmiHeader; + hr = IPin_EnumMediaTypes(source, &enummt); ok(hr == S_OK, "Got hr %#x.\n", hr);
- sink_bih = req_format.bmiHeader; - for (i = 0; i < 9; ++i) { static const struct @@ -1023,6 +1023,15 @@ static void test_connect_pin(void) "%u: Media types didn't match.\n", i); ok(!memcmp(pmt->pbFormat, &expect_format, sizeof(VIDEOINFOHEADER)), "%u: Format blocks didn't match.\n", i); + if (i == 5) + { + const VIDEOINFO *format = (VIDEOINFO *)pmt->pbFormat; + + ok(pmt->cbFormat == offsetof(VIDEOINFO, dwBitMasks[3]), "Got format size %u.\n", pmt->cbFormat); + ok(format->dwBitMasks[iRED] == 0xf800, "Got red bit mask %#x.\n", format->dwBitMasks[iRED]); + ok(format->dwBitMasks[iGREEN] == 0x07e0, "Got green bit mask %#x.\n", format->dwBitMasks[iGREEN]); + ok(format->dwBitMasks[iBLUE] == 0x001f, "Got blue bit mask %#x.\n", format->dwBitMasks[iBLUE]); + }
hr = IPin_QueryAccept(source, pmt); ok(hr == (i == 8 ? S_OK : S_FALSE), "Got hr %#x.\n", hr);