diff options
Diffstat (limited to 'replay/compression.cpp')
| -rw-r--r-- | replay/compression.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/replay/compression.cpp b/replay/compression.cpp new file mode 100644 index 0000000..1acb420 --- /dev/null +++ b/replay/compression.cpp @@ -0,0 +1,229 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +//=======================================================================================// + +#include "compression.h" +#include "replay/ienginereplay.h" +#include "replay/replayutils.h" +#include "convar.h" +#include "filesystem.h" +#include "fmtstr.h" +#include "../utils/bzip2/bzlib.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//---------------------------------------------------------------------------------------- + +extern IEngineReplay *g_pEngine; + +//---------------------------------------------------------------------------------------- + +const char *g_pCompressorTypes[ NUM_COMPRESSOR_TYPES ] = +{ + "lzss", + "bz2", +}; + +//---------------------------------------------------------------------------------------- + +class CCompressor_Lzss : public ICompressor +{ +public: + virtual bool Compress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen ) + { + return g_pEngine->LZSS_Compress( pDest, pDestLen, pSource, nSourceLen ); + } + + virtual bool Decompress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen ) + { + return g_pEngine->LZSS_Decompress( pDest, pDestLen, pSource, nSourceLen ); + } + + virtual int GetEstimatedCompressionSize( unsigned int nSourceLen ) + { + return nSourceLen; + } +}; + +//---------------------------------------------------------------------------------------- + +#define BZ2_DEFAULT_BLOCKSIZE100k 9 // Highest compression rate, but uses the most memory +#define BZ2_DEFAULT_WORKFACTOR 0 // Default work factor - same as using 30 + +//---------------------------------------------------------------------------------------- + +class CCompressor_Bz2 : public ICompressor +{ +public: + CCompressor_Bz2( + int nBlockSize100k = BZ2_DEFAULT_BLOCKSIZE100k, + int nWorkFactor = BZ2_DEFAULT_WORKFACTOR + ) + : m_nBlockSize100k( nBlockSize100k ), + m_nWorkFactor( nWorkFactor ) + { + } + + virtual bool Compress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen ) + { + return BZ_OK == BZ2_bzBuffToBuffCompress( + pDest, + pDestLen, + const_cast< char *>( pSource ), + nSourceLen, + m_nBlockSize100k, + 0, // Silent verbosity + m_nWorkFactor + ); + } + + virtual bool Decompress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen ) + { + return BZ_OK == BZ2_bzBuffToBuffDecompress( + pDest, + pDestLen, + const_cast< char * >( pSource ), + nSourceLen, + 0, // Don't use smaller decompressor (half as fast) + 0 // Quiet + ); + } + + virtual int GetEstimatedCompressionSize( unsigned int nSourceLen ) + { + return (int)( 1.1f * nSourceLen ) + 600; + } + +private: + int m_nBlockSize100k; + int m_nWorkFactor; +}; + +//---------------------------------------------------------------------------------------- + +ICompressor *CreateCompressor( CompressorType_t nType ) +{ + switch ( nType ) + { + case COMPRESSORTYPE_BZ2: return new CCompressor_Bz2(); + case COMPRESSORTYPE_LZSS: return new CCompressor_Lzss(); + } + + return NULL; +} + +const char *GetCompressorNameSafe( CompressorType_t nType ) +{ + if ( nType < 0 || nType >= NUM_COMPRESSOR_TYPES ) + return "Unknown compressor type"; + + return g_pCompressorTypes[ nType ]; +} + +//---------------------------------------------------------------------------------------- + +#ifdef _DEBUG + +CON_COMMAND( replay_testcompress, "Test compression" ) +{ + if ( args.ArgC() < 3 ) + { + Warning( "replay_testcompress <lzss|bz2> <file to compress>" ); + return; + } + + const char *pInFilename = args[ 2 ]; + const char *pCompressionTypeName = args[ 1 ]; + + CompressorType_t nCompressorType = COMPRESSORTYPE_INVALID; + + for ( int i = 0; i < (int)NUM_COMPRESSOR_TYPES; ++i ) + { + if ( !V_stricmp( pCompressionTypeName, g_pCompressorTypes[ i ] ) ) + { + nCompressorType = (CompressorType_t)i; + break; + } + } + + if ( nCompressorType == COMPRESSORTYPE_INVALID ) + { + Warning( "Invalid compression type specified. Use \"bz2\" or \"lzss\"\n" ); + return; + } + + const unsigned int nInFileSize = g_pFullFileSystem->Size( pInFilename ); + if ( !nInFileSize ) + { + Warning( "Zero length file.\n" ); + return; + } + + FileHandle_t hInFile = g_pFullFileSystem->Open( pInFilename, "rb" ); + if ( !hInFile ) + { + Warning( "Failed to open file, %s\n", pInFilename ); + return; + } + + char *pUncompressed = new char[ nInFileSize ]; + if ( !pUncompressed ) + { + Warning( "Failed to alloc %u bytes\n", nInFileSize ); + return; + } + + if ( g_pFullFileSystem->Read( pUncompressed, nInFileSize, hInFile ) != (int)nInFileSize ) + { + Warning( "Failed to read file %s\n", pInFilename ); + } + else + { + ICompressor *pCompressor = CreateCompressor( nCompressorType ); + unsigned int nCompressedSize = pCompressor->GetEstimatedCompressionSize( nInFileSize ); + char *pCompressed = new char[ nCompressedSize ]; + if ( !pCompressed ) + { + Warning( "Failed to allocate %u bytes for compressed buffer.\n", nCompressedSize ); + return; + } + + // Compress + if ( !pCompressor->Compress( pCompressed, &nCompressedSize, pUncompressed, nInFileSize ) ) + { + Warning( "Compression failed.\n" ); + } + else + { + CFmtStr fmtOutFilename( "%s.%s", pInFilename, pCompressionTypeName ); + FileHandle_t hOutFile = g_pFullFileSystem->Open( fmtOutFilename.Access(), "wb+" ); + if ( !hOutFile ) + { + Warning( "Failed to open out file, %s\n", fmtOutFilename.Access() ); + } + else + { + if ( g_pFullFileSystem->Write( pCompressed, nCompressedSize, hOutFile ) != (int)nCompressedSize ) + { + Warning( "Failed to write compressed data to %s\n", fmtOutFilename.Access() ); + } + else + { + const float flRatio = (float)nInFileSize / nCompressedSize; + Warning( "Wrote compressed file to successfully (%s) - ratio: %.2f:1\n", fmtOutFilename.Access(), flRatio ); + } + + g_pFullFileSystem->Close( hOutFile ); + } + } + + delete [] pCompressed; + } + + g_pFullFileSystem->Close( hInFile ); +} + +#endif // _DEBUG + +//----------------------------------------------------------------------------------------
\ No newline at end of file |