|
|
/*
* @DEC_COPYRIGHT@ */ /*
* HISTORY * $Log: h263.c,v $ * $EndLog$ */ /*
**++ ** FACILITY: Workstation Multimedia (WMM) v1.0 ** ** FILE NAME: h263.c ** MODULE NAME: h263.c ** ** MODULE DESCRIPTION: ** H.263ICM driver ** ** Microsoft file I/O functions ** Implemented as functions: ** H263Close ** H263Compress ** H263Decompress ** H263DecompressEnd ** H263DecompressGetPalette ** H263DecompressGetSize ** H263DecompressQuery ** H263GetInfo ** H263Info ** H263Locate ** H263Open ** H263SendMessage ** ** Private functions: ** ** DESIGN OVERVIEW: ** **-- */ /*-------------------------------------------------------------------------
** Modification History: sc_mem.c ** 04-15-97 HWG Added debug statements to help with checking ** for memory leaks --------------------------------------------------------------------------*/
#include <stdlib.h>
#include <windows.h>
#include <mmsystem.h>
#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 */
#define _MEMORY_ 0 /* memory debugging */
dword scMemDump(); #endif
/* For shared mem */ static H26XINFO *pValidHandles = NULL; static int NextH263Hic = 1; static int OpenCount = 0; static HANDLE InfoMutex = NULL;
#define InitInfoMutex() if (InfoMutex==NULL) InfoMutex=CreateMutex(NULL, FALSE, NULL)
#define FreeInfoMutex() if (InfoMutex!=NULL) \
CloseHandle(InfoMutex); InfoMutex=NULL #define LockInfo() WaitForSingleObject(InfoMutex, 5000);
#define ReleaseInfo() ReleaseMutex(InfoMutex)
/*
* Macros */ #define _ICH263CheckFlags(info, flag) ((info->openFlags & flag) ? TRUE : FALSE)
#define FREE_AND_CLEAR(s) if (s) {ScFree(s); (s)=NULL;}
#define FREE_AND_CLEAR_PA(s) if (s) {ScPaFree(s); (s)=NULL;}
/*
* Default LPBI format */ static BITMAPINFOHEADER __defaultDecompresslpbiOut = { sizeof(BITMAPINFOHEADER), // DWORD biSize;
0, // LONG biWidth;
0, // LONG biHeight;
1, // WORD biPlanes;
24, // WORD biBitCount
BI_RGB, // DWORD biCompression;
0, // DWORD biSizeImage;
0, // LONG biXPelsPerMeter;
0, // LONG biYPelsPerMeter;
0, // DWORD biClrUsed;
0 // DWORD biClrImportant;
};
static BITMAPINFOHEADER __defaultCompresslpbiOut = { sizeof(BITMAPINFOHEADER), // DWORD biSize;
0, // LONG biWidth;
0, // LONG biHeight;
1, // WORD biPlanes;
24, // WORD biBitCount
#ifdef H261_SUPPORT
VIDEO_FORMAT_DIGITAL_H261, // DWORD biCompression;
#else
VIDEO_FORMAT_DIGITAL_H263, // DWORD biCompression;
#endif
0, // DWORD biSizeImage;
0, // LONG biXPelsPerMeter;
0, // LONG biYPelsPerMeter;
0, // DWORD biClrUsed;
0 // DWORD biClrImportant;
};
typedef struct SupportList_s { int InFormat; /* Input format */ int InBits; /* Input number of bits */ int OutFormat; /* Output format */ int OutBits; /* Output number of bits */ } SupportList_t;
/*
** Input & Output Formats supported by H.261 Compression */ static SupportList_t _ICCompressionSupport[] = { BI_DECYUVDIB, 16, H26X_FOURCC, 24, /* YUV 4:2:2 Packed */ BI_YUY2, 16, H26X_FOURCC, 24, /* YUV 4:2:2 Packed */ BI_YU12SEP, 24, H26X_FOURCC, 24, /* YUV 4:1:1 Planar */ BI_YVU9SEP, 24, H26X_FOURCC, 24, /* YUV 16:1:1 Planar */ BI_RGB, 16, H26X_FOURCC, 24, /* RGB 16 */ BI_RGB, 24, H26X_FOURCC, 24, /* RGB 24 */ 0, 0, 0, 0 };
/*
** Input & Output Formats supported by H.261 Decompression */ static SupportList_t _ICDecompressionSupport[] = { H26X_FOURCC, 24, BI_DECYUVDIB, 16, /* YUV 4:2:2 Packed */ H26X_FOURCC, 24, BI_YUY2, 16, /* YUV 4:2:2 Packed */ H26X_FOURCC, 24, BI_YU12SEP, 24, /* YUV 4:1:1 Planar */ H26X_FOURCC, 24, BI_YVU9SEP, 24, /* YUV 16:1:1 Planar */ H26X_FOURCC, 24, BI_BITFIELDS, 32, /* BITFIELDS */ H26X_FOURCC, 24, BI_RGB, 16, /* RGB 16 */ H26X_FOURCC, 24, BI_RGB, 24, /* RGB 24 */ H26X_FOURCC, 24, BI_RGB, 32, /* RGB 32 */ H26X_FOURCC, 24, BI_RGB, 8, /* RGB 8 */ 0, 0, 0, 0 };
/*
** Name: IsSupported ** Desc: Lookup the a given input and output format to see if it ** exists in a SupportList. ** Note: If OutFormat==-1 and OutBits==-1 then only input format ** is checked for support. ** If InFormat==-1 and InBits==-1 then only output format ** is checked for support. ** Return: NULL Formats not supported. ** not NULL A pointer to the list entry. */ static SupportList_t *IsSupported(SupportList_t *list, int InFormat, int InBits, int OutFormat, int OutBits) { if (OutFormat==-1 && OutBits==-1) /* Looking up only the Input format */ { while (list->InFormat || list->InBits) if (list->InFormat == InFormat && list->InBits==InBits) return(list); else list++; return(NULL); } if (InFormat==-1 && InBits==-1) /* Looking up only the Output format */ { while (list->InFormat || list->InBits) if (list->OutFormat == OutFormat && list->OutBits==OutBits) return(list); else list++; return(NULL); } /* Looking up both Input and Output */ while (list->InFormat || list->InBits) if (list->InFormat == InFormat && list->InBits==InBits && list->OutFormat == OutFormat && list->OutBits==OutBits) return(list); else list++; return(NULL); }
unsigned int CalcImageSize(unsigned int fourcc, int w, int h, int bits) { if (h<0) h=-h; if (IsYUV411Sep(fourcc)) return((w * h * 3) / 2); else if (IsYUV422Sep(fourcc) || IsYUV422Packed(fourcc)) return(w * h * 2); else if (IsYUV1611Sep(fourcc)) return((w * h * 9) / 8); #ifdef BICOMP_DECXIMAGEDIB
else if (fourcc==BICOMP_DECXIMAGEDIB) return(bits<=8 ? w * h : (w * h * 4)); #endif
else /* RGB */ return(w * h * (bits+7)/8); }
/*
**++ ** FUNCTIONAL_NAME: InitBitmapinfo ** ** FUNCTIONAL_DESCRIPTION: ** Allocate and copy our local copies of the input and output ** BITMAPINFOHEADERs ** ** FORMAL PARAMETERS: ** info pointer to the driver handle ** lpbiIn pointer to the input BITMAPINFOHEADER ** lpbiOut pointer to the output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** ICERR_OK Success ** ICERR_MEMORY Malloc failed ** ** COMMENTS: ** ** DESIGN: ** **/
static MMRESULT InitBitmapinfo(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { _SlibDebug(_DEBUG_, ScDebugPrintf("In InitBitmapinfo(), IN: 0x%x, OUT: 0x%x\n", lpbiIn, lpbiOut));
if (info->lpbiIn == NULL) { if ((info->lpbiIn = (VOID *)ScAlloc(lpbiIn->biSize)) == NULL) return(unsigned int)(ICERR_MEMORY); } bcopy(lpbiIn, info->lpbiIn, lpbiIn->biSize);
if (info->lpbiOut == NULL) { if ((info->lpbiOut = (VOID *)ScAlloc(lpbiOut->biSize)) == NULL) return(unsigned int)(ICERR_MEMORY); } bcopy(lpbiOut, info->lpbiOut, lpbiOut->biSize);
_SlibDebug(_DEBUG_, ScDebugPrintf("Out InitBitmapinfo()\n")); return(ICERR_OK); }
/*
**++ ** FUNCTIONAL_NAME: ICclient2info ** ** FUNCTIONAL_DESCRIPTION: ** Translate the client pointer to an H26XINFO pointer ** ** FORMAL PARAMETERS: ** client the client ptr to look up ** ** RETURN VALUE: ** ** pointer to the H26XINFO structure or NULL ** ** COMMENTS: ** ** DESIGN: ** **/
H26XINFO *ICclient2info(void *client) { return (H26XINFO *) NULL; }
/*
**++ ** FUNCTIONAL_NAME: IChic2info ** ** FUNCTIONAL_DESCRIPTION: ** Translate the HIC integer to an H26XINFO pointer ** ** FORMAL PARAMETERS: ** hic the hic managed by icm.c ** ** RETURN VALUE: ** ** pointer to the H26XINFO structure or NULL ** ** COMMENTS: ** ** DESIGN: ** **/
H26XINFO *IChic2info(HIC hic) { H26XINFO *retptr=NULL, *ptr;
InitInfoMutex(); LockInfo();
#ifdef HANDLE_EXCEPTIONS
__try { /* pointers go wrong when driver closes */ #endif /* HANDLE_EXCEPTIONS */
for (ptr = pValidHandles; ptr; ptr=ptr->next) if (ptr->hic == hic) { retptr=ptr; break; } #ifdef HANDLE_EXCEPTIONS
} __finally { #endif /* HANDLE_EXCEPTIONS */
ReleaseInfo(); #ifdef HANDLE_EXCEPTIONS
return(retptr); } /* try..except */ #endif /* HANDLE_EXCEPTIONS */
return(retptr); }
/*
**++ ** FUNCTIONAL_NAME: ICHandle2hic ** ** FUNCTIONAL_DESCRIPTION: ** Translate the SLIB codec handle to an ICM HIC value ** ** FORMAL PARAMETERS: ** Sh SLIB handle returned on the SlibOpen call ** ** RETURN VALUE: ** ** hic the hic managed by icm.c ** ** COMMENTS: ** ** DESIGN: ** **/ HIC ICHandle2hic(SlibHandle_t Sh) { H26XINFO *ptr;
InitInfoMutex(); LockInfo(); for (ptr = pValidHandles; ptr; ptr=ptr->next) if (ptr->Sh == Sh) break; ReleaseInfo();
return(ptr->hic); }
/*
**++ ** FUNCTIONAL_NAME: ICclientGone ** ** FUNCTIONAL_DESCRIPTION: ** Sets the clientGone flag in client's H26XINFO ** ** FORMAL PARAMETERS: ** client the client ptr to look up ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
BOOL ICclientGone(void *client) { H26XINFO *ptr;
LockInfo(); for (ptr = pValidHandles; ptr; ptr = ptr->next) { if (ptr->client == client) ptr->clientGone = TRUE; } ReleaseInfo(); return(ptr != NULL); }
/*
**++ ** FUNCTIONAL_NAME: ICH263Open ** ** FUNCTIONAL_DESCRIPTION: ** Open the Software CODEC ** ** FORMAL PARAMETERS: ** client ** ** RETURN VALUE: ** driverHandle ** ** COMMENTS: ** ** DESIGN: ** **/
HIC ICH263Open(void *client) { H26XINFO *info;
ICOPEN *icopen =(ICOPEN *) client; DWORD fccType = icopen->fccType; UINT dwFlags = icopen->dwFlags;
_SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Open()\n") );
/*
* fccType must be 'vidc' */ if (fccType != ICTYPE_VIDEO) return(0);
/*
* We don't support draw operations. */ if ( dwFlags & ICMODE_DRAW ) return 0;
/*
* We don't support compress and decompress * with the same handler. */ if ( (dwFlags & ICMODE_COMPRESS) && (dwFlags & ICMODE_DECOMPRESS) ) return 0;
/*
* At least one of these flags must be set: * COMPRESS, DECOMPRESS or QUERY. */ if ( !(dwFlags & ICMODE_COMPRESS) && !(dwFlags & ICMODE_DECOMPRESS) && !(dwFlags & ICMODE_QUERY) ) return 0; info = (H26XINFO *) ScAlloc(sizeof(H26XINFO)); if (info) { InitInfoMutex(); LockInfo(); OpenCount++; bzero(info, sizeof(H26XINFO)); info->next = pValidHandles; pValidHandles = info; info->hic = (HANDLE) NextH263Hic++; /* !!! check for used entry! */ info->client = client; info->fFrameRate=H26X_DEFAULT_FRAMERATE; info->dwBitrate=H26X_DEFAULT_BITRATE; info->dwPacketSize=H26X_DEFAULT_PACKETSIZE; info->dwRTP=H26X_DEFAULT_RTP;
info->dwQuality=H26X_DEFAULT_QUALITY; info->dwMaxQuality=H26X_DEFAULT_QUALITY; info->dwQi=H26X_DEFAULT_CIF_QI; info->dwQp=H26X_DEFAULT_CIF_QP; info->dwMaxQi=H26X_DEFAULT_CIF_QI; info->dwMaxQp=H26X_DEFAULT_CIF_QP;
info->openFlags = dwFlags; _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Open() info=%p hic=%d\n", info, info->hic) ); ReleaseInfo(); return(info->hic); } else { _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Open() alloc failed\n") ); return(NULL); } }
/*
**++ ** FUNCTIONAL_NAME: H263Close ** ** FUNCTIONAL_DESCRIPTION: ** Close the Software CODEC ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** Does it's own post reply. ** ** DESIGN: ** **/
void ICH263Close(H26XINFO *info, BOOL postreply) { H26XINFO *ptr; int status;
_SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Close() In: info=%p\n", info) ); if (info==NULL) return; if (info->Sh) { _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibClose()\n") ); status=SlibClose(info->Sh); info->Sh = NULL; _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibMemUsed = %ld (after SlibClose)\n", SlibMemUsed()) ); }
_SlibDebug(_VERBOSE_, ScDebugPrintf("Freeing memory\n") ); FREE_AND_CLEAR(info->lpbiIn); FREE_AND_CLEAR(info->lpbiOut); LockInfo(); if (pValidHandles == info) pValidHandles = info->next; else { for (ptr = pValidHandles; ptr && ptr->next; ptr = ptr->next) if (ptr->next == info) /* found info, remove from linked list */ { ptr->next = info->next; break; } } OpenCount--; if (pValidHandles==NULL) /* all instances closed, reset driver ID */ { NextH263Hic=1; ReleaseInfo(); FreeInfoMutex(); } else { ptr = pValidHandles; ReleaseInfo(); } _SlibDebug(_VERBOSE_, ScDebugPrintf("DriverPostReply\n") ); if (postreply && !info->clientGone) { _SlibDebug(_VERBOSE_, ScDebugPrintf("DriverPostReply\n") ); DriverPostReply(info->client, ICERR_OK, 0); } ScFree(info); _SlibDebug(_MEMORY_, scMemDump() ); _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Close() Out\n") ); }
/*
**++ ** FUNCTIONAL_NAME: ICH263QueryConfigure ** ** FUNCTIONAL_DESCRIPTION: ** We don't do configure. Say so. ** ** FORMAL PARAMETERS: ** Handle ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
BOOL ICH263QueryConfigure(H26XINFO *info) { return(FALSE); }
/*
**++ ** FUNCTIONAL_NAME: ICH263Configure ** ** FUNCTIONAL_DESCRIPTION: ** Unsupported function ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263Configure(H26XINFO *info) { return(MMRESULT)(ICERR_UNSUPPORTED); }
MMRESULT ICH263CustomEncoder(H26XINFO *info, DWORD param1, DWORD param2) { SlibHandle_t Sh; SlibStream_t stream=SLIB_STREAM_ALL; WORD task=HIWORD(param1); WORD control=LOWORD(param1); Sh = info->Sh; if (task==EC_SET_CURRENT) { switch (control) { case EC_RTP_HEADER: /* Turn on/off RTP */ info->dwRTP=param2; switch (info->dwRTP) { case EC_RTP_MODE_OFF: SlibSetParamInt (Sh, stream, SLIB_PARAM_FORMATEXT, 0); break; default: case EC_RTP_MODE_A: SlibSetParamInt (Sh, stream, SLIB_PARAM_FORMATEXT, PARAM_FORMATEXT_RTPA); break; case EC_RTP_MODE_B: SlibSetParamInt (Sh, stream, SLIB_PARAM_FORMATEXT, PARAM_FORMATEXT_RTPB); break; case EC_RTP_MODE_C: SlibSetParamInt (Sh, stream, SLIB_PARAM_FORMATEXT, PARAM_FORMATEXT_RTPC); break; } return (ICERR_OK); case EC_PACKET_SIZE: /* Set Packet Size */ info->dwPacketSize=param2; SlibSetParamInt (Sh, stream, SLIB_PARAM_PACKETSIZE, info->dwPacketSize); return (ICERR_OK); case EC_BITRATE: /* Set Bitrate */ info->dwBitrate=param2; SlibSetParamInt (Sh, stream, SLIB_PARAM_BITRATE, info->dwBitrate); return (ICERR_OK); case EC_BITRATE_CONTROL: /* Turn constant bitrate on/off */ if (param2==0) info->dwBitrate=0; else if (info->dwBitrate) info->dwBitrate=H26X_DEFAULT_BITRATE; SlibSetParamInt (Sh, stream, SLIB_PARAM_BITRATE, info->dwBitrate); return (ICERR_OK); } } else if (task==EC_GET_CURRENT) { DWORD *pval=(DWORD *)param2; if (pval==NULL) return((MMRESULT)ICERR_BADPARAM); switch (control) { case EC_RTP_HEADER: *pval=info->dwRTP; return (ICERR_OK); case EC_PACKET_SIZE: *pval=info->dwPacketSize; return (ICERR_OK); case EC_BITRATE: *pval=info->dwBitrate; return (ICERR_OK); case EC_BITRATE_CONTROL: /* Turn constant bitrate on/off */ *pval=info->dwBitrate?1:0; return (ICERR_OK); } } else if (task==EC_GET_FACTORY_DEFAULT) { DWORD *pval=(DWORD *)param2; if (pval==NULL) return((MMRESULT)ICERR_BADPARAM); *pval=0; return (ICERR_OK); } else if (task==EC_GET_FACTORY_LIMITS) { DWORD *pval=(DWORD *)param2; if (pval==NULL) return((MMRESULT)ICERR_BADPARAM); *pval=0; return (ICERR_OK); } else if (task==EC_RESET_TO_FACTORY_DEFAULTS) { return (ICERR_OK); } return((MMRESULT)ICERR_UNSUPPORTED); }
/*
**++ ** FUNCTIONAL_NAME: ICH263QueryAbout ** ** FUNCTIONAL_DESCRIPTION: ** Tell 'em we don't do about ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
BOOL ICH263QueryAbout(H26XINFO *info) { return(FALSE); }
/*
**++ ** FUNCTIONAL_NAME: ICH263About ** ** FUNCTIONAL_DESCRIPTION: ** About box ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263About (H26XINFO *info) { return(MMRESULT)(ICERR_UNSUPPORTED); } /*
**++ ** FUNCTIONAL_NAME: ICH263GetInfo ** ** FUNCTIONAL_DESCRIPTION: ** Return info about codec ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263GetInfo(H26XINFO *info, ICINFO *icinfo, DWORD dwSize) { _SlibDebug(_VERBOSE_, ScDebugPrintf("In H263GetInfo\n") );
icinfo->dwSize = sizeof(ICINFO); icinfo->fccType = ICTYPE_VIDEO; icinfo->fccHandler = H26X_FOURCC; icinfo->dwFlags = VIDCF_QUALITY|VIDCF_CRUNCH|VIDCF_TEMPORAL|VIDCF_FASTTEMPORALC;
icinfo->dwVersion = H26X_VERSION; icinfo->dwVersionICM = ICVERSION;
wcscpy(icinfo->szDescription, H26X_DESCRIPTION); wcscpy(icinfo->szName, H26X_NAME); #if 0
/* we shouldn't change the szDriver field */ wcscpy(icinfo->szDriver, _wgetenv(L"SystemRoot")); if( icinfo->szDriver[0] != 0 ) wcscat(icinfo->szDriver, L"\\System32\\" ); wcscat(icinfo->szDriver, H26X_DRIVER); #endif
return (dwSize); }
/*
**++ ** FUNCTIONAL_NAME: ICH263CompressQuery ** ** FUNCTIONAL_DESCRIPTION: ** Determine compression capability ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263CompressQuery(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { _SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263CompressQuery\n") );
if ( (!_ICH263CheckFlags(info, ICMODE_QUERY)) && ( (!_ICH263CheckFlags(info, ICMODE_COMPRESS)) || (!_ICH263CheckFlags(info, ICMODE_FASTCOMPRESS)) ) ) return (MMRESULT)ICERR_BADHANDLE;
/*
* Must query at least an input or an output format */ if (!lpbiIn && !lpbiOut) return (MMRESULT)(ICERR_BADPARAM);
if (!IsSupported(_ICCompressionSupport, lpbiIn ? lpbiIn->biCompression : -1, lpbiIn ? lpbiIn->biBitCount : -1, lpbiOut ? lpbiOut->biCompression : -1, lpbiOut ? lpbiOut->biBitCount : -1)) return(MMRESULT)(ICERR_BADFORMAT);
return ICERR_OK; }
/*
**++ ** FUNCTIONAL_NAME: ICH263CompressBegin ** ** FUNCTIONAL_DESCRIPTION: ** Prepare to start a Compression operation ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263CompressBegin(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { MMRESULT status; SlibStatus_t sstatus; #ifdef H261_SUPPORT
SlibType_t stype = SLIB_TYPE_H261; #else
SlibType_t stype = SLIB_TYPE_H263; #endif
SlibHandle_t Sh;
_SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263CompressBegin\n") );
if ((!_ICH263CheckFlags(info, ICMODE_COMPRESS)) || (!_ICH263CheckFlags(info, ICMODE_FASTCOMPRESS))) return (MMRESULT)ICERR_BADHANDLE;
if (!lpbiIn || !lpbiOut) return (MMRESULT)(ICERR_BADPARAM); if ((status = ICH263CompressQuery(info, lpbiIn, lpbiOut)) != ICERR_OK) return status; if ((status = InitBitmapinfo(info, lpbiIn, lpbiOut)) != ICERR_OK) return status; info->bUsesCodec = TRUE; lpbiIn=info->lpbiIn; lpbiOut=info->lpbiOut;
lpbiIn->biHeight=-lpbiIn->biHeight; /* SLIB assume first line is top */
info->dwMaxQuality=H26X_DEFAULT_QUALITY; if (lpbiIn->biWidth<168) /* Sub-QCIF */ { info->dwMaxQi=H26X_DEFAULT_SQCIF_QI; info->dwMaxQp=H26X_DEFAULT_SQCIF_QP; } if (lpbiIn->biWidth<300) /* QCIF */ { info->dwMaxQi=H26X_DEFAULT_QCIF_QI; info->dwMaxQp=H26X_DEFAULT_QCIF_QP; } else /* CIF */ { info->dwMaxQi=H26X_DEFAULT_CIF_QI; info->dwMaxQp=H26X_DEFAULT_CIF_QP; } info->lastFrameNum=0; info->lastCompBytes=0; /* Synchronized SLIB SYSTEMS calls */ _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibMemUsed = %ld (before SlibOpen)\n", SlibMemUsed()) ); sstatus = SlibOpenSync (&Sh, SLIB_MODE_COMPRESS, &stype, NULL, 0); if (sstatus!=SlibErrorNone) return((MMRESULT)ICERR_BADPARAM); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_WIDTH, lpbiIn->biWidth); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_HEIGHT, lpbiIn->biHeight); #if 0
SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOFORMAT, lpbiIn->biCompression); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOBITS, lpbiIn->biBitCount); #else
SlibSetParamStruct(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOFORMAT, lpbiIn, lpbiIn->biSize); #endif
// SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOQUALITY, info->dwQuality/100);
SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_QUANTI, info->dwQi); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_QUANTP, info->dwQp); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_BITRATE, info->dwBitrate); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_PACKETSIZE, info->dwPacketSize); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_ALGFLAGS, H26X_DEFAULT_MODE); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_KEYSPACING, 132); #ifdef H261_SUPPORT
SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_MOTIONALG, 1); #else
SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_MOTIONALG, 2); #endif
SlibSetParamFloat(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_FPS, info->fFrameRate); switch (info->dwRTP) { case EC_RTP_MODE_OFF: break; case EC_RTP_MODE_A: SlibSetParamInt(Sh, SLIB_STREAM_ALL, SLIB_PARAM_FORMATEXT, PARAM_FORMATEXT_RTPA); break; case EC_RTP_MODE_B: SlibSetParamInt(Sh, SLIB_STREAM_ALL, SLIB_PARAM_FORMATEXT, PARAM_FORMATEXT_RTPB); break; case EC_RTP_MODE_C: SlibSetParamInt(Sh, SLIB_STREAM_ALL, SLIB_PARAM_FORMATEXT, PARAM_FORMATEXT_RTPC); break; } info->Sh = Sh; lpbiIn->biSizeImage = SlibGetParamInt (Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_IMAGESIZE); info->dwMaxCompBytes = ICH263CompressGetSize(lpbiIn); info->bCompressBegun = TRUE;
return ICERR_OK; }
DWORD ICH263CompressGetSize(LPBITMAPINFOHEADER lpbiIn) { if (lpbiIn==NULL) return(0); else if (lpbiIn->biWidth<=168) return(0x1800); /* Sub-QCIF */ else if (lpbiIn->biWidth<=300) return(0x2000); /* QCIF */ else return(0x8000); /* CIF */ }
/*
**++ ** FUNCTIONAL_NAME: ICH263CompressGetFormat ** ** FUNCTIONAL_DESCRIPTION: ** Get the format for compression ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263CompressGetFormat(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
_SlibDebug(_DEBUG_, ScDebugPrintf("In ICH263CompressGetFormat\n") );
if ((!_ICH263CheckFlags(info, ICMODE_COMPRESS)) && (!_ICH263CheckFlags(info, ICMODE_FASTCOMPRESS)) && (!_ICH263CheckFlags(info, ICMODE_QUERY)))
return (MMRESULT)ICERR_BADHANDLE;
if (lpbiIn == NULL) return (MMRESULT)ICERR_BADPARAM;
if (lpbiOut == NULL) return (sizeof(BITMAPINFOHEADER));
bcopy(&__defaultCompresslpbiOut, lpbiOut, sizeof(BITMAPINFOHEADER)); lpbiOut->biWidth = lpbiIn->biWidth; lpbiOut->biHeight= lpbiIn->biHeight; lpbiOut->biSizeImage = ICH263CompressGetSize(lpbiIn); _SlibDebug(_DEBUG_, ScDebugPrintf(" lpbiOut filled: %s\n", BMHtoString(lpbiOut)) ); return(ICERR_OK); }
/*
**++ ** FUNCTIONAL_NAME: ICH263CompressEnd ** ** FUNCTIONAL_DESCRIPTION: ** Terminate the compression cycle ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263CompressEnd(H26XINFO *info) { _SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263CompressEnd\n") );
if ((!_ICH263CheckFlags(info, ICMODE_COMPRESS)) || (!_ICH263CheckFlags(info, ICMODE_FASTCOMPRESS))) return (MMRESULT)ICERR_BADHANDLE;
if (info->Sh) { _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibClose()\n") ); SlibClose (info->Sh); info->Sh=NULL; _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibMemUsed = %ld (after SlibClose)\n", SlibMemUsed()) ); } info->bCompressBegun = FALSE; return(ICERR_OK); }
/*
**++ ** FUNCTIONAL_NAME: ICH263DecompressQuery ** ** FUNCTIONAL_DESCRIPTION: ** Query the codec to determine if it can decompress specified formats ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263DecompressQuery(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { _SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263DecompressQuery\n") );
if (!_ICH263CheckFlags(info, ICMODE_QUERY) && !_ICH263CheckFlags(info, ICMODE_DECOMPRESS)) return (MMRESULT)ICERR_BADHANDLE;
/*
* Must query at least an input or an output format */ if (!lpbiIn && !lpbiOut) return (MMRESULT)(ICERR_BADPARAM);
if (!IsSupported(_ICDecompressionSupport, lpbiIn ? lpbiIn->biCompression : -1, lpbiIn ? lpbiIn->biBitCount : -1, lpbiOut ? lpbiOut->biCompression : -1, lpbiOut ? lpbiOut->biBitCount : -1)) return(MMRESULT)(ICERR_BADFORMAT);
_SlibDebug(_VERBOSE_, ScDebugPrintf("Out ICH263DecompressQuery\n") ); return ICERR_OK; }
/*
**++ ** FUNCTIONAL_NAME: ICH263DecompressBegin ** ** FUNCTIONAL_DESCRIPTION: ** Begin the decompression process ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** ICERR_OK No error ** ICERR_MEMORY Insufficient memory ** ICERR_BADFORMAT Invalid image format ** ICERR_BADPARAM Invalid image size ** ** COMMENTS: ** ** ** DESIGN: ** **/
MMRESULT ICH263DecompressBegin(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { MMRESULT status; _SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263DecompressBegin\n") );
if (!_ICH263CheckFlags(info, ICMODE_DECOMPRESS)) return (MMRESULT)ICERR_BADHANDLE;
if ((status = ICH263DecompressQuery(info, lpbiIn, lpbiOut)) != ICERR_OK) return status;
if (lpbiIn && lpbiOut) { if ((status = InitBitmapinfo(info, lpbiIn, lpbiOut)) != ICERR_OK) return status;
info->bUsesCodec = TRUE; info->bUsesRender = ((lpbiOut->biBitCount == 8) && ((lpbiOut->biCompression == BI_DECXIMAGEDIB)|| (lpbiOut->biCompression == BI_DECGRAYDIB) || (lpbiOut->biCompression == BI_RGB) ) );
if (!info->bUsesCodec && !info->bUsesRender) return (MMRESULT)ICERR_BADFORMAT;
/* SLIB expects first pixel to be top line */ info->lpbiOut->biHeight=-info->lpbiOut->biHeight; } info->bDecompressBegun = TRUE; _SlibDebug(_VERBOSE_, ScDebugPrintf("Out ICH263DecompressBegin\n") ); return ICERR_OK; }
/*
**++ ** FUNCTIONAL_NAME: ICH263DecompressGetFormat ** ** FUNCTIONAL_DESCRIPTION: ** Get the recommended decompressed format of the codec ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263DecompressGetFormat(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
_SlibDebug(_DEBUG_, ScDebugPrintf("In ICH263DecompressGetFormat\n") );
if (!_ICH263CheckFlags(info, ICMODE_DECOMPRESS) && (!_ICH263CheckFlags(info, ICMODE_QUERY))) return((MMRESULT)ICERR_BADHANDLE);
if (lpbiIn == NULL) return((MMRESULT)ICERR_BADPARAM);
if (lpbiOut == NULL) return (sizeof(BITMAPINFOHEADER));
_SlibDebug(_DEBUG_, ScDebugPrintf("lpbiOut is being filled in DecompressGetFormat\n") ); bcopy(&__defaultDecompresslpbiOut, lpbiOut, sizeof(BITMAPINFOHEADER)); lpbiOut->biWidth = lpbiIn->biWidth; lpbiOut->biHeight= lpbiIn->biHeight; /*
** Return biSizeImage = 1.5 * width * height to let application know ** how big the image buffers must be when passed to ICAddBuffer. ** Internal to the codec, they are used to first store a YUV image, ** then the ICM layer renders it (if rendered data is what's called for */ lpbiOut->biSizeImage = CalcImageSize(lpbiOut->biCompression, lpbiOut->biWidth, lpbiOut->biHeight, lpbiOut->biBitCount); if (lpbiOut->biCompression==BI_RGB && lpbiOut->biBitCount==8) lpbiOut->biClrUsed = 1<<lpbiOut->biBitCount; else lpbiOut->biClrUsed = 0; return(0); }
/*
**++ ** FUNCTIONAL_NAME: ICH263DecompressGetSize ** ** FUNCTIONAL_DESCRIPTION: ** ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263DecompressGetSize(H26XINFO *info, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { return(MMRESULT)(ICERR_UNSUPPORTED); }
/*
**++ ** FUNCTIONAL_NAME: ICH263DecompressEnd ** ** FUNCTIONAL_DESCRIPTION: ** End the decompression process ** ** FORMAL PARAMETERS: ** driverID ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263DecompressEnd(H26XINFO *info) { _SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263DecompressEnd\n") );
if (!_ICH263CheckFlags(info, ICMODE_DECOMPRESS)) return (MMRESULT)ICERR_BADHANDLE;
if (info->Sh) { _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibClose()\n") ); SlibClose(info->Sh); info->Sh=NULL; _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibMemUsed = %ld (after SlibClose)\n", SlibMemUsed()) ); } info->bDecompressBegun = FALSE; return(ICERR_OK); }
MMRESULT ICH263GetDefaultQuality(H26XINFO *info, DWORD * quality) { *quality = H26X_DEFAULT_QUALITY; return((MMRESULT)ICERR_OK); }
MMRESULT ICH263GetQuality(H26XINFO *info, DWORD * quality) { *quality = info->dwQuality; return((MMRESULT)ICERR_OK); }
MMRESULT ICH263SetQuality(H26XINFO *info, DWORD quality) { if (quality>10000) info->dwQuality=10000; else info->dwQuality=quality; // SlibSetParamInt(info->Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOQUALITY,
// info->dwQuality/100);
return((MMRESULT)ICERR_OK); }
/*
**++ ** FUNCTIONAL_NAME: ICH263Compress ** ** FUNCTIONAL_DESCRIPTION: ** Compress a frame ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/ MMRESULT ICH263Compress(H26XINFO *info, ICCOMPRESS *icCompress, DWORD dwSize) { MMRESULT status; LPBITMAPINFOHEADER lpbiIn; LPBITMAPINFOHEADER lpbiOut; LPVOID lpIn; LPVOID lpOut; SlibHandle_t Sh; int compBytes, reqBytes; DWORD newQi, newQp; RTPTRAILER_t *ptrail; BOOL keyframe=icCompress->dwFlags&ICCOMPRESS_KEYFRAME;
if (icCompress->dwFrameSize==0 || icCompress->dwFrameSize>64*1024) reqBytes = info->dwMaxCompBytes; else reqBytes = icCompress->dwFrameSize;
#ifdef H261_SUPPORT
_SlibDebug(_VERBOSE_, ScDebugPrintf("ICH261Compress() FrameNum=%d FrameSize=%d Quality=%d reqBytes=%d\n", icCompress->lFrameNum, icCompress->dwFrameSize, icCompress->dwQuality, reqBytes) ); #else
_SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Compress() FrameNum=%d FrameSize=%d Quality=%d reqBytes=%d\n", icCompress->lFrameNum, icCompress->dwFrameSize, icCompress->dwQuality, reqBytes) ); #endif
if ((!_ICH263CheckFlags(info, ICMODE_COMPRESS)) || (!_ICH263CheckFlags(info, ICMODE_FASTCOMPRESS))) return (MMRESULT)ICERR_BADHANDLE;
status = ICERR_OK;
lpbiIn = icCompress->lpbiInput; lpbiOut = icCompress->lpbiOutput; lpIn = icCompress->lpInput; lpOut = icCompress->lpOutput; lpbiOut->biSizeImage = 0;
/* Synchronized SLIB SYSTEMS calls */ Sh = info->Sh; compress_frame: newQi=newQp=(((10000-icCompress->dwQuality)*30)/10000)+1; if (info->dwRTP!=EC_RTP_MODE_OFF) /* if using RTP, check Quant limits */ { if (newQi<info->dwMaxQi) newQi=info->dwMaxQi; if (newQp<info->dwMaxQp) newQp=info->dwMaxQp; } if (info->dwQi!=newQi) { SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_QUANTI, newQi); info->dwQi=newQi; } if (info->dwQp!=newQp) { SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_QUANTP, newQp); info->dwQp=newQp; } if (keyframe) { _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Compress() I Frame: Qi=%d\n", newQi) ); SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_FRAMETYPE, FRAME_TYPE_I); } else { _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Compress() P Frame: Qp=%d\n", newQp) ); } #ifdef HANDLE_EXCEPTIONS
__try { #endif /* HANDLE_EXCEPTIONS */
status=SlibErrorWriting; /* in case there's an exception */ status = SlibWriteVideo (Sh, SLIB_STREAM_MAINVIDEO, lpIn, lpbiIn->biSizeImage); #ifdef HANDLE_EXCEPTIONS
} __finally { #endif /* HANDLE_EXCEPTIONS */
if (status != SlibErrorNone) { #if defined(EXCEPTION_MESSAGES) && defined(H263_SUPPORT)
// MessageBox(NULL, "Error in H263 SlibWriteVideo", "Warning", MB_OK);
#elif defined(EXCEPTION_MESSAGES)
// MessageBox(NULL, "Error in H261 SlibWriteVideo", "Warning", MB_OK);
#endif
/* make the next frame a key */ SlibSetParamInt(Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_FRAMETYPE, FRAME_TYPE_I); status=(MMRESULT)ICERR_INTERNAL; goto bail; } #ifdef HANDLE_EXCEPTIONS
} #endif /* HANDLE_EXCEPTIONS */
info->lastFrameNum=icCompress->lFrameNum; compBytes=reqBytes; status = SlibReadData(Sh, SLIB_STREAM_ALL, &lpOut, &compBytes, NULL); if (status != SlibErrorNone) { info->lastCompBytes=0; status=(MMRESULT)ICERR_BADSIZE; goto bail; } else /* check the amount of compressed data */ { int extraBytes=0; /* query to see if any more data is left in the codec
* if there is then the quant step was too high, reduce it and try again */ status = SlibReadData(Sh, SLIB_STREAM_ALL, NULL, &extraBytes, NULL); if (extraBytes) { _SlibDebug(_VERBOSE_, ScDebugPrintf("ICH263Compress() Too much data: extraBytes=%d\n", extraBytes) ); if (newQi==31 && newQp==31) /* can't compress to any fewer bytes */ return((MMRESULT)ICERR_BADSIZE); info->dwMaxQi+=1+(newQi/4); /* decrease I frame quality */ if (info->dwMaxQi>31) info->dwMaxQi=31; info->dwMaxQp+=1+(newQp/4); /* decrease P frame quality */ if (info->dwMaxQp>31) info->dwMaxQp=31; /* empty out the compressed data */ SlibSeekEx(Sh, SLIB_STREAM_ALL, SLIB_SEEK_RESET, 0, 0, NULL); /* try to compress again, but make it a key frame */ keyframe=TRUE; goto compress_frame; } /* we have compressed data less than or equal to request size */ info->lastCompBytes=compBytes; lpbiOut->biSizeImage = compBytes; status = ICERR_OK; } if (info->dwRTP!=EC_RTP_MODE_OFF) /* RTP is on */ { ptrail=(RTPTRAILER_t *)((unsigned char *)lpOut+compBytes-sizeof(RTPTRAILER_t)); /* check for valid RTP trailer */ if (compBytes<sizeof(RTPTRAILER_t) || ptrail->dwUniqueCode!=H26X_FOURCC) return((MMRESULT)ICERR_INTERNAL); } if (icCompress->dwFlags&ICCOMPRESS_KEYFRAME) /* I frame */ { if (compBytes>(reqBytes>>2)) { info->dwMaxQi+=1+(newQi>>2); /* decrease quality */ if (info->dwMaxQi>31) info->dwMaxQi=31; } else if (newQi==info->dwMaxQi && compBytes<=(reqBytes>>2) && info->dwMaxQi>0) info->dwMaxQi--; /* increase quality */ } else /* P frame */ { if (compBytes>(reqBytes>>1)) { info->dwMaxQp+=1+(newQp>>2); /* decrease max quality */ if (info->dwMaxQp>31) info->dwMaxQp=31; /* also decrease I quality, since P limits are based on I limits */ info->dwMaxQi+=1+(newQi>>2); if (info->dwMaxQi>31) info->dwMaxQi=31; } else if (newQp==info->dwMaxQp && compBytes<(reqBytes>>1) && info->dwMaxQp>(info->dwMaxQi+3)/2) info->dwMaxQp--; /* increase max quality */ } #ifdef H261_SUPPORT
_SlibDebug(_VERBOSE_||_WARN_, ScDebugPrintf("ICH261Compress(%c) lpOut=%p reqBytes=%d compBytes=%d Qi=%d Qp=%d MaxQi=%d MaxQp=%d\n", (icCompress->dwFlags&ICCOMPRESS_KEYFRAME)?'I':'P', lpOut, reqBytes, compBytes, newQi, newQp, info->dwMaxQi, info->dwMaxQp) ); #else
_SlibDebug(_VERBOSE_||_WARN_, ScDebugPrintf("ICH263Compress(%c) lpOut=%p reqBytes=%d compBytes=%d Qi=%d Qp=%d MaxQi=%d MaxQp=%d\n", (icCompress->dwFlags&ICCOMPRESS_KEYFRAME)?'I':'P', lpOut, reqBytes, compBytes, newQi, newQp, info->dwMaxQi, info->dwMaxQp) ); #endif
_SlibDebug(_DEBUG_, { RTPTRAILER_t *ptrail=(RTPTRAILER_t *) ((unsigned char *)lpOut+compBytes-sizeof(RTPTRAILER_t)); ScDebugPrintf(" Trailer: \n" " dwVersion=%d\n" " dwFlags=0x%04X\n" " dwUniqueCode=%c%c%c%c\n" " dwCompressedSize=%d\n" " dwNumberOfPackets=%d\n" " SourceFormat=%d\n" " TR=%d TRB=%d DBQ=%d\n", ptrail->dwVersion, ptrail->dwFlags, ptrail->dwUniqueCode&0xFF, (ptrail->dwUniqueCode>>8)&0xFF, (ptrail->dwUniqueCode>>16)&0xFF, (ptrail->dwUniqueCode>>24)&0xFF, ptrail->dwCompressedSize, ptrail->dwNumberOfPackets, ptrail->SourceFormat, ptrail->TR,ptrail->TRB,ptrail->DBQ); } ); /* _SlibDebug */ #ifdef H261_SUPPORT
_SlibDebug((_DEBUG_ || _WARN_) && (info->dwRTP!=EC_RTP_MODE_OFF), { RTPTRAILER_t *ptrail=(RTPTRAILER_t *) ((unsigned char *)lpOut+compBytes-sizeof(RTPTRAILER_t)); SvH261BITSTREAM_INFO *pinfo; BOOL rtperror=FALSE; unsigned int i; pinfo=(SvH261BITSTREAM_INFO *)((unsigned char *)ptrail -(ptrail->dwNumberOfPackets*16)); if (ptrail->dwNumberOfPackets==0 || pinfo[0].dwBitOffset!=0) { // MessageBox(NULL, "Critical Error in H.261", "Warning", MB_OK);
rtperror=TRUE; } /* check for sequential BitOffsets */ for (i=1; i<ptrail->dwNumberOfPackets; i++) if (pinfo[i-1].dwBitOffset>=pinfo[i].dwBitOffset) { // MessageBox(NULL, "Critical Error in H.261", "Warning", MB_OK);
rtperror=TRUE; break; } if (pinfo[ptrail->dwNumberOfPackets-1].dwBitOffset>ptrail->dwCompressedSize*8) { // MessageBox(NULL, "Critical Error in H.261", "Warning", MB_OK);
rtperror=TRUE; } if (_DEBUG_ || rtperror) { if (ptrail->dwNumberOfPackets>64*2) ptrail->dwNumberOfPackets=32; for (i=0; i<ptrail->dwNumberOfPackets; i++) { ScDebugPrintf(" H261 Packet %2d: dwFlag=0x%04X dwBitOffset=%d\n" " MBAP=%d Quant=%d\n" " GOBN=%d HMV=%d VMV=%d\n", i, pinfo[i].dwFlag, pinfo[i].dwBitOffset, pinfo[i].MBAP, pinfo[i].Quant, pinfo[i].GOBN, pinfo[i].HMV, pinfo[i].VMV); } } } ); /* _SlibDebug */ #else /* H263 */
_SlibDebug((_DEBUG_ || _WARN_) && (info->dwRTP!=EC_RTP_MODE_OFF), { RTPTRAILER_t *ptrail=(RTPTRAILER_t *) ((unsigned char *)lpOut+compBytes-sizeof(RTPTRAILER_t)); SvH263BITSTREAM_INFO *pinfo; BOOL rtperror=FALSE; unsigned int i; pinfo=(SvH263BITSTREAM_INFO *)((unsigned char *)ptrail -(ptrail->dwNumberOfPackets*16)); if (ptrail->dwNumberOfPackets==0 || pinfo[0].dwBitOffset!=0) { // MessageBox(NULL, "Critical Error in H.263", "Warning", MB_OK);
rtperror=TRUE; } /* check for sequential BitOffsets */ for (i=1; i<ptrail->dwNumberOfPackets; i++) if (pinfo[i-1].dwBitOffset>=pinfo[i].dwBitOffset) { // MessageBox(NULL, "Critical Error in H.263", "Warning", MB_OK);
rtperror=TRUE; break; } if (pinfo[ptrail->dwNumberOfPackets-1].dwBitOffset>ptrail->dwCompressedSize*8) { // MessageBox(NULL, "Critical Error in H.263", "Warning", MB_OK);
rtperror=TRUE; } if (_DEBUG_ || rtperror) { if (ptrail->dwNumberOfPackets>64*2) ptrail->dwNumberOfPackets=32; for (i=0; i<ptrail->dwNumberOfPackets; i++) { ScDebugPrintf(" H263 Packet %2d: dwFlag=0x%04X dwBitOffset=%d Mode=%d\n" " MBA=%d Quant=%d\n" " GOBN=%d HMV1=%d VMV1=%d HMV2=%d VMV2=%d\n", i, pinfo[i].dwFlag, pinfo[i].dwBitOffset, pinfo[i].Mode, pinfo[i].MBA, pinfo[i].Quant, pinfo[i].GOBN, pinfo[i].HMV1, pinfo[i].VMV1, pinfo[i].HMV2, pinfo[i].VMV2); } } } ); /* _SlibDebug */ #endif
bail: return status; } /*
**++ ** FUNCTIONAL_NAME: ICH263Decompress ** ** FUNCTIONAL_DESCRIPTION: ** Open the Software CODEC ** ** FORMAL PARAMETERS: ** driverID ** lpbiIn input BITMAPINFOHEADER ** lpbiOut output BITMAPINFOHEADER ** ** RETURN VALUE: ** ** COMMENTS: ** ** DESIGN: ** **/
MMRESULT ICH263Decompress(H26XINFO *info, ICDECOMPRESS *icDecompress, DWORD dwSize)
{ MMRESULT result=(MMRESULT)ICERR_OK; LPBITMAPINFOHEADER lpbiIn; LPBITMAPINFOHEADER lpbiOut; LPVOID lpIn; LPVOID lpOut; SlibHandle_t Sh; SlibStatus_t status; #ifdef H261_SUPPORT
SlibType_t stype = SLIB_TYPE_H261; #else
SlibType_t stype = SLIB_TYPE_H263; #endif
_SlibDebug(_VERBOSE_, ScDebugPrintf("In ICH263Decompress lpIn is %d\n",lpIn) );
if (!_ICH263CheckFlags(info, ICMODE_DECOMPRESS)) return((MMRESULT)ICERR_BADHANDLE);
lpIn = icDecompress->lpInput; lpOut = icDecompress->lpOutput;
lpbiIn = icDecompress->lpbiInput; lpbiOut = icDecompress->lpbiOutput; if (!info->bDecompressBegun && (result = ICH263DecompressBegin(info, lpbiIn, lpbiOut))!=ICERR_OK) return(result);
if (icDecompress->dwFlags & ICDECOMPRESS_HURRYUP) return((MMRESULT)ICERR_OK);
info->lpbiIn->biSizeImage = lpbiIn->biSizeImage; info->lpbiOut->biClrImportant = lpbiOut->biClrImportant; info->lpbiOut->biSizeImage = lpbiOut->biSizeImage; // they don't set it
lpbiIn=info->lpbiIn; lpbiOut=info->lpbiOut; if (!info->Sh) { _SlibDebug(_VERBOSE_, ScDebugPrintf("SlibMemUsed = %ld (before SlibOpen)\n", SlibMemUsed()) ); status = SlibOpenSync (&Sh, SLIB_MODE_DECOMPRESS, &stype, lpIn, icDecompress->lpbiInput->biSizeImage); SlibSetParamInt (Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_HEIGHT, lpbiOut->biHeight); SlibSetParamInt (Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_WIDTH, lpbiOut->biWidth); SlibSetParamInt (Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOFORMAT, lpbiOut->biCompression); SlibSetParamInt (Sh, SLIB_STREAM_MAINVIDEO, SLIB_PARAM_VIDEOBITS, lpbiOut->biBitCount); info->Sh = Sh; _SlibDebug(_WARN_ && status!=SlibErrorNone, ScDebugPrintf("ICH263Decompress() SlibOpenSync: %s\n", SlibGetErrorText(status)) ); } else { DWORD dwPadding=0xFFFFFFFF; status=SlibAddBuffer (info->Sh, SLIB_DATA_COMPRESSED, lpIn, icDecompress->lpbiInput->biSizeImage); _SlibDebug(_WARN_ && status!=SlibErrorNone, ScDebugPrintf("ICH263Decompress() SlibAddBuffer(%p, %d): %s\n", lpIn, lpbiIn->biSizeImage, SlibGetErrorText(status)) ); /* Add some padding bits to the end because the codecs try to peek
* forward past the very last bits of the buffer */ status=SlibAddBuffer (info->Sh, SLIB_DATA_COMPRESSED, (char *)&dwPadding, sizeof(DWORD)); } if (status==SlibErrorNone) { #ifdef HANDLE_EXCEPTIONS
__try { #endif /* HANDLE_EXCEPTIONS */
status = SlibErrorReading; /* in case there's an exception */ status = SlibReadVideo(info->Sh, SLIB_STREAM_MAINVIDEO, &lpOut, &lpbiOut->biSizeImage); #ifdef HANDLE_EXCEPTIONS
} __finally { #endif /* HANDLE_EXCEPTIONS */
if (status!=SlibErrorNone) { _SlibDebug(_WARN_ && status!=SlibErrorNone, ScDebugPrintf("ICH263Decompress() SlibReadVideo: %s\n", SlibGetErrorText(status)) ); status=(MMRESULT)ICERR_BADFORMAT; } else status=(MMRESULT)ICERR_OK; goto bail; #ifdef HANDLE_EXCEPTIONS
} #endif /* HANDLE_EXCEPTIONS */
} else status=(MMRESULT)ICERR_BADFORMAT; bail: return(status); }
/*
* This routine just nulls out the pValidHandles * pointer so that no lingering threads will be * able to use it. It's only called at dll * shutdown on NT. */
int TerminateH263() { pValidHandles = NULL; return 0; }
|