blob: 57e8aa80fc1b2562987fc37966638120f2258797 [file] [log] [blame]
Constantin Kaplinsky71a32f02007-07-24 12:10:16 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/poll.h>
5
6#include <rfb/IrixDMJpegCompressor.h>
7
8using namespace rfb;
9
10const int IrixDMJpegCompressor::DEFAULT_QUALITY = 75;
11
12//
13// Constructor and destructor.
14//
15
16IrixDMJpegCompressor::IrixDMJpegCompressor()
17 : m_quality(DEFAULT_QUALITY),
18 m_width(0),
19 m_height(0),
20 m_bufferSize(0),
21 m_compressedData(0),
22 m_compressedLength(0)
23{
24}
25
26IrixDMJpegCompressor::~IrixDMJpegCompressor()
27{
28 if (m_bufferSize > 0) {
29 m_ic.destroyBufferPool(m_srcPool);
30 m_ic.destroyBufferPool(m_dstPool);
31 }
32
33 if (m_compressedData)
34 delete[] m_compressedData;
35}
36
37//
38// Set JPEG quality level (0..100)
39//
40// FIXME: Call m_ic.setImageQuality() when necessary.
41//
42
43void
44IrixDMJpegCompressor::setQuality(int level)
45{
46 if (level < 0)
47 level = 0;
48 if (level > 100)
49 level = 100;
50
51 m_quality = level;
52}
53
54//
55// Perform JPEG compression.
56//
57// FIXME: This function assumes that pixel format is 32-bit XBGR
58// (depth 24), compatible with IRIX Digital Media libraries.
59//
60
61void
62IrixDMJpegCompressor::compress(const rdr::U32 *buf,
63 const PixelFormat *fmt,
64 int w, int h, int stride)
65{
66 // Discard previous compression results.
67 if (m_compressedData) {
68 delete[] m_compressedData;
69 m_compressedData = 0;
70 }
71 m_compressedLength = 0;
72
73 // Setup the compressor.
74 if (!updateImageSize(w, h))
75 return;
76
77 // Prepare source image data.
78 DMbuffer srcBuf;
79 if (!m_ic.allocBuffer(&srcBuf, m_srcPool)) {
80 return;
81 }
82 // FIXME: Currently, copyToBuffer() copies parts of the image incorrectly.
83 if (!m_ic.copyToBuffer(srcBuf, buf, w * h * (fmt->bpp / 8))) {
84 m_ic.freeBuffer(srcBuf);
85 return;
86 }
87
88 // Initiate compression.
89 if (!m_ic.sendData(srcBuf)) {
90 m_ic.freeBuffer(srcBuf);
91 return;
92 }
93 m_ic.freeBuffer(srcBuf);
94
95 // Wait for results.
96 if (!m_ic.waitConversion()) {
97 perror("poll"); // FIXME: Unify error handling.
98 return;
99 }
100
101 // Save the results.
102 DMbuffer dstBuf;
103 if (!m_ic.receiveData(&dstBuf)) {
104 return;
105 }
106 m_compressedLength = m_ic.getBufferSize(dstBuf);
107 m_compressedData = new char[m_compressedLength];
108 void *bufPtr = m_ic.mapBufferData(dstBuf);
109 memcpy(m_compressedData, bufPtr, m_compressedLength);
110
111 m_ic.freeBuffer(dstBuf);
112}
113
114//
115// Update image size and make sure that our buffer pools will allocate
116// properly-sized buffers.
117//
118// FIXME: Handle image quality separately.
119//
120
121bool
122IrixDMJpegCompressor::updateImageSize(int w, int h)
123{
124 // Configure image formats and parameters, set JPEG image quality level.
125 if (w != m_width || h != m_height) {
126 if (!m_ic.setImageParams(w, h) || !m_ic.setImageQuality(m_quality)) {
127 return false;
128 }
129 m_width = w;
130 m_height = h;
131 }
132
133 // Set up source and destination buffer pools.
134 int dataLen = w * h * 4;
135 if (dataLen > m_bufferSize) {
136 if (m_bufferSize > 0) {
137 m_ic.destroyBufferPool(m_srcPool);
138 m_ic.destroyBufferPool(m_dstPool);
139 m_bufferSize = 0;
140 }
141 if (!m_ic.createSrcBufferPool(&m_srcPool, 1, dataLen)) {
142 return false;
143 }
144 if (!m_ic.registerDstBufferPool(&m_dstPool, 1, dataLen)) {
145 m_ic.destroyBufferPool(m_srcPool);
146 return false;
147 }
148 m_bufferSize = dataLen;
149 }
150
151 return true;
152}
153