Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 7 +- dlls/windowscodecs/tests/wmpformat.c | 4 +- dlls/wmphoto/unix_lib.c | 380 ++++++++++++++++++++++++++- 3 files changed, 381 insertions(+), 10 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index c8a1f9d7f71..b0800d26407 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1531,8 +1531,7 @@ static void test_get_image_info(void) for (i = 0; i < ARRAY_SIZE(test_image); ++i) { hr = D3DX10GetImageInfoFromMemory(test_image[i].data, test_image[i].size, NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) - ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); + ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr != S_OK) continue; check_image_info(&image_info, i, __LINE__); @@ -1552,13 +1551,11 @@ static void test_get_image_info(void) create_file(test_filename, test_image[i].data, test_image[i].size, path);
hr = D3DX10GetImageInfoFromFileW(path, NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__);
hr = D3DX10GetImageInfoFromFileA(get_str_a(path), NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__); @@ -1583,13 +1580,11 @@ static void test_get_image_info(void) resource_module = create_resource_module(test_resource_name, test_image[i].data, test_image[i].size);
hr = D3DX10GetImageInfoFromResourceW(resource_module, test_resource_name, NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__);
hr = D3DX10GetImageInfoFromResourceA(resource_module, get_str_a(test_resource_name), NULL, &image_info, NULL); - todo_wine_if(test_image[i].expected.ImageFileFormat == D3DX10_IFF_WMP) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (hr == S_OK) check_image_info(&image_info, i, __LINE__); diff --git a/dlls/windowscodecs/tests/wmpformat.c b/dlls/windowscodecs/tests/wmpformat.c index 2e2809701f6..c4f947d8acf 100644 --- a/dlls/windowscodecs/tests/wmpformat.c +++ b/dlls/windowscodecs/tests/wmpformat.c @@ -89,7 +89,7 @@ static void test_decode(void) &IID_IWICBitmapDecoder, (void **)&decoder); if (FAILED(hr)) { - todo_wine win_skip("WmpDecoder isn't available, skipping test\n"); + win_skip("WmpDecoder isn't available, skipping test\n"); return; }
@@ -123,7 +123,7 @@ static void test_decode(void) ok(count == 1, "unexpected count %u\n", count);
hr = IWICBitmapDecoder_GetFrame(decoder, 0, NULL); - ok(hr == E_INVALIDARG, "GetFrame(NULL) returned hr=%x\n", hr); + todo_wine ok(hr == E_INVALIDARG, "GetFrame(NULL) returned hr=%x\n", hr);
for (j = 2; j > 0; --j) { diff --git a/dlls/wmphoto/unix_lib.c b/dlls/wmphoto/unix_lib.c index 198c93969f8..235828941f7 100644 --- a/dlls/wmphoto/unix_lib.c +++ b/dlls/wmphoto/unix_lib.c @@ -37,14 +37,371 @@ #include "objbase.h"
#include "initguid.h" -#include "wincodecs_private.h" +#ifdef SONAME_LIBJXRGLUE +#define ERR JXR_ERR +#include <JXRGlue.h> +#undef ERR +#endif
+#include "wincodecs_private.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
#include "wincodecs_common.h"
+#ifdef SONAME_LIBJXRGLUE +static void *libjxrglue; +static typeof(PKImageDecode_Create_WMP) *pPKImageDecode_Create_WMP; + +static const struct +{ + const WICPixelFormatGUID *format; + UINT bpp; +} pixel_format_bpp[] = +{ + {&GUID_PKPixelFormat128bppRGBAFixedPoint, 128}, + {&GUID_PKPixelFormat128bppRGBAFloat, 128}, + {&GUID_PKPixelFormat128bppRGBFloat, 128}, + {&GUID_PKPixelFormat16bppRGB555, 16}, + {&GUID_PKPixelFormat16bppRGB565, 16}, + {&GUID_PKPixelFormat16bppGray, 16}, + {&GUID_PKPixelFormat16bppGrayFixedPoint, 16}, + {&GUID_PKPixelFormat16bppGrayHalf, 16}, + {&GUID_PKPixelFormat24bppBGR, 24}, + {&GUID_PKPixelFormat24bppRGB, 24}, + {&GUID_PKPixelFormat32bppBGR, 32}, + {&GUID_PKPixelFormat32bppRGB101010, 32}, + {&GUID_PKPixelFormat32bppBGRA, 32}, + {&GUID_PKPixelFormat32bppCMYK, 32}, + {&GUID_PKPixelFormat32bppGrayFixedPoint, 32}, + {&GUID_PKPixelFormat32bppGrayFloat, 32}, + {&GUID_PKPixelFormat32bppRGBE, 32}, + {&GUID_PKPixelFormat40bppCMYKAlpha, 40}, + {&GUID_PKPixelFormat48bppRGB, 48}, + {&GUID_PKPixelFormat48bppRGBFixedPoint, 48}, + {&GUID_PKPixelFormat48bppRGBHalf, 48}, + {&GUID_PKPixelFormat64bppCMYK, 64}, + {&GUID_PKPixelFormat64bppRGBA, 64}, + {&GUID_PKPixelFormat64bppRGBAFixedPoint, 64}, + {&GUID_PKPixelFormat64bppRGBAHalf, 64}, + {&GUID_PKPixelFormat80bppCMYKAlpha, 80}, + {&GUID_PKPixelFormat8bppGray, 8}, + {&GUID_PKPixelFormat96bppRGBFixedPoint, 96}, + {&GUID_PKPixelFormatBlackWhite, 1}, +}; + +static inline UINT pixel_format_get_bpp(const WICPixelFormatGUID *format) +{ + int i; + for (i = 0; i < ARRAY_SIZE(pixel_format_bpp); ++i) + if (IsEqualGUID(format, pixel_format_bpp[i].format)) return pixel_format_bpp[i].bpp; + return 0; +} + +struct wmp_decoder +{ + struct decoder decoder_iface; + struct WMPStream WMPStream_iface; + PKImageDecode *decoder; + IStream *stream; + struct decoder_frame frame; + UINT frame_stride; + BYTE *frame_data; +}; + +static inline struct wmp_decoder *impl_from_decoder(struct decoder *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, decoder_iface); +} + +static inline struct wmp_decoder *impl_from_WMPStream(struct WMPStream *iface) +{ + return CONTAINING_RECORD(iface, struct wmp_decoder, WMPStream_iface); +} + +static JXR_ERR wmp_stream_Close(struct WMPStream **piface) +{ + TRACE("iface %p\n", piface); + return WMP_errSuccess; +} + +static Bool wmp_stream_EOS(struct WMPStream *iface) +{ + FIXME("iface %p, stub!\n", iface); + return FALSE; +} + +static JXR_ERR wmp_stream_Read(struct WMPStream *iface, void *buf, size_t len) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + ULONG count; + if (FAILED(stream_read(This->stream, buf, len, &count)) || count != len) + { + WARN("Failed to read data!\n"); + return WMP_errFileIO; + } + return WMP_errSuccess; +} + +static JXR_ERR wmp_stream_Write(struct WMPStream *iface, const void *buf, size_t len) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + ULONG count; + if (FAILED(stream_write(This->stream, buf, len, &count)) || count != len) + { + WARN("Failed to write data!\n"); + return WMP_errFileIO; + } + return WMP_errSuccess; +} + +static JXR_ERR wmp_stream_SetPos(struct WMPStream *iface, size_t pos) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + if (FAILED(stream_seek(This->stream, pos, STREAM_SEEK_SET, NULL))) + { + WARN("Failed to set stream pos!\n"); + return WMP_errFileIO; + } + return WMP_errSuccess; +} + +static JXR_ERR wmp_stream_GetPos(struct WMPStream *iface, size_t *pos) +{ + struct wmp_decoder *This = impl_from_WMPStream(iface); + ULONGLONG ofs; + if (FAILED(stream_seek(This->stream, 0, STREAM_SEEK_CUR, &ofs))) + { + WARN("Failed to get stream pos!\n"); + return WMP_errFileIO; + } + *pos = ofs; + return WMP_errSuccess; +} + +HRESULT CDECL wmp_decoder_initialize(struct decoder *iface, IStream *stream, struct decoder_stat *st) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + HRESULT hr; + Float dpix, dpiy; + I32 width, height; + U32 count; + + TRACE("iface %p, stream %p, st %p\n", iface, stream, st); + + if (This->stream) + return WINCODEC_ERR_WRONGSTATE; + + This->stream = stream; + if (FAILED(hr = stream_seek(This->stream, 0, STREAM_SEEK_SET, NULL))) + return hr; + if (This->decoder->Initialize(This->decoder, &This->WMPStream_iface)) + { + ERR("Failed to initialize jxrlib decoder!\n"); + return E_FAIL; + } + + if (This->decoder->GetFrameCount(This->decoder, &st->frame_count)) + { + ERR("Failed to get frame count!\n"); + return E_FAIL; + } + + if (st->frame_count > 1) FIXME("multi frame JPEG-XR not implemented\n"); + st->frame_count = 1; + st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages | + WICBitmapDecoderCapabilityCanDecodeSomeImages | + WICBitmapDecoderCapabilityCanEnumerateMetadata; + + if (This->decoder->SelectFrame(This->decoder, 0)) + { + ERR("Failed to select frame 0!\n"); + return E_FAIL; + } + if (This->decoder->GetPixelFormat(This->decoder, &This->frame.pixel_format)) + { + ERR("Failed to get frame pixel format!\n"); + return E_FAIL; + } + if (This->decoder->GetSize(This->decoder, &width, &height)) + { + ERR("Failed to get frame size!\n"); + return E_FAIL; + } + if (This->decoder->GetResolution(This->decoder, &dpix, &dpiy)) + { + ERR("Failed to get frame resolution!\n"); + return E_FAIL; + } + if (This->decoder->GetColorContext(This->decoder, NULL, &count)) + { + ERR("Failed to get frame color context size!\n"); + return E_FAIL; + } + + if (!(This->frame.bpp = pixel_format_get_bpp(&This->frame.pixel_format))) return E_FAIL; + This->frame.width = width; + This->frame.height = height; + This->frame.dpix = dpix; + This->frame.dpiy = dpiy; + This->frame.num_colors = 0; + if (count) This->frame.num_color_contexts = 1; + else This->frame.num_color_contexts = 0; + + return S_OK; +} + +HRESULT CDECL wmp_decoder_get_frame_info(struct decoder *iface, UINT frame, struct decoder_frame *info) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + + TRACE("iface %p, frame %d, info %p\n", iface, frame, info); + + if (frame > 0) + { + FIXME("multi frame JPEG-XR not implemented\n"); + return E_NOTIMPL; + } + + *info = This->frame; + return S_OK; +} + +HRESULT CDECL wmp_decoder_copy_pixels(struct decoder *iface, UINT frame, const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + PKRect pkrect; + U8 *frame_data; + + TRACE("iface %p, frame %d, rect %p, stride %d, buffersize %d, buffer %p\n", iface, frame, prc, stride, buffersize, buffer); + + if (frame > 0) + { + FIXME("multi frame JPEG-XR not implemented\n"); + return E_NOTIMPL; + } + + if (!This->frame_data) + { + pkrect.X = 0; + pkrect.Y = 0; + pkrect.Width = This->frame.width; + pkrect.Height = This->frame.height; + This->frame_stride = (This->frame.width * This->frame.bpp + 7) / 8; + if (!(frame_data = RtlAllocateHeap(GetProcessHeap(), 0, This->frame.height * This->frame_stride))) + return E_FAIL; + if (This->decoder->Copy(This->decoder, &pkrect, frame_data, stride)) + { + ERR("Failed to copy frame data!\n"); + RtlFreeHeap(GetProcessHeap(), 0, frame_data); + return E_FAIL; + } + + This->frame_data = frame_data; + } + + return copy_pixels(This->frame.bpp, This->frame_data, + This->frame.width, This->frame.height, This->frame_stride, + prc, stride, buffersize, buffer); +} + +HRESULT CDECL wmp_decoder_get_metadata_blocks(struct decoder* iface, UINT frame, UINT *count, struct decoder_block **blocks) +{ + TRACE("iface %p, frame %d, count %p, blocks %p\n", iface, frame, count, blocks); + + *count = 0; + *blocks = NULL; + return S_OK; +} + +HRESULT CDECL wmp_decoder_get_color_context(struct decoder* iface, UINT frame, UINT num, BYTE **data, DWORD *datasize) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + U32 count; + U8 *bytes; + + TRACE("iface %p, frame %d, num %u, data %p, datasize %p\n", iface, frame, num, data, datasize); + + *datasize = 0; + *data = NULL; + + if (This->decoder->GetColorContext(This->decoder, NULL, &count)) + { + ERR("Failed to get frame color context size!\n"); + return E_FAIL; + } + *datasize = count; + + bytes = RtlAllocateHeap(GetProcessHeap(), 0, count); + if (!bytes) + return E_OUTOFMEMORY; + + if (This->decoder->GetColorContext(This->decoder, bytes, &count)) + { + ERR("Failed to get frame color context!\n"); + RtlFreeHeap(GetProcessHeap(), 0, bytes); + return E_FAIL; + } + + *data = bytes; + return S_OK; +} + +void CDECL wmp_decoder_destroy(struct decoder* iface) +{ + struct wmp_decoder *This = impl_from_decoder(iface); + + TRACE("iface %p\n", iface); + + This->decoder->Release(&This->decoder); + RtlFreeHeap(GetProcessHeap(), 0, This->frame_data); + RtlFreeHeap(GetProcessHeap(), 0, This); +} + +static const struct decoder_funcs wmp_decoder_vtable = { + wmp_decoder_initialize, + wmp_decoder_get_frame_info, + wmp_decoder_copy_pixels, + wmp_decoder_get_metadata_blocks, + wmp_decoder_get_color_context, + wmp_decoder_destroy +}; + +HRESULT CDECL wmp_decoder_create(struct decoder_info *info, struct decoder **result) +{ + struct wmp_decoder *This; + PKImageDecode *decoder; + + if (!pPKImageDecode_Create_WMP || pPKImageDecode_Create_WMP(&decoder)) return E_FAIL; + This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->decoder_iface.vtable = &wmp_decoder_vtable; + This->WMPStream_iface.Close = &wmp_stream_Close; + This->WMPStream_iface.EOS = &wmp_stream_EOS; + This->WMPStream_iface.Read = &wmp_stream_Read; + This->WMPStream_iface.Write = &wmp_stream_Write; + This->WMPStream_iface.SetPos = &wmp_stream_SetPos; + This->WMPStream_iface.GetPos = &wmp_stream_GetPos; + + This->decoder = decoder; + This->stream = NULL; + memset(&This->frame, 0, sizeof(This->frame)); + This->frame_stride = 0; + This->frame_data = NULL; + + *result = &This->decoder_iface; + + info->container_format = GUID_ContainerFormatWmp; + info->block_format = GUID_ContainerFormatWmp; + info->clsid = CLSID_WICWmpDecoder; + + return S_OK; +} +#endif + static const struct win32_funcs *win32_funcs;
HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size) @@ -69,7 +426,17 @@ HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULO
HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result) { - FIXME("decoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result); + if (IsEqualGUID(decoder_clsid, &CLSID_WICWmpDecoder)) +#ifdef SONAME_LIBJXRGLUE + return wmp_decoder_create(info, result); +#else + { + WARN("jxrlib support not compiled in, returning E_NOINTERFACE.\n"); + return E_NOINTERFACE; + } +#endif + + FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result); return E_NOTIMPL; }
@@ -103,6 +470,15 @@ NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *p
win32_funcs = ptr_in;
+#ifdef SONAME_LIBJXRGLUE + if (!(libjxrglue = dlopen(SONAME_LIBJXRGLUE, RTLD_NOW))) + ERR("failed to load %s\n", SONAME_LIBJXRGLUE); + else if (!(pPKImageDecode_Create_WMP = dlsym(libjxrglue, "PKImageDecode_Create_WMP"))) + ERR("unable to find PKImageDecode_Create_WMP in %s!\n", SONAME_LIBJXRGLUE); +#else + ERR("jxrlib support not compiled in!\n"); +#endif + *(const struct unix_funcs **)ptr_out = &unix_funcs; return STATUS_SUCCESS; }