DWORD CodecInst::CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { CompressEnd(); // free resources if necessary if (!CanCompress(lpbiIn, lpbiOut, true)) return ICERR_BADFORMAT; codec = new VideoCodec(); if (!codec) return ICERR_MEMORY; if (!codec->SetupCompress( lpbiIn->biWidth, lpbiIn->biHeight)) return ICERR_MEMORY; return ICERR_OK; }
DWORD CodecInst::Compress(ICCOMPRESS* icinfo, DWORD dwSize) { int i, pitch; zmbv_format_t format; LPBITMAPINFOHEADER lpbiIn=icinfo->lpbiInput; LPBITMAPINFOHEADER lpbiOut=icinfo->lpbiOutput; if (!CanCompress(lpbiIn, lpbiOut, true)) return ICERR_BADFORMAT; if (!icinfo->lpInput || !icinfo->lpOutput) return ICERR_ABORT; switch (GetInputBitDepth(lpbiIn)) { case 8: format = ZMBV_FORMAT_8BPP; pitch = lpbiIn->biWidth; break; case 15: format = ZMBV_FORMAT_15BPP; pitch = lpbiIn->biWidth * 2; break; case 16: format = ZMBV_FORMAT_16BPP; pitch = lpbiIn->biWidth * 2; break; case 32: format = ZMBV_FORMAT_32BPP; pitch = lpbiIn->biWidth * 4; break; } // DIB scanlines for RGB formats are always aligned to DWORD. pitch = (pitch + 3) & ~3; // force a key frame if requested by the client int flags = 0; if (icinfo->dwFlags & ICCOMPRESS_KEYFRAME) flags |= 1; codec->PrepareCompressFrame( flags, format, 0, icinfo->lpOutput, 99999999); char *readPt = (char *)icinfo->lpInput + pitch*(lpbiIn->biHeight - 1); for(i = 0;i<lpbiIn->biHeight;i++) { codec->CompressLines(1, (void **)&readPt ); readPt -= pitch; } lpbiOut->biSizeImage = codec->FinishCompressFrame(); if (flags & 1) *icinfo->lpdwFlags = AVIIF_KEYFRAME; else *icinfo->lpdwFlags = 0; return ICERR_OK; }
DWORD CodecInst::Compress(ICCOMPRESS* icinfo, DWORD dwSize) { int i, pitch; zmbv_format_t format; LPBITMAPINFOHEADER lpbiIn=icinfo->lpbiInput; LPBITMAPINFOHEADER lpbiOut=icinfo->lpbiOutput; if (!CanCompress(lpbiIn, lpbiOut, true)) return ICERR_BADFORMAT; if (!icinfo->lpInput || !icinfo->lpOutput) return ICERR_ABORT; switch (GetInputBitDepth(lpbiIn)) { case 8: format = ZMBV_FORMAT_8BPP; pitch = lpbiIn->biWidth; break; case 15: format = ZMBV_FORMAT_15BPP; pitch = lpbiIn->biWidth * 2; break; case 16: format = ZMBV_FORMAT_16BPP; pitch = lpbiIn->biWidth * 2; break; case 32: format = ZMBV_FORMAT_32BPP; pitch = lpbiIn->biWidth * 4; break; } // DIB scanlines for RGB formats are always aligned to DWORD. pitch = (pitch + 3) & ~3; // force a key frame if requested by the client int flags = 0; if (icinfo->dwFlags & ICCOMPRESS_KEYFRAME) flags |= 1; char palette[256 * 4]; char *pal = NULL; if (lpbiIn->biBitCount == 8) { const int entries = icinfo->lpbiInput->biClrUsed ? icinfo->lpbiInput->biClrUsed : 256; const char* srcpal = (char *)icinfo->lpbiInput + icinfo->lpbiInput->biSize; char* dstpal = palette; memset(palette, 0, sizeof palette); for(int i=0; i<entries; ++i) { dstpal[0] = srcpal[2]; dstpal[1] = srcpal[1]; dstpal[2] = srcpal[0]; dstpal[3] = 0; dstpal += 4; srcpal += 4; } pal = palette; } codec->PrepareCompressFrame( flags, format, pal, icinfo->lpOutput, 99999999); char *readPt = (char *)icinfo->lpInput + pitch*(lpbiIn->biHeight - 1); for(i = 0;i<lpbiIn->biHeight;i++) { codec->CompressLines(1, (void **)&readPt ); readPt -= pitch; } lpbiOut->biSizeImage = codec->FinishCompressFrame(); if (flags & 1) *icinfo->lpdwFlags = AVIIF_KEYFRAME; else *icinfo->lpdwFlags = 0; return ICERR_OK; }
DWORD CodecInst::CompressGetSize(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { if (!CanCompress(lpbiIn, lpbiOut, true)) return ICERR_BADFORMAT; return lpbiIn->biWidth * lpbiIn->biHeight * lpbiIn->biBitCount/8 + 1024; }
DWORD CodecInst::CompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { if (CanCompress(lpbiIn,lpbiOut,false)) return ICERR_OK; return ICERR_BADFORMAT; }