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
;
149 TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", decoder
, in
, out
);
152 return ICERR_BADPARAM
;
154 if ( out
->bmiHeader
.biBitCount
== 32 )
155 output_subtype
= &MFVideoFormat_RGB32
;
156 else if ( out
->bmiHeader
.biBitCount
== 24 )
157 output_subtype
= &MFVideoFormat_RGB24
;
158 else if ( out
->bmiHeader
.biBitCount
== 16 )
159 output_subtype
= &MFVideoFormat_RGB555
;
161 return ICERR_BADFORMAT
;
163 if ( FAILED(MFCreateMediaType( &input_type
)) )
164 return ICERR_INTERNAL
;
166 if ( FAILED(MFCreateMediaType( &output_type
)) )
168 IMFMediaType_Release( input_type
);
169 return ICERR_INTERNAL
;
172 if ( FAILED(IMFMediaType_SetGUID( input_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) ||
173 FAILED(IMFMediaType_SetGUID( input_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_IV50
)) )
175 if ( FAILED(IMFMediaType_SetUINT64(
176 input_type
, &MF_MT_FRAME_SIZE
,
177 make_uint64( in
->bmiHeader
.biWidth
, in
->bmiHeader
.biHeight
) )) )
180 if ( FAILED(IMFMediaType_SetGUID( output_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) ||
181 FAILED(IMFMediaType_SetGUID( output_type
, &MF_MT_SUBTYPE
, output_subtype
)) )
183 if ( FAILED(IMFMediaType_SetUINT64(
184 output_type
, &MF_MT_FRAME_SIZE
,
185 make_uint64( out
->bmiHeader
.biWidth
, abs(out
->bmiHeader
.biHeight
) ) )) )
188 if ( FAILED(IMFTransform_SetInputType( decoder
, 0, input_type
, 0 )) ||
189 FAILED(IMFTransform_SetOutputType( decoder
, 0, output_type
, 0 )) )
195 IMFMediaType_Release( input_type
);
196 IMFMediaType_Release( output_type
);
200 static LRESULT
IV50_Decompress( IMFTransform
*decoder
, ICDECOMPRESS
*icd
, DWORD size
)
202 IMFSample
*in_sample
= NULL
, *out_sample
= NULL
;
203 IMFMediaBuffer
*in_buf
= NULL
, *out_buf
= NULL
;
204 MFT_OUTPUT_DATA_BUFFER mft_buf
;
208 LRESULT r
= ICERR_INTERNAL
;
210 TRACE("ICM_DECOMPRESS %p %p %lu\n", decoder
, icd
, size
);
212 if ( FAILED(MFCreateSample( &in_sample
)) )
213 return ICERR_INTERNAL
;
215 if ( FAILED(MFCreateMemoryBuffer( icd
->lpbiInput
->biSizeImage
, &in_buf
)) )
218 if ( FAILED(IMFSample_AddBuffer( in_sample
, in_buf
)) )
221 if ( FAILED(MFCreateSample( &out_sample
)) )
224 if ( FAILED(MFCreateMemoryBuffer( icd
->lpbiOutput
->biSizeImage
, &out_buf
)) )
227 if ( FAILED(IMFSample_AddBuffer( out_sample
, out_buf
)) )
230 if ( FAILED(IMFMediaBuffer_Lock( in_buf
, &data
, NULL
, NULL
)))
233 memcpy( data
, icd
->lpInput
, icd
->lpbiInput
->biSizeImage
);
235 if ( FAILED(IMFMediaBuffer_Unlock( in_buf
)) )
238 if ( FAILED(IMFMediaBuffer_SetCurrentLength( in_buf
, icd
->lpbiInput
->biSizeImage
)) )
241 if ( FAILED(IMFTransform_ProcessInput( decoder
, 0, in_sample
, 0 )) )
244 memset( &mft_buf
, 0, sizeof(mft_buf
) );
245 mft_buf
.pSample
= out_sample
;
247 hr
= IMFTransform_ProcessOutput( decoder
, 0, 1, &mft_buf
, &mft_status
);
248 if ( SUCCEEDED(hr
) && (mft_status
& MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
) )
249 hr
= IMFTransform_ProcessOutput( decoder
, 0, 1, &mft_buf
, &mft_status
);
253 LONG width
= icd
->lpbiOutput
->biWidth
* (icd
->lpbiOutput
->biBitCount
/ 8);
254 LONG height
= abs( icd
->lpbiOutput
->biHeight
);
255 LONG data_stride
= (width
+ 3) & ~3;
256 LONG out_stride
= icd
->lpbiOutput
->biHeight
>= 0 ? -data_stride
: data_stride
;
257 BYTE
*output_start
= (BYTE
*)icd
->lpOutput
;
260 output_start
+= (height
- 1) * abs(out_stride
);
262 if ( FAILED(IMFMediaBuffer_Lock( out_buf
, &data
, NULL
, NULL
)))
265 MFCopyImage( output_start
, out_stride
, data
, data_stride
, width
, height
);
267 IMFMediaBuffer_Unlock( out_buf
);
270 else if ( hr
== MF_E_TRANSFORM_NEED_MORE_INPUT
)
272 TRACE("no output received.\n");
278 IMFMediaBuffer_Release( in_buf
);
280 IMFSample_Release( in_sample
);
282 IMFMediaBuffer_Release( out_buf
);
284 IMFSample_Release( out_sample
);
289 static LRESULT
IV50_GetInfo( ICINFO
*icinfo
, DWORD dwSize
)
291 TRACE("ICM_GETINFO %p %lu\n", icinfo
, dwSize
);
293 if ( !icinfo
) return sizeof(ICINFO
);
294 if ( dwSize
< sizeof(ICINFO
) ) return 0;
296 icinfo
->dwSize
= sizeof(ICINFO
);
297 icinfo
->fccType
= ICTYPE_VIDEO
;
298 icinfo
->fccHandler
= IV50_MAGIC
;
300 icinfo
->dwVersion
= ICVERSION
;
301 icinfo
->dwVersionICM
= ICVERSION
;
303 LoadStringW( IR50_32_hModule
, IDS_NAME
, icinfo
->szName
, ARRAY_SIZE(icinfo
->szName
) );
304 LoadStringW( IR50_32_hModule
, IDS_DESCRIPTION
, icinfo
->szDescription
, ARRAY_SIZE(icinfo
->szDescription
) );
305 /* msvfw32 will fill icinfo->szDriver for us */
307 return sizeof(ICINFO
);
310 /***********************************************************************
311 * DriverProc (IR50_32.@)
313 LRESULT WINAPI
IV50_DriverProc( DWORD_PTR dwDriverId
, HDRVR hdrvr
, UINT msg
,
314 LPARAM lParam1
, LPARAM lParam2
)
316 IMFTransform
*decoder
= (IMFTransform
*) dwDriverId
;
317 LRESULT r
= ICERR_UNSUPPORTED
;
319 TRACE("%Id %p %04x %08Ix %08Ix\n", dwDriverId
, hdrvr
, msg
, lParam1
, lParam2
);
329 r
= IV50_Open((ICINFO
*)lParam2
);
333 TRACE("DRV_CLOSE\n");
335 IMFTransform_Release( decoder
);
345 r
= IV50_GetInfo( (ICINFO
*) lParam1
, (DWORD
) lParam2
);
348 case ICM_DECOMPRESS_QUERY
:
349 r
= IV50_DecompressQuery( (LPBITMAPINFO
) lParam1
, (LPBITMAPINFO
) lParam2
);
352 case ICM_DECOMPRESS_GET_FORMAT
:
353 r
= IV50_DecompressGetFormat( (LPBITMAPINFO
) lParam1
, (LPBITMAPINFO
) lParam2
);
356 case ICM_DECOMPRESS_GET_PALETTE
:
357 FIXME("ICM_DECOMPRESS_GET_PALETTE\n");
361 r
= IV50_Decompress( decoder
, (ICDECOMPRESS
*) lParam1
, (DWORD
) lParam2
);
364 case ICM_DECOMPRESS_BEGIN
:
365 r
= IV50_DecompressBegin( decoder
, (LPBITMAPINFO
) lParam1
, (LPBITMAPINFO
) lParam2
);
368 case ICM_DECOMPRESS_END
:
369 r
= ICERR_UNSUPPORTED
;
372 case ICM_DECOMPRESSEX_QUERY
:
373 FIXME("ICM_DECOMPRESSEX_QUERY\n");
376 case ICM_DECOMPRESSEX
:
377 FIXME("ICM_DECOMPRESSEX\n");
380 case ICM_COMPRESS_QUERY
:
383 case ICM_COMPRESS_GET_FORMAT
:
384 case ICM_COMPRESS_END
:
386 FIXME("compression not implemented\n");
393 FIXME("Unknown message: %04x %Id %Id\n", msg
, lParam1
, lParam2
);
399 /***********************************************************************
402 BOOL WINAPI
DllMain(HINSTANCE hModule
, DWORD dwReason
, LPVOID lpReserved
)
404 TRACE("(%p,%lu,%p)\n", hModule
, dwReason
, lpReserved
);
408 case DLL_PROCESS_ATTACH
:
409 DisableThreadLibraryCalls(hModule
);
410 IR50_32_hModule
= hModule
;