Module: wine Branch: master Commit: 4eac23121d17e5b5cca61516429398aac1ed8e5a URL: https://gitlab.winehq.org/wine/wine/-/commit/4eac23121d17e5b5cca61516429398a...
Author: Shaun Ren sren@codeweavers.com Date: Wed Feb 8 02:04:02 2023 -0500
ir50_32: Implement decompression.
---
dlls/ir50_32/ir50.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 4 deletions(-)
diff --git a/dlls/ir50_32/ir50.c b/dlls/ir50_32/ir50.c index 428108f09ba..87807aba25f 100644 --- a/dlls/ir50_32/ir50.c +++ b/dlls/ir50_32/ir50.c @@ -26,6 +26,7 @@ #include "winuser.h" #include "commdlg.h" #include "vfw.h" +#include "initguid.h" #include "ir50_private.h"
#include "wine/debug.h" @@ -37,6 +38,14 @@ static HINSTANCE IR50_32_hModule; #define IV50_MAGIC mmioFOURCC('I','V','5','0') #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
+DEFINE_MEDIATYPE_GUID(MFVideoFormat_IV50, MAKEFOURCC('I','V','5','0')); + +static inline UINT64 +make_uint64( UINT32 high, UINT32 low ) +{ + return ((UINT64)high << 32) | low; +} +
static LRESULT IV50_Open( const ICINFO *icinfo ) @@ -133,14 +142,146 @@ IV50_DecompressGetFormat( LPBITMAPINFO in, LPBITMAPINFO out )
static LRESULT IV50_DecompressBegin( IMFTransform *decoder, LPBITMAPINFO in, LPBITMAPINFO out ) { - FIXME("ICM_DECOMPRESS_BEGIN %p %p %p\n", decoder, in, out); - return ICERR_UNSUPPORTED; + IMFMediaType *input_type, *output_type; + const GUID *output_subtype; + LRESULT r = ICERR_INTERNAL; + + TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", decoder, in, out); + + if ( !decoder ) + return ICERR_BADPARAM; + + if ( out->bmiHeader.biBitCount == 32 ) + output_subtype = &MFVideoFormat_RGB32; + else if ( out->bmiHeader.biBitCount == 16 ) + output_subtype = &MFVideoFormat_RGB555; + else + return ICERR_BADFORMAT; + + 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_IV50 )) ) + goto done; + if ( FAILED(IMFMediaType_SetUINT64( + input_type, &MF_MT_FRAME_SIZE, + make_uint64( in->bmiHeader.biWidth, in->bmiHeader.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->bmiHeader.biWidth, abs(out->bmiHeader.biHeight) ) )) ) + goto done; + + if ( FAILED(IMFTransform_SetInputType( decoder, 0, input_type, 0 )) || + FAILED(IMFTransform_SetOutputType( decoder, 0, output_type, 0 )) ) + goto done; + + r = ICERR_OK; + +done: + IMFMediaType_Release( input_type ); + IMFMediaType_Release( output_type ); + return r; }
static LRESULT IV50_Decompress( IMFTransform *decoder, ICDECOMPRESS *icd, DWORD size ) { - FIXME("ICM_DECOMPRESS %p %p %lu\n", decoder, icd, size); - return ICERR_UNSUPPORTED; + IMFSample *in_sample = NULL, *out_sample = NULL; + IMFMediaBuffer *in_buf = NULL, *out_buf = NULL; + MFT_OUTPUT_DATA_BUFFER mft_buf; + DWORD mft_status; + BYTE *data; + HRESULT hr; + LRESULT r = ICERR_INTERNAL; + + TRACE("ICM_DECOMPRESS %p %p %lu\n", decoder, icd, size); + + if ( FAILED(MFCreateSample( &in_sample )) ) + return ICERR_INTERNAL; + + if ( FAILED(MFCreateMemoryBuffer( icd->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( icd->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, icd->lpInput, icd->lpbiInput->biSizeImage ); + + if ( FAILED(IMFMediaBuffer_Unlock( in_buf )) ) + goto done; + + if ( FAILED(IMFMediaBuffer_SetCurrentLength( in_buf, icd->lpbiInput->biSizeImage )) ) + goto done; + + if ( FAILED(IMFTransform_ProcessInput( decoder, 0, in_sample, 0 )) ) + goto done; + + memset( &mft_buf, 0, sizeof(mft_buf) ); + mft_buf.pSample = out_sample; + + hr = IMFTransform_ProcessOutput( decoder, 0, 1, &mft_buf, &mft_status ); + if ( SUCCEEDED(hr) && (mft_status & MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE) ) + hr = IMFTransform_ProcessOutput( decoder, 0, 1, &mft_buf, &mft_status ); + + if ( SUCCEEDED(hr) ) + { + LONG width = icd->lpbiOutput->biWidth * (icd->lpbiOutput->biBitCount / 8); + LONG height = abs( icd->lpbiOutput->biHeight ); + LONG data_stride = (width + 3) & ~3; + LONG out_stride = icd->lpbiOutput->biHeight >= 0 ? -data_stride : data_stride; + BYTE *output_start = (BYTE *)icd->lpOutput; + + if (out_stride < 0) + output_start += (height - 1) * abs(out_stride); + + if ( FAILED(IMFMediaBuffer_Lock( out_buf, &data, NULL, NULL ))) + goto done; + + MFCopyImage( output_start, out_stride, data, data_stride, width, height ); + + IMFMediaBuffer_Unlock( out_buf ); + r = ICERR_OK; + } + else if ( hr == MF_E_TRANSFORM_NEED_MORE_INPUT ) + { + TRACE("no output received.\n"); + 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 IV50_GetInfo( ICINFO *icinfo, DWORD dwSize )