mirror of
https://github.com/libretro/Mesen.git
synced 2024-12-13 20:42:24 +00:00
110 lines
2.6 KiB
C++
110 lines
2.6 KiB
C++
//This is based on the code in lsnes' cscd.cpp file
|
|
//A few modifications were done to improve compression speed
|
|
#include "stdafx.h"
|
|
#include <cstring>
|
|
#include "CamstudioCodec.h"
|
|
#include "miniz.h"
|
|
|
|
CamstudioCodec::~CamstudioCodec()
|
|
{
|
|
if(_prevFrame) {
|
|
delete[] _prevFrame;
|
|
_prevFrame = nullptr;
|
|
}
|
|
|
|
if(_currentFrame) {
|
|
delete[] _currentFrame;
|
|
_currentFrame = nullptr;
|
|
}
|
|
|
|
if(_buffer) {
|
|
delete[] _buffer;
|
|
_buffer = nullptr;
|
|
}
|
|
|
|
if(_compressBuffer) {
|
|
delete[] _compressBuffer;
|
|
_compressBuffer = nullptr;
|
|
}
|
|
|
|
deflateEnd(&_compressor);
|
|
}
|
|
|
|
bool CamstudioCodec::SetupCompress(int width, int height, uint32_t compressionLevel)
|
|
{
|
|
_compressionLevel = compressionLevel;
|
|
_orgWidth = width;
|
|
|
|
if(width % 4 != 0) {
|
|
_rowStride = ((int)((width * 24 + 31) / 32 * 4));
|
|
} else {
|
|
_rowStride = width*3;
|
|
}
|
|
_height = height;
|
|
|
|
_prevFrame = new uint8_t[_rowStride*_height]; //24-bit RGB
|
|
_currentFrame = new uint8_t[_rowStride*_height]; //24-bit RGB
|
|
_buffer = new uint8_t[_rowStride*_height]; //24-bit RGB
|
|
|
|
_compressBufferLength = compressBound(_rowStride*_height) + 2;
|
|
_compressBuffer = new uint8_t[_compressBufferLength];
|
|
|
|
memset(_prevFrame, 0, _rowStride * _height);
|
|
memset(_currentFrame, 0, _rowStride * _height);
|
|
memset(_buffer, 0, _rowStride * _height);
|
|
memset(_compressBuffer, 0, _compressBufferLength);
|
|
|
|
deflateInit(&_compressor, compressionLevel);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CamstudioCodec::LoadRow(uint8_t* inPointer, uint8_t* outPointer)
|
|
{
|
|
for(int x = 0; x < _orgWidth; x++) {
|
|
outPointer[0] = inPointer[0];
|
|
outPointer[1] = inPointer[1];
|
|
outPointer[2] = inPointer[2];
|
|
outPointer += 3;
|
|
inPointer += 4;
|
|
}
|
|
}
|
|
|
|
int CamstudioCodec::CompressFrame(bool isKeyFrame, uint8_t *frameData, uint8_t** compressedData)
|
|
{
|
|
deflateReset(&_compressor);
|
|
|
|
_compressor.next_out = _compressBuffer + 2;
|
|
_compressor.avail_out = _compressBufferLength - 2;
|
|
|
|
_compressBuffer[0] = (isKeyFrame ? 0x03 : 0x02) | (_compressionLevel << 4);
|
|
_compressBuffer[1] = 8; //8-bit per color
|
|
|
|
uint8_t* rowBuffer = _currentFrame;
|
|
for(int y = 0; y < _height; y++) {
|
|
LoadRow(frameData + (_height - y - 1) * _orgWidth * 4, rowBuffer);
|
|
rowBuffer += _rowStride;
|
|
}
|
|
|
|
if(isKeyFrame) {
|
|
_compressor.next_in = _currentFrame;
|
|
} else {
|
|
for(int i = 0, len = _rowStride * _height; i < len; i++) {
|
|
_buffer[i] = _currentFrame[i] - _prevFrame[i];
|
|
}
|
|
_compressor.next_in = _buffer;
|
|
}
|
|
|
|
memcpy(_prevFrame, _currentFrame, _rowStride*_height);
|
|
|
|
_compressor.avail_in = _height * _rowStride;
|
|
deflate(&_compressor, MZ_FINISH);
|
|
|
|
*compressedData = _compressBuffer;
|
|
return _compressor.total_out + 2;
|
|
}
|
|
|
|
const char* CamstudioCodec::GetFourCC()
|
|
{
|
|
return "CSCD";
|
|
} |