blob: 5fef16606555f4ae1edfc95bac29b8cf3ba3c78e [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <rfb/IrixCLJpegCompressor.h>
#include <rfb/LogWriter.h>
using namespace rfb;
static LogWriter vlog("IrixCLJpeg");
const int IrixCLJpegCompressor::DEFAULT_QUALITY = 75;
//
// Constructor and destructor.
//
IrixCLJpegCompressor::IrixCLJpegCompressor()
: m_quality(DEFAULT_QUALITY),
m_clHandleValid(false),
m_srcBufferSize(0),
m_dstBufferSize(0),
m_sourceData(0),
m_compressedData(0),
m_compressedLength(0)
{
int impactScheme = clQuerySchemeFromName(CL_ALG_VIDEO, "impact");
if (impactScheme < 0) {
vlog.error("Warning: No compression scheme named \"impact\"");
}
vlog.debug("Trying \"impact\" compression scheme (Octane Compression)");
int r = clOpenCompressor(impactScheme, &m_clHandle);
if (r == SUCCESS) {
vlog.debug("Using \"impact\" compression scheme");
m_clHandleValid = true;
return;
}
vlog.debug("Trying Cosmo Compress");
r = clOpenCompressor(CL_JPEG_COSMO, &m_clHandle);
if (r == SUCCESS) {
vlog.debug("Using Cosmo Compress");
m_clHandleValid = true;
return;
}
#ifdef DEBUG_FORCE_CL
vlog.debug("DEBUG: Trying Irix software JPEG compressor");
r = clOpenCompressor(CL_JPEG_SOFTWARE, &m_clHandle);
if (r == SUCCESS) {
vlog.debug("DEBUG: Using Irix software JPEG compressor");
m_clHandleValid = true;
return;
}
#endif
vlog.error("Ho hardware JPEG available via Irix CL library");
}
IrixCLJpegCompressor::~IrixCLJpegCompressor()
{
if (m_clHandleValid)
clCloseCompressor(m_clHandle);
if (m_sourceData)
delete[] m_sourceData;
if (m_compressedData)
delete[] m_compressedData;
}
//
// Set JPEG quality level (1..99)
//
void
IrixCLJpegCompressor::setQuality(int level)
{
if (level < 1) {
level = 1;
} else if (level > 99) {
level = 99;
}
if (level != m_quality) {
m_quality = level;
}
}
//
// Perform JPEG compression.
//
// FIXME: This function assumes that pixel format is 32-bit XBGR
// (depth 24), compatible with IRIX Compression Library.
//
void
IrixCLJpegCompressor::compress(const rdr::U32 *buf,
const PixelFormat *fmt,
int w, int h, int stride)
{
// Discard previous compression results.
m_compressedLength = 0;
// A sanity check.
if (!m_clHandleValid)
return;
// (Re)allocate the source buffer if necessary.
if (w * h > m_srcBufferSize) {
if (m_sourceData)
delete[] m_sourceData;
m_srcBufferSize = w * h;
m_sourceData = new rdr::U32[m_srcBufferSize];
}
// Copy source pixels
for (int y = 0; y < h; y++) {
memcpy(&m_sourceData[y * w], &buf[y * stride], w * sizeof(rdr::U32));
}
// Set image attributes and JPEG quality factor.
clSetParam(m_clHandle, CL_FORMAT, CL_FORMAT_XBGR);
clSetParam(m_clHandle, CL_IMAGE_WIDTH, w);
clSetParam(m_clHandle, CL_IMAGE_HEIGHT, h);
clSetParam(m_clHandle, CL_FRAME_BUFFER_SIZE, w * h * 4);
clSetParam(m_clHandle, CL_JPEG_QUALITY_FACTOR, m_quality);
// Determine buffer size required.
int newBufferSize = clGetParam(m_clHandle, CL_COMPRESSED_BUFFER_SIZE);
// (Re)allocate destination buffer if necessary.
if (newBufferSize > m_dstBufferSize) {
if (m_compressedData)
delete[] m_compressedData;
m_dstBufferSize = newBufferSize;
m_compressedData = new char[m_dstBufferSize];
}
int newCompressedSize = newBufferSize;
int n = clCompress(m_clHandle, 1, m_sourceData,
&newCompressedSize, m_compressedData);
if (n != 1)
return;
m_compressedLength = (size_t)newCompressedSize;
}