ir50_32: Implement decompression.

This commit is contained in:
Shaun Ren 2023-02-08 02:04:02 -05:00 committed by Alexandre Julliard
parent 6d7b3addc4
commit 4eac23121d

View file

@ -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 )