blob: 3e33a0c1ec480ed642170fcf178aa584ad1994e6 [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
48 // DEBUG: Uncomment to test without hardware compressor.
49 /*
50 vlog.debug("Trying Irix software JPEG compressor (debug mode!)");
51 r = clOpenCompressor(CL_JPEG_SOFTWARE, &m_clHandle);
52 if (r == SUCCESS) {
53 vlog.debug("Using Irix software JPEG compressor (debug mode!)");
54 m_clHandleValid = true;
55 return;
56 }
57 */
58
59 vlog.error("Ho hardware JPEG available via Irix CL library");
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000060}
61
62IrixCLJpegCompressor::~IrixCLJpegCompressor()
63{
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000064 if (m_clHandleValid)
65 clCloseCompressor(m_clHandle);
66
67 if (m_sourceData)
68 delete[] m_sourceData;
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000069 if (m_compressedData)
70 delete[] m_compressedData;
71}
72
73//
74// Set JPEG quality level (1..99)
75//
76
77void
78IrixCLJpegCompressor::setQuality(int level)
79{
80 if (level < 1) {
81 level = 1;
82 } else if (level > 99) {
83 level = 99;
84 }
85 if (level != m_quality) {
86 m_quality = level;
87 }
88}
89
90//
91// Perform JPEG compression.
92//
93// FIXME: This function assumes that pixel format is 32-bit XBGR
Constantin Kaplinsky51e66522007-12-19 06:25:06 +000094// (depth 24), compatible with IRIX Compression Library.
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +000095//
96
97void
98IrixCLJpegCompressor::compress(const rdr::U32 *buf,
99 const PixelFormat *fmt,
100 int w, int h, int stride)
101{
102 // Discard previous compression results.
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +0000103 m_compressedLength = 0;
104
Constantin Kaplinsky51e66522007-12-19 06:25:06 +0000105 // A sanity check.
106 if (!m_clHandleValid)
107 return;
108
109 // (Re)allocate the source buffer if necessary.
110 if (w * h > m_srcBufferSize) {
111 if (m_sourceData)
112 delete[] m_sourceData;
113 m_srcBufferSize = w * h;
114 m_sourceData = new rdr::U32[m_srcBufferSize];
115 }
116
117 // Copy source pixels
118 for (int y = 0; y < h; y++) {
119 memcpy(&m_sourceData[y * w], &buf[y * stride], w * sizeof(rdr::U32));
120 }
121
122 // Set image attributes and JPEG quality factor.
123 clSetParam(m_clHandle, CL_FORMAT, CL_FORMAT_XBGR);
124 clSetParam(m_clHandle, CL_IMAGE_WIDTH, w);
125 clSetParam(m_clHandle, CL_IMAGE_HEIGHT, h);
126 clSetParam(m_clHandle, CL_FRAME_BUFFER_SIZE, w * h * 4);
127 clSetParam(m_clHandle, CL_JPEG_QUALITY_FACTOR, m_quality);
128
129 // Determine buffer size required.
130 int newBufferSize = clGetParam(m_clHandle, CL_COMPRESSED_BUFFER_SIZE);
131
132 /* DEBUG:
133 int arr[200];
134 int nn = clQueryParams(m_clHandle, arr, 200);
135 vlog.debug("Params:");
136 for (int ii = 0; ii < nn; ii += 2) {
137 int id = clGetParamID(m_clHandle, (char *)arr[ii]);
138 vlog.debug(" %s = %d", (char*)arr[ii], clGetParam(m_clHandle, id));
139 }
140 */
141
142 // (Re)allocate destination buffer if necessary.
143 if (newBufferSize > m_dstBufferSize) {
144 if (m_compressedData)
145 delete[] m_compressedData;
146 m_dstBufferSize = newBufferSize;
147 m_compressedData = new char[m_dstBufferSize];
148 }
149
150 int newCompressedSize = newBufferSize;
151 int n = clCompress(m_clHandle, 1, m_sourceData,
152 &newCompressedSize, m_compressedData);
153 if (n != 1)
154 return;
155
156 m_compressedLength = (size_t)newCompressedSize;
Constantin Kaplinsky39e31a12007-12-13 19:16:33 +0000157}
158