2 * Intel Indeo 5 Video Decoder
3 * Copyright 2023 Shaun Ren for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "ir50_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ir50_32
);
36 static HINSTANCE IR50_32_hModule
;
38 #define IV50_MAGIC mmioFOURCC('I','V','5','0')
39 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
41 DEFINE_MEDIATYPE_GUID(MFVideoFormat_IV50
, MAKEFOURCC('I','V','5','0'));
44 make_uint64( UINT32 high
, UINT32 low
)
46 return ((UINT64
)high
<< 32) | low
;
51 IV50_Open( const ICINFO
*icinfo
)
53 IMFTransform
*decoder
= NULL
;
55 TRACE("DRV_OPEN %p\n", icinfo
);
57 if ( icinfo
&& compare_fourcc( icinfo
->fccType
, ICTYPE_VIDEO
) )
60 if ( FAILED(winegstreamer_create_video_decoder( &decoder
)) )
63 return (LRESULT
)decoder
;
67 IV50_DecompressQuery( LPBITMAPINFO in
, LPBITMAPINFO out
)
69 TRACE("ICM_DECOMPRESS_QUERY %p %p\n", in
, out
);
71 TRACE("in->planes = %d\n", in
->bmiHeader
.biPlanes
);
72 TRACE("in->bpp = %d\n", in
->bmiHeader
.biBitCount
);
73 TRACE("in->height = %ld\n", in
->bmiHeader
.biHeight
);
74 TRACE("in->width = %ld\n", in
->bmiHeader
.biWidth
);
75 TRACE("in->compr = %#lx\n", in
->bmiHeader
.biCompression
);
77 if ( in
->bmiHeader
.biCompression
!= IV50_MAGIC
)
79 TRACE("can't do %#lx compression\n", in
->bmiHeader
.biCompression
);
80 return ICERR_BADFORMAT
;
83 /* output must be same dimensions as input */
86 TRACE("out->planes = %d\n", out
->bmiHeader
.biPlanes
);
87 TRACE("out->bpp = %d\n", out
->bmiHeader
.biBitCount
);
88 TRACE("out->height = %ld\n", out
->bmiHeader
.biHeight
);
89 TRACE("out->width = %ld\n", out
->bmiHeader
.biWidth
);
90 TRACE("out->compr = %#lx\n", out
->bmiHeader
.biCompression
);
92 if ( out
->bmiHeader
.biCompression
!= BI_RGB
)
94 TRACE("incompatible compression requested\n");
95 return ICERR_BADFORMAT
;
98 if ( out
->bmiHeader
.biBitCount
!= 32 && out
->bmiHeader
.biBitCount
!= 24 && out
->bmiHeader
.biBitCount
!= 16 )
100 TRACE("incompatible depth requested\n");
101 return ICERR_BADFORMAT
;
104 if ( in
->bmiHeader
.biPlanes
!= out
->bmiHeader
.biPlanes
||
105 in
->bmiHeader
.biHeight
!= abs(out
->bmiHeader
.biHeight
) ||
106 in
->bmiHeader
.biWidth
!= out
->bmiHeader
.biWidth
)
108 TRACE("incompatible output dimensions requested\n");
109 return ICERR_BADFORMAT
;
117 IV50_DecompressGetFormat( LPBITMAPINFO in
, LPBITMAPINFO out
)
121 TRACE("ICM_DECOMPRESS_GETFORMAT %p %p\n", in
, out
);
124 return ICERR_BADPARAM
;
126 if ( in
->bmiHeader
.biCompression
!= IV50_MAGIC
)
127 return ICERR_BADFORMAT
;
129 size
= in
->bmiHeader
.biSize
;
132 memcpy( out
, in
, size
);
133 out
->bmiHeader
.biHeight
= abs(in
->bmiHeader
.biHeight
);
134 out
->bmiHeader
.biCompression
= BI_RGB
;
135 out
->bmiHeader
.biBitCount
= 32;
136 out
->bmiHeader
.biSizeImage
= out
->bmiHeader
.biWidth
* out
->bmiHeader
.biHeight
* 4;
143 static LRESULT
IV50_DecompressBegin( IMFTransform
*decoder
, LPBITMAPINFO in
, LPBITMAPINFO out
)
145 IMFMediaType
*input_type
, *output_type
;
146 const GUID
*output_subtype
;
147 LRESULT r
= ICERR_INTERNAL
;
150 TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", decoder
, in
, out
);
153 return ICERR_BADPARAM
;
155 if ( out
->bmiHeader
.biBitCount
== 32 )
156 output_subtype
= &MFVideoFormat_RGB32
;
157 else if ( out
->bmiHeader
.biBitCount
== 24 )
158 output_subtype
= &MFVideoFormat_RGB24
;
159 else if ( out
->bmiHeader
.biBitCount
== 16 )
160 output_subtype
= &MFVideoFormat_RGB555
;
162 return ICERR_BADFORMAT
;
164 stride
= (out
->bmiHeader
.biWidth
+ 3) & ~3;
165 if (out
->bmiHeader
.biHeight
>= 0)
168 if ( FAILED(MFCreateMediaType( &input_type
)) )
169 return ICERR_INTERNAL
;
171 if ( FAILED(MFCreateMediaType( &output_type
)) )
173 IMFMediaType_Release( input_type
);
174 return ICERR_INTERNAL
;
177 if ( FAILED(IMFMediaType_SetGUID( input_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) ||
178 FAILED(IMFMediaType_SetGUID( input_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_IV50
)) )
180 if ( FAILED(IMFMediaType_SetUINT64(
181 input_type
, &MF_MT_FRAME_SIZE
,
182 make_uint64( in
->bmiHeader
.biWidth
, in
->bmiHeader
.biHeight
) )) )
185 if ( FAILED(IMFMediaType_SetGUID( output_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) ||
186 FAILED(IMFMediaType_SetGUID( output_type
, &MF_MT_SUBTYPE
, output_subtype
)) )
188 if ( FAILED(IMFMediaType_SetUINT64(
189 output_type
, &MF_MT_FRAME_SIZE
,
190 make_uint64( out
->bmiHeader
.biWidth
, abs(out
->bmiHeader
.biHeight
) ) )) )
192 if ( FAILED(IMFMediaType_SetUINT32( output_type
, &MF_MT_DEFAULT_STRIDE
, stride
)) )
195 if ( FAILED(IMFTransform_SetInputType( decoder
, 0, input_type
, 0 )) ||
196 FAILED(IMFTransform_SetOutputType( decoder
, 0, output_type
, 0 )) )
202 IMFMediaType_Release( input_type
);
203 IMFMediaType_Release( output_type
);
207 static LRESULT
IV50_Decompress( IMFTransform
*decoder
, ICDECOMPRESS
*icd
, DWORD size
)
209 IMFSample
*in_sample
= NULL
, *out_sample
= NULL
;
210 IMFMediaBuffer
*in_buf
= NULL
, *out_buf
= NULL
;
211 MFT_OUTPUT_DATA_BUFFER mft_buf
;
215 LRESULT r
= ICERR_INTERNAL
;
217 TRACE("ICM_DECOMPRESS %p %p %lu\n", decoder
, icd
, size
);
219 if ( FAILED(MFCreateSample( &in_sample
)) )
220 return ICERR_INTERNAL
;
222 if ( FAILED(MFCreateMemoryBuffer( icd
->lpbiInput
->biSizeImage
, &in_buf
)) )
225 if ( FAILED(IMFSample_AddBuffer( in_sample
, in_buf
)) )
228 if ( FAILED(MFCreateSample( &out_sample
)) )
231 if ( FAILED(MFCreateMemoryBuffer( icd
->lpbiOutput
->biSizeImage
, &out_buf
)) )
234 if ( FAILED(IMFSample_AddBuffer( out_sample
, out_buf
)) )
237 if ( FAILED(IMFMediaBuffer_Lock( in_buf
, &data
, NULL
, NULL
)))
240 memcpy( data
, icd
->lpInput
, icd
->lpbiInput
->biSizeImage
);
242 if ( FAILED(IMFMediaBuffer_Unlock( in_buf
)) )
245 if ( FAILED(IMFMediaBuffer_SetCurrentLength( in_buf
, icd
->lpbiInput
->biSizeImage
)) )
248 if ( FAILED(IMFTransform_ProcessInput( decoder
, 0, in_sample
, 0 )) )
251 memset( &mft_buf
, 0, sizeof(mft_buf
) );
252 mft_buf
.pSample
= out_sample
;
254 hr
= IMFTransform_ProcessOutput( decoder
, 0, 1, &mft_buf
, &mft_status
);
255 if ( SUCCEEDED(hr
) && (mft_status
& MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
) )
256 hr
= IMFTransform_ProcessOutput( decoder
, 0, 1, &mft_buf
, &mft_status
);
260 LONG width
= icd
->lpbiOutput
->biWidth
* (icd
->lpbiOutput
->biBitCount
/ 8);
261 LONG height
= abs( icd
->lpbiOutput
->biHeight
);
262 LONG stride
= (width
+ 3) & ~3;
263 BYTE
*output
= (BYTE
*)icd
->lpOutput
;
265 if ( FAILED(IMFMediaBuffer_Lock( out_buf
, &data
, NULL
, NULL
)))
268 MFCopyImage( output
, stride
, data
, stride
, width
, height
);
270 IMFMediaBuffer_Unlock( out_buf
);
273 else if ( hr
== MF_E_TRANSFORM_NEED_MORE_INPUT
)
275 TRACE("no output received.\n");
281 IMFMediaBuffer_Release( in_buf
);
283 IMFSample_Release( in_sample
);
285 IMFMediaBuffer_Release( out_buf
);
287 IMFSample_Release( out_sample
);
292 static LRESULT
IV50_GetInfo( ICINFO
*icinfo
, DWORD dwSize
)
294 TRACE("ICM_GETINFO %p %lu\n", icinfo
, dwSize
);
296 if ( !icinfo
) return sizeof(ICINFO
);
297 if ( dwSize
< sizeof(ICINFO
) ) return 0;
299 icinfo
->dwSize
= sizeof(ICINFO
);
300 icinfo
->fccType
= ICTYPE_VIDEO
;
301 icinfo
->fccHandler
= IV50_MAGIC
;
303 icinfo
->dwVersion
= ICVERSION
;
304 icinfo
->dwVersionICM
= ICVERSION
;
306 LoadStringW( IR50_32_hModule
, IDS_NAME
, icinfo
->szName
, ARRAY_SIZE(icinfo
->szName
) );
307 LoadStringW( IR50_32_hModule
, IDS_DESCRIPTION
, icinfo
->szDescription
, ARRAY_SIZE(icinfo
->szDescription
) );
308 /* msvfw32 will fill icinfo->szDriver for us */
310 return sizeof(ICINFO
);
313 /***********************************************************************
314 * DriverProc (IR50_32.@)
316 LRESULT WINAPI
IV50_DriverProc( DWORD_PTR dwDriverId
, HDRVR hdrvr
, UINT msg
,
317 LPARAM lParam1
, LPARAM lParam2
)
319 IMFTransform
*decoder
= (IMFTransform
*) dwDriverId
;
320 LRESULT r
= ICERR_UNSUPPORTED
;
322 TRACE("%Id %p %04x %08Ix %08Ix\n", dwDriverId
, hdrvr
, msg
, lParam1
, lParam2
);
332 r
= IV50_Open((ICINFO
*)lParam2
);
336 TRACE("DRV_CLOSE\n");
338 IMFTransform_Release( decoder
);
348 r
= IV50_GetInfo( (ICINFO
*) lParam1
, (DWORD
) lParam2
);
351 case ICM_DECOMPRESS_QUERY
:
352 r
= IV50_DecompressQuery( (LPBITMAPINFO
) lParam1
, (LPBITMAPINFO
) lParam2
);
355 case ICM_DECOMPRESS_GET_FORMAT
:
356 r
= IV50_DecompressGetFormat( (LPBITMAPINFO
) lParam1
, (LPBITMAPINFO
) lParam2
);
359 case ICM_DECOMPRESS_GET_PALETTE
:
360 FIXME("ICM_DECOMPRESS_GET_PALETTE\n");
364 r
= IV50_Decompress( decoder
, (ICDECOMPRESS
*) lParam1
, (DWORD
) lParam2
);
367 case ICM_DECOMPRESS_BEGIN
:
368 r
= IV50_DecompressBegin( decoder
, (LPBITMAPINFO
) lParam1
, (LPBITMAPINFO
) lParam2
);
371 case ICM_DECOMPRESS_END
:
372 r
= ICERR_UNSUPPORTED
;
375 case ICM_DECOMPRESSEX_QUERY
:
376 FIXME("ICM_DECOMPRESSEX_QUERY\n");
379 case ICM_DECOMPRESSEX
:
380 FIXME("ICM_DECOMPRESSEX\n");
383 case ICM_COMPRESS_QUERY
:
386 case ICM_COMPRESS_GET_FORMAT
:
387 case ICM_COMPRESS_END
:
389 FIXME("compression not implemented\n");
396 FIXME("Unknown message: %04x %Id %Id\n", msg
, lParam1
, lParam2
);
402 /***********************************************************************
405 BOOL WINAPI
DllMain(HINSTANCE hModule
, DWORD dwReason
, LPVOID lpReserved
)
407 TRACE("(%p,%lu,%p)\n", hModule
, dwReason
, lpReserved
);
411 case DLL_PROCESS_ATTACH
:
412 DisableThreadLibraryCalls(hModule
);
413 IR50_32_hModule
= hModule
;