blob: 5fef16606555f4ae1edfc95bac29b8cf3ba3c78e [file] [log] [blame]
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/poll.h>
5
6#include <rfb/IrixCLJpegCompressor.h>
Constantin Kaplinsky51e66522007-12-19 06:25:06 +00007#include <rfb/LogWriter.h>
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +00008
9using namespace rfb;
10
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000011static LogWriter vlog("IrixCLJpeg");
12
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000013const int IrixCLJpegCompressor::DEFAULT_QUALITY = 75;
14
15//
16// Constructor and destructor.
17//
18
19IrixCLJpegCompressor::IrixCLJpegCompressor()
20 : m_quality(DEFAULT_QUALITY),
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000021 m_clHandleValid(false),
22 m_srcBufferSize(0),
23 m_dstBufferSize(0),
24 m_sourceData(0),
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000025 m_compressedData(0),
26 m_compressedLength(0)
27{
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000028 int impactScheme = clQuerySchemeFromName(CL_ALG_VIDEO, "impact");
29 if (impactScheme < 0) {
30 vlog.error("Warning: No compression scheme named \"impact\"");
31 }
32
33 vlog.debug("Trying \"impact\" compression scheme (Octane Compression)");
34 int r = clOpenCompressor(impactScheme, &m_clHandle);
35 if (r == SUCCESS) {
36 vlog.debug("Using \"impact\" compression scheme");
37 m_clHandleValid = true;
38 return;
39 }
40 vlog.debug("Trying Cosmo Compress");
41 r = clOpenCompressor(CL_JPEG_COSMO, &m_clHandle);
42 if (r == SUCCESS) {
43 vlog.debug("Using Cosmo Compress");
44 m_clHandleValid = true;
45 return;
46 }
47
Constantin Kaplinsky1b738582007-12-20 15:30:20 +000048#ifdef DEBUG_FORCE_CL
49 vlog.debug("DEBUG: Trying Irix software JPEG compressor");
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000050 r = clOpenCompressor(CL_JPEG_SOFTWARE, &m_clHandle);
51 if (r == SUCCESS) {
Constantin Kaplinsky1b738582007-12-20 15:30:20 +000052 vlog.debug("DEBUG: Using Irix software JPEG compressor");
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000053 m_clHandleValid = true;
54 return;
55 }
Constantin Kaplinsky1b738582007-12-20 15:30:20 +000056#endif
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000057
58 vlog.error("Ho hardware JPEG available via Irix CL library");
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000059}
60
61IrixCLJpegCompressor::~IrixCLJpegCompressor()
62{
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000063 if (m_clHandleValid)
64 clCloseCompressor(m_clHandle);
65
66 if (m_sourceData)
67 delete[] m_sourceData;
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000068 if (m_compressedData)
69 delete[] m_compressedData;
70}
71
72//
73// Set JPEG quality level (1..99)
74//
75
76void
77IrixCLJpegCompressor::setQuality(int level)
78{
79 if (level < 1) {
80 level = 1;
81 } else if (level > 99) {
82 level = 99;
83 }
84 if (level != m_quality) {
85 m_quality = level;
86 }
87}
88
89//
90// Perform JPEG compression.
91//
92// FIXME: This function assumes that pixel format is 32-bit XBGR
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000093// (depth 24), compatible with IRIX Compression Library.
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000094//
95
96void
97IrixCLJpegCompressor::compress(const rdr::U32 *buf,
98 const PixelFormat *fmt,
99 int w, int h, int stride)
100{
101 // Discard previous compression results.
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +0000102 m_compressedLength = 0;
103
Constantin Kaplinsky51e66522007-12-19 06:25:06 +0000104 // A sanity check.
105 if (!m_clHandleValid)
106 return;
107
108 // (Re)allocate the source buffer if necessary.
109 if (w * h > m_srcBufferSize) {
110 if (m_sourceData)
111 delete[] m_sourceData;
112 m_srcBufferSize = w * h;
113 m_sourceData = new rdr::U32[m_srcBufferSize];
114 }
115
116 // Copy source pixels
117 for (int y = 0; y < h; y++) {
118 memcpy(&m_sourceData[y * w], &buf[y * stride], w * sizeof(rdr::U32));
119 }
120
121 // Set image attributes and JPEG quality factor.
122 clSetParam(m_clHandle, CL_FORMAT, CL_FORMAT_XBGR);
123 clSetParam(m_clHandle, CL_IMAGE_WIDTH, w);
124 clSetParam(m_clHandle, CL_IMAGE_HEIGHT, h);
125 clSetParam(m_clHandle, CL_FRAME_BUFFER_SIZE, w * h * 4);
126 clSetParam(m_clHandle, CL_JPEG_QUALITY_FACTOR, m_quality);
127
128 // Determine buffer size required.
129 int newBufferSize = clGetParam(m_clHandle, CL_COMPRESSED_BUFFER_SIZE);
130
Constantin Kaplinsky51e66522007-12-19 06:25:06 +0000131 // (Re)allocate destination buffer if necessary.
132 if (newBufferSize > m_dstBufferSize) {
133 if (m_compressedData)
134 delete[] m_compressedData;
135 m_dstBufferSize = newBufferSize;
136 m_compressedData = new char[m_dstBufferSize];
137 }
138
139 int newCompressedSize = newBufferSize;
140 int n = clCompress(m_clHandle, 1, m_sourceData,
141 &newCompressedSize, m_compressedData);
142 if (n != 1)
143 return;
144
145 m_compressedLength = (size_t)newCompressedSize;
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +0000146}
147