[PATCH v6 0/8] MR10549: iyuv_32: Implement Decompression
This MR adds I420 "decompression" functionality to the `iyuv_32.dll`. -- v6: iyuv_32: Implement IYUV_Decompress. iyuv_32: Implement IYUV_DecompressBegin. https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/tests/iyuv_32.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dlls/iyuv_32/tests/iyuv_32.c b/dlls/iyuv_32/tests/iyuv_32.c index 97572411e6e..1f4f381753f 100644 --- a/dlls/iyuv_32/tests/iyuv_32.c +++ b/dlls/iyuv_32/tests/iyuv_32.c @@ -297,6 +297,7 @@ static void test_decompress(DWORD handler) DWORD res, diff; BYTE *i420_data; HRSRC resource; + DWORD bmp_len; HIC hic; BITMAPINFOHEADER i420_info = @@ -322,8 +323,9 @@ static void test_decompress(DWORD handler) resource = FindResourceW(NULL, L"i420frame.bmp", (const WCHAR *)RT_RCDATA); i420_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); - i420_data += *(DWORD *)(i420_data + 2); - i420_info.biSizeImage = SizeofResource(GetModuleHandleW(NULL), resource); + bmp_len = *(DWORD *)(i420_data + 2); + i420_data += bmp_len; + i420_info.biSizeImage = SizeofResource(GetModuleHandleW(NULL), resource) - bmp_len; hic = ICOpen(ICTYPE_VIDEO, handler, ICMODE_DECOMPRESS); ok(!!hic, "Failed to open codec.\n"); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> This is a exported function that wraps the color_convert_create function. --- dlls/winegstreamer/color_convert.c | 16 ++++++++++++++++ dlls/winegstreamer/winegstreamer.spec | 1 + 2 files changed, 17 insertions(+) diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index 697cd6fcd4c..5d9e5f1c0a9 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -1038,3 +1038,19 @@ HRESULT color_convert_create(IUnknown *outer, IUnknown **out) TRACE("Created %p\n", *out); return S_OK; } + +HRESULT WINAPI winegstreamer_create_color_converter(IMFTransform **out) +{ + IUnknown *unknown; + HRESULT hr; + + TRACE("out %p.\n", out); + + if (!init_gstreamer()) + return E_FAIL; + + if (FAILED(hr = color_convert_create(NULL, &unknown))) + return hr; + + return IUnknown_QueryInterface(unknown, &IID_IMFTransform, (void**)out); +} diff --git a/dlls/winegstreamer/winegstreamer.spec b/dlls/winegstreamer/winegstreamer.spec index 095f75a0865..69eed004b78 100644 --- a/dlls/winegstreamer/winegstreamer.spec +++ b/dlls/winegstreamer/winegstreamer.spec @@ -4,3 +4,4 @@ @ stdcall -private DllUnregisterServer() @ stdcall winegstreamer_create_wm_sync_reader(ptr ptr) @ stdcall winegstreamer_create_video_decoder(ptr) +@ stdcall winegstreamer_create_color_converter(ptr) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/Makefile.in | 3 ++- dlls/iyuv_32/iyuv.c | 25 ++++++++++++++++++++++--- dlls/iyuv_32/iyuv_32.rc | 29 +++++++++++++++++++++++++++++ dlls/iyuv_32/iyuv_private.h | 27 +++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 dlls/iyuv_32/iyuv_32.rc create mode 100644 dlls/iyuv_32/iyuv_private.h diff --git a/dlls/iyuv_32/Makefile.in b/dlls/iyuv_32/Makefile.in index 6b9b11569b1..c386ec9b924 100644 --- a/dlls/iyuv_32/Makefile.in +++ b/dlls/iyuv_32/Makefile.in @@ -2,4 +2,5 @@ MODULE = iyuv_32.dll IMPORTS = user32 mfplat ole32 SOURCES = \ - iyuv.c + iyuv.c \ + iyuv_32.rc diff --git a/dlls/iyuv_32/iyuv.c b/dlls/iyuv_32/iyuv.c index e114fde50e0..7fa004f16f7 100644 --- a/dlls/iyuv_32/iyuv.c +++ b/dlls/iyuv_32/iyuv.c @@ -31,19 +31,22 @@ #include "vfw.h" #include "wmcodecdsp.h" +#include "iyuv_private.h" #include "wine/debug.h" #define COBJMACROS #include "mfapi.h" #include "mferror.h" -#include "mfobjects.h" #include "mfidl.h" +#include "mfobjects.h" #include "mftransform.h" WINE_DEFAULT_DEBUG_CHANNEL(iyuv_32); static HINSTANCE IYUV_32_module; +#define FOURCC_IYUV mmioFOURCC('I', 'Y', 'U', 'V') + static LRESULT IYUV_Open(const ICINFO *icinfo) { FIXME("DRV_OPEN %p\n", icinfo); @@ -81,9 +84,25 @@ static LRESULT IYUV_Decompress(IMFTransform *transform, const ICDECOMPRESS *para static LRESULT IYUV_GetInfo(ICINFO *icinfo, DWORD size) { - FIXME("ICM_GETINFO %p %lu\n", icinfo, size); + TRACE("ICM_GETINFO %p %lu\n", icinfo, size); - return ICERR_UNSUPPORTED; + if (!icinfo) + return sizeof(ICINFO); + if (size < sizeof(ICINFO)) + return 0; + + icinfo->dwSize = sizeof(ICINFO); + icinfo->fccType = ICTYPE_VIDEO; + icinfo->fccHandler = FOURCC_IYUV; + icinfo->dwFlags = 0; + icinfo->dwVersion = 0; + icinfo->dwVersionICM = ICVERSION; + + LoadStringW(IYUV_32_module, IDS_NAME, icinfo->szName, ARRAY_SIZE(icinfo->szName)); + LoadStringW(IYUV_32_module, IDS_DESCRIPTION, icinfo->szDescription, ARRAY_SIZE(icinfo->szDescription)); + /* msvfw32 will fill icinfo->szDriver for us */ + + return sizeof(ICINFO); } /*********************************************************************** diff --git a/dlls/iyuv_32/iyuv_32.rc b/dlls/iyuv_32/iyuv_32.rc new file mode 100644 index 00000000000..a9705a2bd76 --- /dev/null +++ b/dlls/iyuv_32/iyuv_32.rc @@ -0,0 +1,29 @@ +/* + * Copyright 2026 Brendan McGrath for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "iyuv_private.h" + +#pragma makedep po + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_NAME "IYUV codec" + IDS_DESCRIPTION "IYUV codec" +} diff --git a/dlls/iyuv_32/iyuv_private.h b/dlls/iyuv_32/iyuv_private.h new file mode 100644 index 00000000000..cf2d392dc44 --- /dev/null +++ b/dlls/iyuv_32/iyuv_private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2026 Brendan McGrath for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __IYUV_PRIVATE_H +#define __IYUV_PRIVATE_H + +#include "windef.h" + +#define IDS_NAME 100 +#define IDS_DESCRIPTION 101 + +#endif /* __IYUV_PRIVATE_H */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/iyuv.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/dlls/iyuv_32/iyuv.c b/dlls/iyuv_32/iyuv.c index 7fa004f16f7..06634861115 100644 --- a/dlls/iyuv_32/iyuv.c +++ b/dlls/iyuv_32/iyuv.c @@ -45,8 +45,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(iyuv_32); static HINSTANCE IYUV_32_module; +#define FOURCC_I420 mmioFOURCC('I', '4', '2', '0') #define FOURCC_IYUV mmioFOURCC('I', 'Y', 'U', 'V') +#define compare_fourcc(fcc1, fcc2) (((fcc1) ^ (fcc2)) & ~0x20202020) + static LRESULT IYUV_Open(const ICINFO *icinfo) { FIXME("DRV_OPEN %p\n", icinfo); @@ -56,9 +59,41 @@ static LRESULT IYUV_Open(const ICINFO *icinfo) static LRESULT IYUV_DecompressQuery(const BITMAPINFOHEADER *in, const BITMAPINFOHEADER *out) { - FIXME("ICM_DECOMPRESS_QUERY %p %p\n", in, out); + TRACE("in->planes = %d\n", in->biPlanes); + TRACE("in->bpp = %d\n", in->biBitCount); + TRACE("in->height = %ld\n", in->biHeight); + TRACE("in->width = %ld\n", in->biWidth); + TRACE("in->compr = %#lx\n", in->biCompression); - return ICERR_UNSUPPORTED; + if (compare_fourcc(in->biCompression, FOURCC_I420) && compare_fourcc(in->biCompression, FOURCC_IYUV)) + { + TRACE("can't do %#lx decompression\n", in->biCompression); + return ICERR_BADFORMAT; + } + + if (!in->biHeight || !in->biWidth) + return ICERR_BADFORMAT; + + /* output must be same dimensions as input */ + if (out) + { + TRACE("out->planes = %d\n", out->biPlanes); + TRACE("out->bpp = %d\n", out->biBitCount); + TRACE("out->height = %ld\n", out->biHeight); + TRACE("out->width = %ld\n", out->biWidth); + TRACE("out->compr = %#lx\n", out->biCompression); + + if (out->biCompression != BI_RGB) + return ICERR_BADFORMAT; + + if (out->biBitCount != 24 && out->biBitCount != 16 && out->biBitCount != 8) + return ICERR_BADFORMAT; + + if (in->biWidth != out->biWidth || in->biHeight != out->biHeight) + return ICERR_BADFORMAT; + } + + return ICERR_OK; } static LRESULT IYUV_DecompressGetFormat(BITMAPINFOHEADER *in, BITMAPINFOHEADER *out) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/iyuv.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/dlls/iyuv_32/iyuv.c b/dlls/iyuv_32/iyuv.c index 06634861115..e039c28c4e0 100644 --- a/dlls/iyuv_32/iyuv.c +++ b/dlls/iyuv_32/iyuv.c @@ -98,9 +98,25 @@ static LRESULT IYUV_DecompressQuery(const BITMAPINFOHEADER *in, const BITMAPINFO static LRESULT IYUV_DecompressGetFormat(BITMAPINFOHEADER *in, BITMAPINFOHEADER *out) { - FIXME("ICM_DECOMPRESS_GETFORMAT %p %p\n", in, out); + TRACE("ICM_DECOMPRESS_GETFORMAT %p %p\n", in, out); - return ICERR_UNSUPPORTED; + if (compare_fourcc(in->biCompression, FOURCC_I420) && compare_fourcc(in->biCompression, FOURCC_IYUV)) + return ICERR_BADFORMAT; + + if (out) + { + memset(out, 0, sizeof(*out)); + out->biSize = sizeof(BITMAPINFOHEADER); + out->biWidth = in->biWidth; + out->biHeight = abs(in->biHeight); + out->biCompression = BI_RGB; + out->biPlanes = 1; + out->biBitCount = 24; + out->biSizeImage = out->biWidth * out->biHeight * 3; + return ICERR_OK; + } + + return sizeof(*out); } static LRESULT IYUV_DecompressBegin(IMFTransform *transform, const BITMAPINFOHEADER *in, const BITMAPINFOHEADER *out) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/Makefile.in | 2 +- dlls/iyuv_32/iyuv.c | 17 ++++++++++------- dlls/iyuv_32/iyuv_private.h | 6 ++++++ dlls/iyuv_32/tests/iyuv_32.c | 3 --- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/dlls/iyuv_32/Makefile.in b/dlls/iyuv_32/Makefile.in index c386ec9b924..e5a261b973f 100644 --- a/dlls/iyuv_32/Makefile.in +++ b/dlls/iyuv_32/Makefile.in @@ -1,5 +1,5 @@ MODULE = iyuv_32.dll -IMPORTS = user32 mfplat ole32 +IMPORTS = user32 mfplat ole32 winegstreamer SOURCES = \ iyuv.c \ diff --git a/dlls/iyuv_32/iyuv.c b/dlls/iyuv_32/iyuv.c index e039c28c4e0..b130bb8a4c9 100644 --- a/dlls/iyuv_32/iyuv.c +++ b/dlls/iyuv_32/iyuv.c @@ -34,12 +34,7 @@ #include "iyuv_private.h" #include "wine/debug.h" -#define COBJMACROS -#include "mfapi.h" #include "mferror.h" -#include "mfidl.h" -#include "mfobjects.h" -#include "mftransform.h" WINE_DEFAULT_DEBUG_CHANNEL(iyuv_32); @@ -52,9 +47,17 @@ static HINSTANCE IYUV_32_module; static LRESULT IYUV_Open(const ICINFO *icinfo) { - FIXME("DRV_OPEN %p\n", icinfo); + IMFTransform *transform; - return 0; + TRACE("DRV_OPEN %p\n", icinfo); + + if (icinfo && compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) + return 0; + + if (FAILED(winegstreamer_create_color_converter(&transform))) + transform = NULL; + + return (LRESULT)transform; } static LRESULT IYUV_DecompressQuery(const BITMAPINFOHEADER *in, const BITMAPINFOHEADER *out) diff --git a/dlls/iyuv_32/iyuv_private.h b/dlls/iyuv_32/iyuv_private.h index cf2d392dc44..694f89799d5 100644 --- a/dlls/iyuv_32/iyuv_private.h +++ b/dlls/iyuv_32/iyuv_private.h @@ -21,6 +21,12 @@ #include "windef.h" +#define COBJMACROS +#include "mfapi.h" +#include "mftransform.h" + +HRESULT WINAPI winegstreamer_create_color_converter(IMFTransform **out); + #define IDS_NAME 100 #define IDS_DESCRIPTION 101 diff --git a/dlls/iyuv_32/tests/iyuv_32.c b/dlls/iyuv_32/tests/iyuv_32.c index 1f4f381753f..a406140b5c4 100644 --- a/dlls/iyuv_32/tests/iyuv_32.c +++ b/dlls/iyuv_32/tests/iyuv_32.c @@ -458,10 +458,7 @@ START_TEST(iyuv_32) int i; hic = ICLocate(ICTYPE_VIDEO, FOURCC_I420, &in, NULL, ICMODE_DECOMPRESS); - todo_wine ok(!!hic, "Failed to locate iyuv codec\n"); - if (!hic) - return; ICClose(hic); for (i = 0; i < ARRAY_SIZE(handler); i++) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/iyuv.c | 67 ++++++++++++++++++++++++++++++++++-- dlls/iyuv_32/tests/iyuv_32.c | 6 ---- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/dlls/iyuv_32/iyuv.c b/dlls/iyuv_32/iyuv.c index b130bb8a4c9..7ba85a95a30 100644 --- a/dlls/iyuv_32/iyuv.c +++ b/dlls/iyuv_32/iyuv.c @@ -45,6 +45,11 @@ static HINSTANCE IYUV_32_module; #define compare_fourcc(fcc1, fcc2) (((fcc1) ^ (fcc2)) & ~0x20202020) +static inline UINT64 make_uint64(UINT32 high, UINT32 low) +{ + return ((UINT64)high << 32) | low; +} + static LRESULT IYUV_Open(const ICINFO *icinfo) { IMFTransform *transform; @@ -124,9 +129,67 @@ static LRESULT IYUV_DecompressGetFormat(BITMAPINFOHEADER *in, BITMAPINFOHEADER * static LRESULT IYUV_DecompressBegin(IMFTransform *transform, const BITMAPINFOHEADER *in, const BITMAPINFOHEADER *out) { - FIXME("ICM_DECOMPRESS_BEGIN %p %p %p\n", transform, in, out); + IMFMediaType *input_type, *output_type; + LRESULT r = ICERR_INTERNAL; + const GUID *output_subtype; + LONG stride, depth; - return ICERR_UNSUPPORTED; + TRACE("transform %p, in %p, out %p.\n", transform, in, out); + + if (!transform) + return ICERR_BADPARAM; + + if (out->biCompression != BI_RGB) + return ICERR_BADFORMAT; + + if (out->biBitCount == 24) + output_subtype = &MFVideoFormat_RGB24; + else if (out->biBitCount == 16) + output_subtype = &MFVideoFormat_RGB555; + else if (out->biBitCount == 8) + output_subtype = &MFVideoFormat_RGB8; + else + return ICERR_BADFORMAT; + + if (in->biWidth != out->biWidth || in->biHeight != out->biHeight) + return ICERR_BADFORMAT; + + depth = out->biBitCount / 8; + stride = -((out->biWidth * depth + 3) & ~3); + + if (FAILED(MFCreateMediaType(&input_type))) + return ICERR_INTERNAL; + + if (FAILED(MFCreateMediaType(&output_type))) + { + IMFMediaType_Release(input_type); + return ICERR_INTERNAL; + } + + if (FAILED(IMFMediaType_SetGUID(input_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)) || + FAILED(IMFMediaType_SetGUID(input_type, &MF_MT_SUBTYPE, &MFVideoFormat_I420))) + goto done; + if (FAILED(IMFMediaType_SetUINT64(input_type, &MF_MT_FRAME_SIZE, make_uint64(in->biWidth, in->biHeight)))) + goto done; + + if (FAILED(IMFMediaType_SetGUID(output_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)) || + FAILED(IMFMediaType_SetGUID(output_type, &MF_MT_SUBTYPE, output_subtype))) + goto done; + if (FAILED(IMFMediaType_SetUINT64(output_type, &MF_MT_FRAME_SIZE, make_uint64(out->biWidth, out->biHeight)))) + goto done; + if (FAILED(IMFMediaType_SetUINT32(output_type, &MF_MT_DEFAULT_STRIDE, stride))) + goto done; + + if (FAILED(IMFTransform_SetInputType(transform, 0, input_type, 0)) || + FAILED(IMFTransform_SetOutputType(transform, 0, output_type, 0))) + goto done; + + r = ICERR_OK; + +done: + IMFMediaType_Release(input_type); + IMFMediaType_Release(output_type); + return r; } static LRESULT IYUV_Decompress(IMFTransform *transform, const ICDECOMPRESS *params) diff --git a/dlls/iyuv_32/tests/iyuv_32.c b/dlls/iyuv_32/tests/iyuv_32.c index a406140b5c4..6feb81bdcd8 100644 --- a/dlls/iyuv_32/tests/iyuv_32.c +++ b/dlls/iyuv_32/tests/iyuv_32.c @@ -269,7 +269,6 @@ static void test_formats(DWORD handler) out.biCompression = BI_RGB; out.biBitCount = 24; res = ICDecompressBegin(hic, &in, &out); - todo_wine ok(res == ICERR_OK, "Got %ld.\n", res); res = ICDecompressEnd(hic); @@ -331,12 +330,8 @@ static void test_decompress(DWORD handler) ok(!!hic, "Failed to open codec.\n"); res = ICDecompressBegin(hic, &i420_info, &rgb_info); - todo_wine ok(res == ICERR_OK, "Got %ld.\n", res); - if (res != ICERR_OK) - goto skip_decompression_tests; - res = ICDecompress(hic, 0, &i420_info, i420_data, &rgb_info, rgb_data); todo_wine ok(res == ICERR_OK, "Got %ld.\n", res); @@ -356,7 +351,6 @@ static void test_decompress(DWORD handler) todo_wine ok(diff == 0, "Got %lu%% difference.\n", diff); -skip_decompression_tests: res = ICClose(hic); ok(res == ICERR_OK, "Got %ld.\n", res); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/iyuv.c | 71 +++++++++++++++++++++++++++++++++++- dlls/iyuv_32/tests/iyuv_32.c | 2 - 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/dlls/iyuv_32/iyuv.c b/dlls/iyuv_32/iyuv.c index 7ba85a95a30..f990a5bd6a1 100644 --- a/dlls/iyuv_32/iyuv.c +++ b/dlls/iyuv_32/iyuv.c @@ -194,9 +194,76 @@ done: static LRESULT IYUV_Decompress(IMFTransform *transform, const ICDECOMPRESS *params) { - FIXME("ICM_DECOMPRESS %p %p\n", transform, params); + IMFSample *in_sample = NULL, *out_sample = NULL; + IMFMediaBuffer *in_buf = NULL, *out_buf = NULL; + MFT_OUTPUT_DATA_BUFFER mft_buf; + LRESULT r = ICERR_INTERNAL; + DWORD mft_status; + BYTE *data; + + TRACE("transform %p, params %p.\n", transform, params); + + if (FAILED(MFCreateSample(&in_sample))) + return ICERR_INTERNAL; + + if (FAILED(MFCreateMemoryBuffer(params->lpbiInput->biSizeImage, &in_buf))) + goto done; + + if (FAILED(IMFSample_AddBuffer(in_sample, in_buf))) + goto done; + + if (FAILED(MFCreateSample(&out_sample))) + goto done; + + if (FAILED(MFCreateMemoryBuffer(params->lpbiOutput->biSizeImage, &out_buf))) + goto done; + + if (FAILED(IMFSample_AddBuffer(out_sample, out_buf))) + goto done; + + if (FAILED(IMFMediaBuffer_Lock(in_buf, &data, NULL, NULL))) + goto done; + + memcpy(data, params->lpInput, params->lpbiInput->biSizeImage); - return ICERR_UNSUPPORTED; + if (FAILED(IMFMediaBuffer_Unlock(in_buf))) + goto done; + + if (FAILED(IMFMediaBuffer_SetCurrentLength(in_buf, params->lpbiInput->biSizeImage))) + goto done; + + if (FAILED(IMFTransform_ProcessInput(transform, 0, in_sample, 0))) + goto done; + + memset(&mft_buf, 0, sizeof(mft_buf)); + mft_buf.pSample = out_sample; + + if (SUCCEEDED(IMFTransform_ProcessOutput(transform, 0, 1, &mft_buf, &mft_status))) + { + LONG depth = params->lpbiOutput->biBitCount / 8; + LONG width = params->lpbiOutput->biWidth * depth; + LONG stride = (width + 3) & ~3; + + if (FAILED(IMFMediaBuffer_Lock(out_buf, &data, NULL, NULL))) + goto done; + + MFCopyImage(params->lpOutput, stride, data, stride, width, params->lpbiOutput->biHeight); + + IMFMediaBuffer_Unlock(out_buf); + r = ICERR_OK; + } + +done: + if (in_buf) + IMFMediaBuffer_Release(in_buf); + if (in_sample) + IMFSample_Release(in_sample); + if (out_buf) + IMFMediaBuffer_Release(out_buf); + if (out_sample) + IMFSample_Release(out_sample); + + return r; } static LRESULT IYUV_GetInfo(ICINFO *icinfo, DWORD size) diff --git a/dlls/iyuv_32/tests/iyuv_32.c b/dlls/iyuv_32/tests/iyuv_32.c index 6feb81bdcd8..2f1c0aae31c 100644 --- a/dlls/iyuv_32/tests/iyuv_32.c +++ b/dlls/iyuv_32/tests/iyuv_32.c @@ -333,7 +333,6 @@ static void test_decompress(DWORD handler) ok(res == ICERR_OK, "Got %ld.\n", res); res = ICDecompress(hic, 0, &i420_info, i420_data, &rgb_info, rgb_data); - todo_wine ok(res == ICERR_OK, "Got %ld.\n", res); res = ICDecompressEnd(hic); ok(res == ICERR_OK, "Got %ld.\n", res); @@ -348,7 +347,6 @@ static void test_decompress(DWORD handler) for (unsigned int i = 0; i < rgb_info.biSizeImage; ++i) diff += abs((int)rgb_data[i] - (int)expect_rgb_data[i]); diff = diff * 100 / 256 / rgb_info.biSizeImage; - todo_wine ok(diff == 0, "Got %lu%% difference.\n", diff); res = ICClose(hic); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
On Mon Apr 6 20:09:26 2026 +0000, Elizabeth Figura wrote:
7/8: That should depend on the sign of the height.
YUV is always top-down and Windows actually rejects a negative sign for the output (see the test [here](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/iyuv_32/tests/iyuv_32...)). So the output stride is always negative (as it's always a bottom-up RGB image). I think you need to do the same checks in DecompressBegin() as you do in DecompressQuery(). Maybe I'm wrong about that, though. I don't see any harm in adding those checks, so I have done so.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10549#note_135255
v6: - check values of compression, width and height in `IYUV_DecompressBegin` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10549#note_135256
On Sun Apr 5 23:17:56 2026 +0000, Brendan McGrath wrote:
I think there is enough differences between `IYUV` and `IR50` that we're going to need separate code paths somewhere. So I think putting that in their own DLLs makes sense. And eventually, something as simple as I420 decompression could end up having a lighter implementation outside of `winegstreamer`. Fwiw I do not think that putting more code in winegstreamer is a good idea. I'd like to continue evolving winedmo at some point and eventually offer an option to not use GStreamer at all. Also, we could even consider importing the uncontroversial parts of FFmpeg as a PE external lib, and use it to implement things on the PE side only. This would be especially the case for this, or for audio resampling for instance, the libswresample / libswscale are completely fine to embed and probably going to perform much better than anything we could write ourselves.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10549#note_135265
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
This merge request was approved by Elizabeth Figura. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10549
participants (4)
-
Brendan McGrath -
Brendan McGrath (@redmcg) -
Elizabeth Figura (@zfigura) -
Rémi Bernon (@rbernon)