From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/tests/Makefile.in | 3 +- dlls/iyuv_32/tests/i420frame.bmp | Bin 0 -> 50742 bytes dlls/iyuv_32/tests/iyuv_32.c | 131 +++++++++++++++++++++++++ dlls/iyuv_32/tests/resource.rc | 30 ++++++ dlls/iyuv_32/tests/rgb24frame_flip.bmp | Bin 0 -> 27702 bytes 5 files changed, 163 insertions(+), 1 deletion(-) create mode 100755 dlls/iyuv_32/tests/i420frame.bmp create mode 100644 dlls/iyuv_32/tests/resource.rc create mode 100644 dlls/iyuv_32/tests/rgb24frame_flip.bmp diff --git a/dlls/iyuv_32/tests/Makefile.in b/dlls/iyuv_32/tests/Makefile.in index 05779d3c2dc..7d47050a25b 100644 --- a/dlls/iyuv_32/tests/Makefile.in +++ b/dlls/iyuv_32/tests/Makefile.in @@ -2,4 +2,5 @@ TESTDLL = iyuv_32.dll IMPORTS = msvfw32 SOURCES = \ - iyuv_32.c + iyuv_32.c \ + resource.rc diff --git a/dlls/iyuv_32/tests/i420frame.bmp b/dlls/iyuv_32/tests/i420frame.bmp new file mode 100755 index 0000000000000000000000000000000000000000..acebee03e4d77aa6f5720df1c0b0bc04940c67fe GIT binary patch literal 50742 zcmZ?rHJiWy24)Nl3>pj!3<(Sj3=97M|If&v02XI}%0oC1^54II|3~p?7>uTY(KIlc z21e7sXc`zz1EXnRG!2ZVfzdQDng&MGz-Ss6O#`E8VECp1hQELRkK)lV7)=ACX<#%B zjHZFnG%%V5M$^D(8W>FjqiJ9?4UDFN(KIlc21e7s@J$2%|1<m_#iL;`ng&MGz-Ss6 zO#`E8U^ESkrh(BkFq#HN)4*sN7)=ACX<#%BjHZF%n+6#EGW;LKqhT<b21e7sXc`zz z1EXnRG!2ZVfzdQDng&MGz-Ss6O#`E8U^ESkrh(y`2L3So`#*|D!(cQGjHZFnG%%V5 zM$^D(8W>FjqiJ9?4UDFN(KIlc21e7sXc`zz1H(5BFfjc2KZ-}gU^ESkrh(BkFq#HN z)4*sN7)=ACX<#%BjHZFnG%%V5M$^D(8W>Fj!#555XJGh0ibum>G!2ZVfzdQDng&MG zz-Ss6O#`E8U^ESkrh(BkFq#HN)4*sN7)=AiHw`c_F#I3IqhT<b21e7sXc`zz1EXnR zG!2ZVfzdQDng&MGz-Ss6O#`E8U^ESkrh(y`240VX(GVC7fzc2cpb)q?3PwX<Gz3ON zV1Pnk)hHMZfzc2c4S@j)feE8vGz3ONU^D~<C<L-b!DtAKhQMeD3{VIJj)Kt;7!85Z z5E!5k&>RJ$Aut*OqaiRrAs{dcMnhmU1V%$(fI^^Q6yObk0g9F(W9_n0fHwrpMgiUs zI5`UNhCtLPz#9S|MgiUsz+1VEN{)sAfe@H93h;)&kZGt5kVBP60p1X}Hwy5E!23~v RHw5xV0p1WGP`!<KX#n}>2Mz!L literal 0 HcmV?d00001 diff --git a/dlls/iyuv_32/tests/iyuv_32.c b/dlls/iyuv_32/tests/iyuv_32.c index dc2248850e0..bfea1998deb 100644 --- a/dlls/iyuv_32/tests/iyuv_32.c +++ b/dlls/iyuv_32/tests/iyuv_32.c @@ -25,6 +25,64 @@ #define FOURCC_I420 mmioFOURCC('I', '4', '2', '0') #define FOURCC_IYUV mmioFOURCC('I', 'Y', 'U', 'V') +#pragma pack(push, 2) +struct bmp_header +{ + char magic[2]; + DWORD length; + DWORD reserved; + DWORD offset; +}; +#pragma pack(pop) + +static void write_bitmap_to_file(const BITMAPINFOHEADER *bitmap_header, const BYTE *data, HANDLE output) +{ + struct bmp_header header = + { + .magic = "BM", + .length = sizeof(header) + sizeof(*bitmap_header) + bitmap_header->biSizeImage, + .offset = sizeof(header) + sizeof(*bitmap_header), + }; + DWORD written; + BOOL ret; + + ret = WriteFile(output, &header, sizeof(header), &written, NULL); + ok(ret, "WriteFile failed, error %lu\n", GetLastError()); + ok(written == sizeof(header), "written %lu bytes\n", written); + ret = WriteFile(output, bitmap_header, sizeof(*bitmap_header), &written, NULL); + ok(ret, "WriteFile failed, error %lu\n", GetLastError()); + ok(written == sizeof(*bitmap_header), "written %lu bytes\n", written); + ret = WriteFile(output, data, bitmap_header->biSizeImage, &written, NULL); + ok(ret, "WriteFile failed, error %lu\n", GetLastError()); + ok(written == bitmap_header->biSizeImage, "written %lu bytes\n", written); +} + +static HANDLE open_temp_file(const WCHAR *output_filename) +{ + WCHAR path[MAX_PATH]; + HANDLE output; + + GetTempPathW(ARRAY_SIZE(path), path); + lstrcatW(path, output_filename); + + output = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(output != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError()); + + trace("created %s\n", debugstr_w(path)); + + return output; +} + +static void write_bitmap(const BITMAPINFOHEADER *bitmap_header, const BYTE *data, const WCHAR *output_filename) +{ + HANDLE output; + + output = open_temp_file(output_filename); + write_bitmap_to_file(bitmap_header, data, output); + + CloseHandle(output); +} + static void test_formats(DWORD handler) { BITMAPINFOHEADER in = {.biSize = sizeof(BITMAPINFOHEADER)}; @@ -152,6 +210,78 @@ static void test_formats(DWORD handler) ok(res == ICERR_OK, "Got %ld.\n", res); } +static void test_decompress(DWORD handler) +{ + static const DWORD width = 96, height = 96; + + const struct bmp_header *expect_rgb_header; + const BYTE *expect_rgb_data; + BYTE rgb_data[96 * 96 * 3]; + DWORD res, diff; + BYTE *i420_data; + HRSRC resource; + HIC hic; + + BITMAPINFOHEADER i420_info = + { + .biSize = sizeof(i420_info), + .biWidth = width, + .biHeight = height, + .biPlanes = 1, + .biBitCount = 12, + .biCompression = handler, + }; + + BITMAPINFOHEADER rgb_info = + { + .biSize = sizeof(rgb_info), + .biWidth = width, + .biHeight = height, + .biPlanes = 1, + .biBitCount = 24, + .biCompression = BI_RGB, + .biSizeImage = sizeof(rgb_data), + }; + + 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); + + hic = ICOpen(ICTYPE_VIDEO, handler, ICMODE_DECOMPRESS); + 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); + res = ICDecompressEnd(hic); + ok(res == ICERR_OK, "Got %ld.\n", res); + + write_bitmap(&rgb_info, rgb_data, L"rgb24frame_flip.bmp"); + + resource = FindResourceW(NULL, L"rgb24frame_flip.bmp", (const WCHAR *)RT_RCDATA); + expect_rgb_header = ((const struct bmp_header *)LockResource(LoadResource(GetModuleHandleW(NULL), resource))); + expect_rgb_data = (const BYTE *)((uintptr_t)expect_rgb_header + expect_rgb_header->offset); + + diff = 0; + 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); + +skip_decompression_tests: + res = ICClose(hic); + ok(res == ICERR_OK, "Got %ld.\n", res); +} + START_TEST(iyuv_32) { static const DWORD handler[] = {FOURCC_IYUV, FOURCC_I420}; @@ -178,6 +308,7 @@ START_TEST(iyuv_32) { winetest_push_context("handler %.4s", (char *)&handler[i]); test_formats(handler[i]); + test_decompress(handler[i]); winetest_pop_context(); } } diff --git a/dlls/iyuv_32/tests/resource.rc b/dlls/iyuv_32/tests/resource.rc new file mode 100644 index 00000000000..d963e812105 --- /dev/null +++ b/dlls/iyuv_32/tests/resource.rc @@ -0,0 +1,30 @@ +/* + * 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 "windef.h" + +/* Generated with: */ +/* ffmpeg -f lavfi -i pal100bars=size=96x96 \ + * -vf transpose -pix_fmt bgr24 -frames:v 1 \ + * rgb24frame_flip.bmp */ +/* @makedep: rgb24frame_flip.bmp */ +rgb24frame_flip.bmp RCDATA rgb24frame_flip.bmp + +/* Generated by running the compression test on Windows */ +/* @makedep: i420frame.bmp */ +i420frame.bmp RCDATA i420frame.bmp diff --git a/dlls/iyuv_32/tests/rgb24frame_flip.bmp b/dlls/iyuv_32/tests/rgb24frame_flip.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7795fcf3989b8bf6594935c15eedf22829f14229 GIT binary patch literal 27702 zcmZ?rHOpZD12YB&1`P%Vh6E^PWRL)hGeG4boKbQ#1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONfSw`nkAYznjfTKz2#kinXb6mkz-S1JhQMeDjE2By2#kinXb8|D1Q;0p zj-t^J7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu;sI)uPqhJT}IGz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLx2t;FuMA1Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLx4UZ@c%!<C>jlc(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc44LkKYZ{X2?ALtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1n3X~|3|@S2#kinXb6mkz-S1JhQMeDjE2By Q2#kinXb6mk09`@=09!zwZ~y=R literal 0 HcmV?d00001 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10467