#include #include #include #include #include #include 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; }