/* * @DEC_COPYRIGHT@ */ /* * HISTORY * $Log: h263_dispatch.c,v $ * $EndLog$ */ /* **++ ** FACILITY: Workstation Multimedia (WMM) v1.0 ** ** FILE NAME: h263_dispatch.c ** MODULE NAME: h263_dispatch.c ** ** MODULE DESCRIPTION: ** H.263 ICM driver message dispatch routine. ** ** Functions ** ** DriverProc (Entry point into codec) ** ICH263Message (ICM message handler. Calls routines in h263.c) ** ICH263ClientThread (Thread for processing most messages) ** ICH263ProcessThread (Thread for processing compress/decompress) ** ** Private functions: ** ** DESIGN OVERVIEW: ** Accept the DriverProc message and dispatch to the proper ** handler. ** **-- */ #include #include #include "h26x_int.h" #ifdef _SLIBDEBUG_ #define _DEBUG_ 0 /* detailed debuging statements */ #define _VERBOSE_ 1 /* show progress */ #define _VERIFY_ 1 /* verify correct operation */ #define _WARN_ 1 /* warnings about strange behavior */ #endif static CRITICAL_SECTION h263CritSect; /* Critical section for multi-thread protection */ static HMODULE ghModule=NULL; /* Global handle to Module */ #define BOGUS_DRIVER_ID -1 /* Used during open on NT */ #ifdef WIN32 #define CHECKANDLOCK(x) if (((void *)lParam1==NULL) || (int)lParam2dwRTP==EC_RTP_MODE_OFF) /* must be NetMeeting, turn on RTP */ info->dwRTP=EC_RTP_MODE_A; return (0x60); case ICM_GETINFO: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_GETINFO::\n") ); icinfo = (ICINFO FAR *)lParam1; if (icinfo == NULL) return sizeof(ICINFO); if ((DWORD)lParam2 < sizeof(ICINFO)) return 0; ret = ICH263GetInfo(info, icinfo, (DWORD)lParam2); UNLOCK; return ret; case ICM_GETDEFAULTQUALITY: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_GETDEFAULTQUALITY::\n") ); CHECKANDLOCK(DWORD); ret = ICH263GetDefaultQuality(info, (DWORD *)lParam1); UNLOCK; return ret; case ICM_GETQUALITY: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_GETQUALITY::\n") ); CHECKANDLOCK(DWORD); ret = ICH263GetQuality(info, (DWORD *)lParam1); UNLOCK; return ret; case ICM_SETQUALITY: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_SETQUALITY::\n") ); CHECKANDLOCK(DWORD); ret = ICH263SetQuality(info, (DWORD)lParam1); UNLOCK; return ret; case ICM_GETDEFAULTKEYFRAMERATE: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_GETDEFAULTKEYFRAMERATE:::\n") ); return ((unsigned int)ICERR_UNSUPPORTED); case DECH26X_CUSTOM_ENCODER_CONTROL: _SlibDebug(_VERBOSE_, ScDebugPrintf("------DECH26X_CUSTOM_ENCODER_CONTROL:::\n") ); return(ICH263CustomEncoder(info, (DWORD)lParam2, (DWORD)lParam2)); /********************************************************************* compression messages *********************************************************************/ case ICM_COMPRESS_QUERY: _SlibDebug(_DEBUG_, ScDebugPrintf("------ICM_COMPRESS_QUERY::\n") ); if ((lpbiIn = (LPBITMAPINFOHEADER)lParam1) == NULL) return ((unsigned int)ICERR_BADPARAM); lpbiOut = (LPBITMAPINFOHEADER)lParam2; _SlibDebug(_DEBUG_, ScDebugPrintf(" lpbiIn: %s\n", BMHtoString(lpbiIn)) ); _SlibDebug(_DEBUG_, ScDebugPrintf(" lpbiOut: %s\n", BMHtoString(lpbiOut)) ); /* Lock the memory - have to lock the structure first, and iff * that works, lock the rest */ biSizeIn = lpbiIn->biSize; if (lpbiOut) biSizeOut = lpbiOut->biSize; if ((biSizeIn != sizeof(BITMAPINFOHEADER)) || (lpbiOut && biSizeOut != sizeof(BITMAPINFOHEADER))) { UNLOCK; if ((biSizeIn < sizeof(BITMAPINFOHEADER)) || (lpbiOut && (biSizeOut < sizeof(BITMAPINFOHEADER)))) return ((unsigned int)ICERR_BADPARAM); } ret = ICH263CompressQuery(info, lpbiIn, lpbiOut); UNLOCK; return ret; case ICM_COMPRESS_BEGIN: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_COMPRESS_BEGIN::\n") ); lpbiIn = (LPBITMAPINFOHEADER)lParam1; lpbiOut = (LPBITMAPINFOHEADER)lParam2; _SlibDebug(_VERBOSE_, ScDebugPrintf(" lpbiIn: %s\n", BMHtoString(lpbiIn)) ); _SlibDebug(_VERBOSE_, ScDebugPrintf(" lpbiOut: %s\n", BMHtoString(lpbiOut)) ); if (lpbiIn == NULL || lpbiOut == NULL) return ((unsigned int)ICERR_BADPARAM); /* Lock the memory - have to lock the structure first, and iff * that works, lock the rest */ biSizeIn = lpbiIn->biSize; biSizeOut = lpbiOut->biSize; if (biSizeIn != sizeof(BITMAPINFOHEADER) || biSizeOut != sizeof(BITMAPINFOHEADER)) { _SlibDebug(_VERBOSE_, ScDebugPrintf("biSizeIn or biSizeOut > sizeof(BITMAPINFOHEADER)\n") ); UNLOCK; if ((biSizeIn < sizeof(BITMAPINFOHEADER)) || (biSizeOut < sizeof(BITMAPINFOHEADER))) return ((unsigned int)ICERR_BADPARAM); } ret = ICH263CompressBegin(info, lpbiIn, lpbiOut); UNLOCK; _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_COMPRESS_BEGIN:: Done\n") ); return ret; case ICM_COMPRESS_GET_FORMAT: _SlibDebug(_DEBUG_, ScDebugPrintf("------ICM_COMPRESS_GET_FORMAT::\n") ); /* Nobody uses lpbiIn in this function. Don't lock anything, * the lower layers will have to do any necessary locking. */ return ICH263CompressGetFormat(info, (LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); case ICM_COMPRESS_GET_SIZE: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_COMPRESS_GET_SIZE::\n") ); lpbiIn = (LPBITMAPINFOHEADER)lParam1; lpbiOut = (LPBITMAPINFOHEADER)lParam2; return(ICH263CompressGetSize(lpbiIn)); case ICM_COMPRESS: _SlibDebug(_DEBUG_, ScDebugPrintf("------ICM_COMPRESS::\n") ); ret = ICH263Compress(info, (ICCOMPRESS *) lParam1, (DWORD)lParam2); return ret; case ICM_COMPRESS_END: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_COMPRESS_END::\n") ); return ICH263CompressEnd(info); /********************************************************************* decompress messages *********************************************************************/ case ICM_DECOMPRESS_GET_FORMAT: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_DECOMPRESS_GET_FORMAT::\n") ); /* Nobody uses lpbiIn in this function. Don't lock anything, * the lower layers will have to do any necessary locking. */ return ICH263DecompressGetFormat(info, (LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); case ICM_DECOMPRESS_GET_PALETTE: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_DECOMPRESS_GET_PALETTE::\n") ); if ((lpbiIn = (LPBITMAPINFOHEADER)lParam1) == NULL) return ((unsigned int)ICERR_BADPARAM); if ((biSizeIn = lpbiIn->biSize) != sizeof(BITMAPINFOHEADER)) { UNLOCK; if (biSizeIn < sizeof(BITMAPINFOHEADER)) return (unsigned int)ICERR_BADPARAM; } /*ret = ICH263DecompressGetPalette(info, (LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); */ ret = (MMRESULT)ICERR_BADPARAM; UNLOCK; return ret; case ICM_DECOMPRESS_SET_PALETTE: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_DECOMPRESS_SET_PALETTE::\n") ); return ((unsigned int)ICERR_UNSUPPORTED); case ICM_DECOMPRESS_QUERY: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_DECOMPRESS_QUERY::\n") ); if ((lpbiIn = (LPBITMAPINFOHEADER)lParam1) == NULL) return ((unsigned int)ICERR_BADPARAM); lpbiOut = (LPBITMAPINFOHEADER)lParam2; _SlibDebug(_VERBOSE_, ScDebugPrintf(" lpbiIn: %s\n", BMHtoString(lpbiIn)) ); _SlibDebug(_VERBOSE_, ScDebugPrintf(" lpbiOut: %s\n", BMHtoString(lpbiOut)) ); /* Lock the memory - have to lock the structure first, and iff * that works, lock the rest */ biSizeIn = lpbiIn->biSize; if (lpbiOut) biSizeOut = lpbiOut->biSize; if ((biSizeIn != sizeof(BITMAPINFOHEADER)) || (lpbiOut && biSizeOut != sizeof(BITMAPINFOHEADER))) { UNLOCK; if ((biSizeIn < sizeof(BITMAPINFOHEADER)) || (lpbiOut && (biSizeOut < sizeof(BITMAPINFOHEADER)))) return (unsigned int)ICERR_BADPARAM; } ret = ICH263DecompressQuery(info, lpbiIn, lpbiOut); UNLOCK; return ret; case ICM_DECOMPRESS_BEGIN: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_DECOMPRESS_BEGIN::\n") ); if (((lpbiIn = (LPBITMAPINFOHEADER)lParam1) == NULL) || ((lpbiOut = (LPBITMAPINFOHEADER)lParam2) == NULL)) return ((unsigned int)ICERR_BADPARAM); /* Lock the memory - have to lock the structure first, and iff * that works, lock the rest */ biSizeIn = lpbiIn->biSize; biSizeOut = lpbiOut->biSize; if ((biSizeIn != sizeof(BITMAPINFOHEADER)) || (biSizeOut != sizeof(BITMAPINFOHEADER))) { UNLOCK; if ((biSizeIn < sizeof(BITMAPINFOHEADER)) || (biSizeOut < sizeof(BITMAPINFOHEADER))) return ((unsigned int)ICERR_BADPARAM); } ret = ICH263DecompressBegin(info, lpbiIn, lpbiOut); UNLOCK; return ret; case ICM_DECOMPRESS: _SlibDebug(_DEBUG_, ScDebugPrintf("------ICM_DECOMPRESS::\n") ); icDecompress = (ICDECOMPRESS *)(void *)lParam1; if ((void *)lParam1==NULL && (void *)lParam2==NULL) return (unsigned int)ICERR_BADPARAM; ret = ICH263Decompress(info, (ICDECOMPRESS *) lParam1, (DWORD)lParam2); return ret; case ICM_DECOMPRESS_END: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_DECOMPRESS_END::\n") ); ret = ICH263DecompressEnd(info); return ret; case ICM_COMPRESS_FRAMES_INFO: _SlibDebug(_VERBOSE_, ScDebugPrintf("------ICM_COMPRESS_FRAMES_INFO\n") ); if ((LPVOID)lParam1==NULL || lParam2lStartFrame,cf->lFrameCount,cf->lQuality, cf->lDataRate, cf->lDataRate*8.0/1000, cf->lKeyRate, cf->dwRate*1.0/cf->dwScale) ); /* info->dwBitrate=cf->lDataRate*8; */ info->dwQuality=cf->lQuality; /* info->fFrameRate=(float)(cf->dwRate*1.0/cf->dwScale); */ } return (unsigned int)ICERR_OK; } _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Message(DriverID=%p, message=%d, lParam1=%p,lParam1=%p, info=%p) Unsupported\n", driverHandle, uiMessage, lParam1, lParam2, info) ); return ((unsigned int)ICERR_UNSUPPORTED); } /* **++ ** FUNCTIONAL_NAME: DriverProc ** ** FUNCTIONAL_DESCRIPTION: ** main and only entry point for the server into this driver ** ** FORMAL PARAMETERS: ** client pointer ** driverHandle, returned by us on a DRV_OPEN message ** driverID allocated and passed by the server ** message to handle ** parameters ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/ #define DLLEXPORT MMRESULT DLLEXPORT APIENTRY DriverProc( DWORD_PTR dwDriverID, HDRVR hDriver, UINT message, LPARAM lParam1, LPARAM lParam2 ) { MMRESULT ret = DRV_OK; BOOL notfound = FALSE; H26XINFO *info = NULL; void *client = 0; /* Dummy client pointer for other calls. */ /* * On NT, use __try {} __except() {} to catch * error conditions. */ #ifdef HANDLE_EXCEPTIONS __try { /* try..except */ __try { /* try..finally */ #endif /* * Protect threads from interfering with each other. * To protect against a crash at shutdown, make sure * that the critical section has not been deleted. */ if( h263CritSect.DebugInfo ) EnterCriticalSection( &h263CritSect ) ; _SlibDebug(_DEBUG_, ScDebugPrintf("DriverProc(DriverID=%p,hDriver=%p,message=%d,lParam1=%p,lParam2=%p)\n", dwDriverID, hDriver, message, lParam1, lParam2) ); switch (message) { case DRV_LOAD: ret = DRV_OK; _SlibDebug(_VERBOSE_, ScDebugPrintf("------DRV_LOAD returns %d\n", ret) ); break; case DRV_ENABLE: ret = 0; _SlibDebug(_VERBOSE_, ScDebugPrintf("------DRV_ENABLE returns %d\n", ret) ); break; case DRV_DISABLE: ret = DRV_OK; _SlibDebug(_VERBOSE_, ScDebugPrintf("------DRV_DISABLE returns %d\n", ret) ); break; case DRV_FREE: ret = DRV_OK; _SlibDebug(_VERBOSE_, ScDebugPrintf("------DRV_FREE returns %d\n", ret) ); break; case DRV_OPEN: /* If lParam2 is NULL, then the app is trying to do a CONFIGURE. * Return BOGUS_DRIVER_ID, since we don't support CONFIGURE. */ if( lParam2 == (LONG_PTR) NULL ) ret = (MMRESULT)BOGUS_DRIVER_ID; else /* lParam2 is an ICOPEN structure, let's really open */ ret = (MMRESULT)((ULONG_PTR)ICH263Open((void *) lParam2)); _SlibDebug(_VERBOSE_, ScDebugPrintf("------DRV_OPEN returns %d\n", ret) ); break; case DRV_CLOSE: _SlibDebug(_VERBOSE_, ScDebugPrintf("------DRV_CLOSE. client %d DriverID %p\n", client, dwDriverID) ); ret = 0 ; if ((INT_PTR)dwDriverID != BOGUS_DRIVER_ID) { info = IChic2info((HIC)dwDriverID); if (info) ICH263Close(info, FALSE); else ret = ((unsigned int)ICERR_BADHANDLE); } break; case DRV_QUERYCONFIGURE: /* * this is a GLOBAL query configure */ ret = ICH263QueryConfigure(info); break; case DRV_CONFIGURE: /* * this is a GLOBAL configure ('cause we don't get a configure * for each of our procs, we must have just one configure) */ ret = ICH263Configure(info); break; case DRV_INSTALL: case DRV_REMOVE: case DRV_EXITSESSION: break; default: info = IChic2info((HIC)dwDriverID); if (info) ret = ICH263Message(dwDriverID, message, lParam1, lParam2, info ) ; else ret = ((unsigned int)ICERR_BADHANDLE) ; } #ifdef HANDLE_EXCEPTIONS } __finally { #endif /* HANDLE_EXCEPTIONS */ /* * Leave the critical section, so we don't * deadlock. */ if( h263CritSect.DebugInfo ) LeaveCriticalSection( &h263CritSect ); #ifdef HANDLE_EXCEPTIONS } /* try..finally */ } __except(EXCEPTION_EXECUTE_HANDLER) { /* * NT exception handler. If anything went * wrong in the __try {} section, we will * end up here. */ #if defined(EXCEPTION_MESSAGES) && defined(H263_SUPPORT) // MessageBox(NULL, "Exception in H263 DriverProc", "Warning", MB_OK); #elif defined(EXCEPTION_MESSAGES) // MessageBox(NULL, "Exception in H261 DriverProc", "Warning", MB_OK); #endif /* * Return an error code. */ return((MMRESULT)ICERR_INTERNAL); } /* try..except */ #endif /* HANDLE_EXCEPTIONS */ _SlibDebug(_DEBUG_||_VERBOSE_, ScDebugPrintf("return is %d\n", ret) ); return ret; } /* * Dummy DriverPostReply routine, it does nothing. * It should never be called on NT. */ DriverPostReply(void *client, DWORD ret, DWORD arg ) { return 0; } #ifndef INITCRT #define INITCRT #endif #ifdef INITCRT BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); #endif /* * This DllEntryPoint is needed on NT in order for * an application to connect to a dll properly. */ DLLEXPORT BOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: /* * We're being loaded - save our handle in a global. */ ghModule = (HMODULE) hinstDLL; /* * Initialize the Critical Section that we use * to ensure Threads don't stomp on each other. */ InitializeCriticalSection( &h263CritSect ) ; /* * A Process is also a thread, so deliberately * fall into DLL_THREAD_ATTACH. */ case DLL_THREAD_ATTACH: /* * A Thread have been created that may * be calling this DLL. * Initialize the C run_time library. */ #ifdef INITCRT if( !_CRT_INIT( hinstDLL, fdwReason, lpReserved ) ) return FALSE ; #endif /* INITCRT */ break; case DLL_PROCESS_DETACH: /* * We are shutting down. Perform some cleanup * so that lingering threads won't try to work * and maybe access violate. */ TerminateH263() ; /* * Delete the Critical Section that we created * at load time. */ DeleteCriticalSection( &h263CritSect ) ; /* * A Process is also a thread so deliberately * fall through to DLL_THREAD_DETACH. */ case DLL_THREAD_DETACH: /* * Close down the C run-time library. */ #ifdef INITCRT if( !_CRT_INIT( hinstDLL, fdwReason, lpReserved ) ) return FALSE ; #endif /* INITCRT */ break; } return (TRUE); }