blob: dda059f8814c522a85b3f034875ab76265e59841 [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 }
Constantin Kaplinsky52eaa8c2007-09-04 09:12:59 +000082 int widthInBytes = w * (fmt->bpp / 8);
83 int strideInBytes = stride * (fmt->bpp / 8);
84 if (!m_ic.copyToBuffer(srcBuf, buf, widthInBytes, h, strideInBytes)) {
Constantin Kaplinsky71a32f02007-07-24 12:10:16 +000085 m_ic.freeBuffer(srcBuf);
86 return;
87 }
88
89 // Initiate compression.
90 if (!m_ic.sendData(srcBuf)) {
91 m_ic.freeBuffer(srcBuf);
92 return;
93 }
94 m_ic.freeBuffer(srcBuf);
95
96 // Wait for results.
97 if (!m_ic.waitConversion()) {
98 perror("poll"); // FIXME: Unify error handling.
99 return;
100 }
101
102 // Save the results.
103 DMbuffer dstBuf;
104 if (!m_ic.receiveData(&dstBuf)) {
105 return;
106 }
107 m_compressedLength = m_ic.getBufferSize(dstBuf);
108 m_compressedData = new char[m_compressedLength];
109 void *bufPtr = m_ic.mapBufferData(dstBuf);
110 memcpy(m_compressedData, bufPtr, m_compressedLength);
111
112 m_ic.freeBuffer(dstBuf);
113}
114
115//
116// Update image size and make sure that our buffer pools will allocate
117// properly-sized buffers.
118//
119// FIXME: Handle image quality separately.
120//
121
122bool
123IrixDMJpegCompressor::updateImageSize(int w, int h)
124{
125 // Configure image formats and parameters, set JPEG image quality level.
126 if (w != m_width || h != m_height) {
127 if (!m_ic.setImageParams(w, h) || !m_ic.setImageQuality(m_quality)) {
128 return false;
129 }
130 m_width = w;
131 m_height = h;
132 }
133
134 // Set up source and destination buffer pools.
135 int dataLen = w * h * 4;
136 if (dataLen > m_bufferSize) {
137 if (m_bufferSize > 0) {
138 m_ic.destroyBufferPool(m_srcPool);
139 m_ic.destroyBufferPool(m_dstPool);
140 m_bufferSize = 0;
141 }
142 if (!m_ic.createSrcBufferPool(&m_srcPool, 1, dataLen)) {
143 return false;
144 }
145 if (!m_ic.registerDstBufferPool(&m_dstPool, 1, dataLen)) {
146 m_ic.destroyBufferPool(m_srcPool);
147 return false;
148 }
149 m_bufferSize = dataLen;
150 }
151
152 return true;
153}
154