Created
March 18, 2020 13:51
-
-
Save qsniyg/82da0b0541162cfeb0313d0aa5703a97 to your computer and use it in GitHub Desktop.
Null video codec driver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/configure.ac b/configure.ac | |
| index 7096e2fb66..90adbb9f92 100644 | |
| --- a/configure.ac | |
| +++ b/configure.ac | |
| @@ -3549,6 +3549,7 @@ WINE_CONFIG_MAKEFILE(dlls/ntoskrnl.exe) | |
| WINE_CONFIG_MAKEFILE(dlls/ntoskrnl.exe/tests) | |
| WINE_CONFIG_MAKEFILE(dlls/ntprint) | |
| WINE_CONFIG_MAKEFILE(dlls/ntprint/tests) | |
| +WINE_CONFIG_MAKEFILE(dlls/nullvidc) | |
| WINE_CONFIG_MAKEFILE(dlls/objsel) | |
| WINE_CONFIG_MAKEFILE(dlls/odbc32) | |
| WINE_CONFIG_MAKEFILE(dlls/odbcbcp) | |
| diff --git a/dlls/nullvidc/Makefile.in b/dlls/nullvidc/Makefile.in | |
| new file mode 100644 | |
| index 0000000000..1dbe7333b5 | |
| --- /dev/null | |
| +++ b/dlls/nullvidc/Makefile.in | |
| @@ -0,0 +1,9 @@ | |
| +MODULE = nullvidc.dll | |
| +IMPORTS = user32 | |
| + | |
| +EXTRADLLFLAGS = -mno-cygwin | |
| + | |
| +C_SRCS = \ | |
| + nullvidc.c | |
| + | |
| +RC_SRCS = nullvidc.rc | |
| diff --git a/dlls/nullvidc/nullvidc.c b/dlls/nullvidc/nullvidc.c | |
| new file mode 100644 | |
| index 0000000000..f795bf5149 | |
| --- /dev/null | |
| +++ b/dlls/nullvidc/nullvidc.c | |
| @@ -0,0 +1,305 @@ | |
| +#include <stdarg.h> | |
| +#include "windef.h" | |
| +#include "winbase.h" | |
| +#include "wingdi.h" | |
| +#include "winuser.h" | |
| +#include "commdlg.h" | |
| +#include "vfw.h" | |
| +#include "mmsystem.h" | |
| +#include "nullvidc_private.h" | |
| + | |
| +#include "wine/debug.h" | |
| + | |
| +WINE_DEFAULT_DEBUG_CHANNEL(nullvidc); | |
| + | |
| +static HINSTANCE NULL_hModule; | |
| + | |
| +#define NULL_MAGIC mmioFOURCC('n', 'u', 'l', 'l') | |
| +#define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020) | |
| + | |
| +typedef struct _NULL_Info { | |
| + DWORD dwMagic; | |
| + int depth; | |
| +} NULL_Info; | |
| + | |
| +typedef BYTE uint8_t; | |
| + | |
| + | |
| +static inline int get_stride(int width, int depth) | |
| +{ | |
| + return ((depth * width + 31) >> 3) & ~3; | |
| +} | |
| + | |
| + | |
| +static LRESULT NULL_DecompressQuery( NULL_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) | |
| +{ | |
| + TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out); | |
| + | |
| + if( (info==NULL) || (info->dwMagic!=NULL_MAGIC) ) | |
| + return ICERR_BADPARAM; | |
| + | |
| + return ICERR_OK; | |
| +} | |
| + | |
| + | |
| +static LRESULT NULL_DecompressGetFormat( NULL_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) | |
| +{ | |
| + DWORD size; | |
| + | |
| + TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out); | |
| + | |
| + if( (info==NULL) || (info->dwMagic!=NULL_MAGIC) ) | |
| + return ICERR_BADPARAM; | |
| + | |
| + size = in->bmiHeader.biSize; | |
| + if (in->bmiHeader.biBitCount <= 8) | |
| + size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD); | |
| + | |
| + if( out ) | |
| + { | |
| + memcpy( out, in, size ); | |
| + out->bmiHeader.biBitCount = 24; | |
| + out->bmiHeader.biCompression = BI_RGB; | |
| + out->bmiHeader.biSizeImage = get_stride(in->bmiHeader.biWidth, 24) * in->bmiHeader.biHeight; | |
| + return ICERR_OK; | |
| + } | |
| + return size; | |
| +} | |
| + | |
| + | |
| +static LRESULT NULL_DecompressBegin( NULL_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) | |
| +{ | |
| + TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out); | |
| + | |
| + if( (info==NULL) || (info->dwMagic!=NULL_MAGIC) ) | |
| + return ICERR_BADPARAM; | |
| + | |
| + TRACE("bitmap is %d bpp\n", in->bmiHeader.biBitCount); | |
| + if( in->bmiHeader.biBitCount == 8 ) | |
| + info->depth = 8; | |
| + else if( in->bmiHeader.biBitCount == 16 ) | |
| + info->depth = 16; | |
| + else if( in->bmiHeader.biBitCount == 24 ) | |
| + info->depth = 24; | |
| + else if( in->bmiHeader.biBitCount == 32 ) | |
| + info->depth = 32; | |
| + else | |
| + { | |
| + info->depth = 0; | |
| + FIXME("Unsupported output format %i\n", in->bmiHeader.biBitCount); | |
| + } | |
| + | |
| + return ICERR_OK; | |
| +} | |
| + | |
| + | |
| +static void draw(void* output, int depth, LONG width, LONG height, LONG sz) | |
| +{ | |
| + LONG write_size; | |
| + BYTE *pixel_ptr, *pixel_end; | |
| + | |
| + write_size = width * height * (depth / 8); | |
| + if (write_size > sz) | |
| + write_size = sz; | |
| + | |
| + pixel_end = output + write_size; | |
| + | |
| + for (pixel_ptr = output; pixel_ptr != pixel_end; pixel_ptr++) { | |
| + *pixel_ptr = 0; | |
| + } | |
| +} | |
| + | |
| + | |
| +static LRESULT NULL_Decompress( NULL_Info *info, ICDECOMPRESS *icd, DWORD size ) | |
| +{ | |
| + LONG width, height, stride, sz, write_size; | |
| + void *output, *pixel_ptr, *pixel_end; | |
| + | |
| + TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size); | |
| + | |
| + if( (info==NULL) || (info->dwMagic!=NULL_MAGIC) ) | |
| + return ICERR_BADPARAM; | |
| + | |
| + /* FIXME: flags are ignored */ | |
| + | |
| + width = icd->lpbiInput->biWidth; | |
| + height = icd->lpbiInput->biHeight; | |
| + sz = icd->lpbiInput->biSizeImage; | |
| + | |
| + output = icd->lpOutput; | |
| + | |
| + draw(output, info->depth, width, height, sz); | |
| + | |
| + return ICERR_OK; | |
| +} | |
| + | |
| + | |
| +static LRESULT NULL_DecompressEx( NULL_Info *info, ICDECOMPRESSEX *icd, DWORD size ) | |
| +{ | |
| + LONG width, height, stride, sz; | |
| + void *output; | |
| + | |
| + TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size); | |
| + | |
| + if( (info==NULL) || (info->dwMagic!=NULL_MAGIC) ) | |
| + return ICERR_BADPARAM; | |
| + | |
| + /* FIXME: flags are ignored */ | |
| + | |
| + width = icd->lpbiSrc->biWidth; | |
| + height = icd->lpbiSrc->biHeight; | |
| + sz = icd->lpbiSrc->biSizeImage; | |
| + | |
| + output = icd->lpDst; | |
| + | |
| + draw(output, info->depth, width, height, sz); | |
| + return ICERR_OK; | |
| +} | |
| + | |
| + | |
| +static LRESULT NULL_GetInfo( NULL_Info *info, ICINFO *icinfo, DWORD dwSize ) | |
| +{ | |
| + if (!icinfo) return sizeof(ICINFO); | |
| + if (dwSize < sizeof(ICINFO)) return 0; | |
| + | |
| + icinfo->dwSize = sizeof(ICINFO); | |
| + icinfo->fccType = ICTYPE_VIDEO; | |
| + icinfo->fccHandler = info ? info->dwMagic : NULL_MAGIC; | |
| + icinfo->dwFlags = 0; | |
| + icinfo->dwVersion = ICVERSION; | |
| + icinfo->dwVersionICM = ICVERSION; | |
| + | |
| + LoadStringW(NULL_hModule, IDS_NAME, icinfo->szName, ARRAY_SIZE(icinfo->szName)); | |
| + LoadStringW(NULL_hModule, IDS_DESCRIPTION, icinfo->szDescription, ARRAY_SIZE(icinfo->szDescription)); | |
| + /* msvfw32 will fill icinfo->szDriver for us */ | |
| + | |
| + return sizeof(ICINFO); | |
| +} | |
| + | |
| + | |
| +/*********************************************************************** | |
| + * DriverProc | |
| + */ | |
| +LRESULT WINAPI NULL_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg, | |
| + LPARAM lParam1, LPARAM lParam2 ) | |
| +{ | |
| + NULL_Info *info = (NULL_Info *) dwDriverId; | |
| + LRESULT r = ICERR_UNSUPPORTED; | |
| + | |
| + TRACE("%ld %p %04x %08lx %08lx\n", dwDriverId, hdrvr, msg, lParam1, lParam2); | |
| + | |
| + switch( msg ) | |
| + { | |
| + case DRV_LOAD: | |
| + TRACE("Loaded\n"); | |
| + r = 1; | |
| + break; | |
| + | |
| + case DRV_ENABLE: | |
| + break; | |
| + | |
| + case DRV_OPEN: | |
| + { | |
| + ICINFO *icinfo = (ICINFO *)lParam2; | |
| + | |
| + TRACE("Opened\n"); | |
| + | |
| + if (icinfo && compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) return 0; | |
| + | |
| + info = HeapAlloc( GetProcessHeap(), 0, sizeof (NULL_Info) ); | |
| + if( info ) | |
| + { | |
| + memset( info, 0, sizeof *info ); | |
| + info->dwMagic = NULL_MAGIC; | |
| + } | |
| + r = (LRESULT) info; | |
| + break; | |
| + } | |
| + | |
| + case DRV_CLOSE: | |
| + TRACE("Closed\n"); | |
| + HeapFree( GetProcessHeap(), 0, info ); | |
| + break; | |
| + | |
| + case DRV_DISABLE: | |
| + break; | |
| + | |
| + case DRV_FREE: | |
| + break; | |
| + | |
| + case ICM_GETINFO: | |
| + r = NULL_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 ); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESS_QUERY: | |
| + r = NULL_DecompressQuery( info, (LPBITMAPINFO) lParam1, | |
| + (LPBITMAPINFO) lParam2 ); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESS_GET_FORMAT: | |
| + r = NULL_DecompressGetFormat( info, (LPBITMAPINFO) lParam1, | |
| + (LPBITMAPINFO) lParam2 ); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESS_GET_PALETTE: | |
| + FIXME("ICM_DECOMPRESS_GET_PALETTE\n"); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESSEX_QUERY: | |
| + FIXME("ICM_DECOMPRESSEX_QUERY\n"); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESS: | |
| + r = NULL_Decompress( info, (ICDECOMPRESS*) lParam1, | |
| + (DWORD) lParam2 ); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESS_BEGIN: | |
| + r = NULL_DecompressBegin( info, (LPBITMAPINFO) lParam1, | |
| + (LPBITMAPINFO) lParam2 ); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESSEX: | |
| + r = NULL_DecompressEx( info, (ICDECOMPRESSEX*) lParam1, | |
| + (DWORD) lParam2 ); | |
| + break; | |
| + | |
| + case ICM_DECOMPRESS_END: | |
| + r = ICERR_OK; | |
| + break; | |
| + | |
| + case ICM_COMPRESS_QUERY: | |
| + r = ICERR_BADFORMAT; | |
| + /* fall through */ | |
| + case ICM_COMPRESS_GET_FORMAT: | |
| + case ICM_COMPRESS_END: | |
| + case ICM_COMPRESS: | |
| + FIXME("compression not implemented\n"); | |
| + break; | |
| + | |
| + case ICM_CONFIGURE: | |
| + break; | |
| + | |
| + default: | |
| + FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2); | |
| + } | |
| + | |
| + return r; | |
| +} | |
| + | |
| +/*********************************************************************** | |
| + * DllMain | |
| + */ | |
| +BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) | |
| +{ | |
| + TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved); | |
| + | |
| + switch (dwReason) | |
| + { | |
| + case DLL_PROCESS_ATTACH: | |
| + DisableThreadLibraryCalls(hModule); | |
| + NULL_hModule = hModule; | |
| + break; | |
| + } | |
| + return TRUE; | |
| +} | |
| diff --git a/dlls/nullvidc/nullvidc.rc b/dlls/nullvidc/nullvidc.rc | |
| new file mode 100644 | |
| index 0000000000..399cb14e59 | |
| --- /dev/null | |
| +++ b/dlls/nullvidc/nullvidc.rc | |
| @@ -0,0 +1,11 @@ | |
| +#include "nullvidc_private.h" | |
| + | |
| +#pragma makedep po | |
| + | |
| +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT | |
| + | |
| +STRINGTABLE | |
| +{ | |
| + IDS_NAME "#msgctxt#do not translate#MS-NULL" | |
| + IDS_DESCRIPTION "Wine null video codec" | |
| +} | |
| diff --git a/dlls/nullvidc/nullvidc.spec b/dlls/nullvidc/nullvidc.spec | |
| new file mode 100644 | |
| index 0000000000..aec2706b8e | |
| --- /dev/null | |
| +++ b/dlls/nullvidc/nullvidc.spec | |
| @@ -0,0 +1 @@ | |
| +@ stdcall -private DriverProc(long long long long long) NULL_DriverProc | |
| diff --git a/dlls/nullvidc/nullvidc_private.h b/dlls/nullvidc/nullvidc_private.h | |
| new file mode 100644 | |
| index 0000000000..f087460e56 | |
| --- /dev/null | |
| +++ b/dlls/nullvidc/nullvidc_private.h | |
| @@ -0,0 +1,9 @@ | |
| +#ifndef __NULLVIDC_PRIVATE_H | |
| +#define __NULLVIDC_PRIVATE_H | |
| + | |
| +#include <windef.h> | |
| + | |
| +#define IDS_NAME 100 | |
| +#define IDS_DESCRIPTION 101 | |
| + | |
| +#endif /* __NULLVIDC_PRIVATE_H */ | |
| -- | |
| 2.25.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment