From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/iyuv_32/tests/iyuv_32.c | 132 +++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/dlls/iyuv_32/tests/iyuv_32.c b/dlls/iyuv_32/tests/iyuv_32.c index ee7b9de689e..efe4158566c 100644 --- a/dlls/iyuv_32/tests/iyuv_32.c +++ b/dlls/iyuv_32/tests/iyuv_32.c @@ -24,6 +24,65 @@ #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)}; @@ -151,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 }; @@ -177,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(); } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10467