blob: 6e155ec10aa1c38ff1a6e8006078da65a974b76d [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//
Constantin Kaplinskyc2573702007-10-10 10:03:06 +000038// Set JPEG quality level (1..100)
Constantin Kaplinsky71a32f02007-07-24 12:10:16 +000039//
40// FIXME: Call m_ic.setImageQuality() when necessary.
41//
42
43void
44IrixDMJpegCompressor::setQuality(int level)
45{
Constantin Kaplinskyc2573702007-10-10 10:03:06 +000046 if (level < 1) {
47 level = 1;
48 } else if (level > 100) {
Constantin Kaplinsky71a32f02007-07-24 12:10:16 +000049 level = 100;
Constantin Kaplinskyc2573702007-10-10 10:03:06 +000050 }
Constantin Kaplinsky71a32f02007-07-24 12:10:16 +000051
52 m_quality = level;
53}
54
55//
56// Perform JPEG compression.
57//
58// FIXME: This function assumes that pixel format is 32-bit XBGR
59// (depth 24), compatible with IRIX Digital Media libraries.
60//
61
62void
63IrixDMJpegCompressor::compress(const rdr::U32 *buf,
64 const PixelFormat *fmt,
65 int w, int h, int stride)
66{
67 // Discard previous compression results.
68 if (m_compressedData) {
69 delete[] m_compressedData;
70 m_compressedData = 0;
71 }
72 m_compressedLength = 0;
73
74 // Setup the compressor.
75 if (!updateImageSize(w, h))
76 return;
77
78 // Prepare source image data.
79 DMbuffer srcBuf;
80 if (!m_ic.allocBuffer(&srcBuf, m_srcPool)) {
81 return;
82 }
Constantin Kaplinsky52eaa8c2007-09-04 09:12:59 +000083 int widthInBytes = w * (fmt->bpp / 8);
84 int strideInBytes = stride * (fmt->bpp / 8);
85 if (!m_ic.copyToBuffer(srcBuf, buf, widthInBytes, h, strideInBytes)) {
Constantin Kaplinsky71a32f02007-07-24 12:10:16 +000086 m_ic.freeBuffer(srcBuf);
87 return;
88 }
89
90 // Initiate compression.
91 if (!m_ic.sendData(srcBuf)) {
92 m_ic.freeBuffer(srcBuf);
93 return;
94 }
95 m_ic.freeBuffer(srcBuf);
96
97 // Wait for results.
98 if (!m_ic.waitConversion()) {
99 perror("poll"); // FIXME: Unify error handling.
100 return;
101 }
102
103 // Save the results.
104 DMbuffer dstBuf;
105 if (!m_ic.receiveData(&dstBuf)) {
106 return;
107 }
108 m_compressedLength = m_ic.getBufferSize(dstBuf);
109 m_compressedData = new char[m_compressedLength];
110 void *bufPtr = m_ic.mapBufferData(dstBuf);
111 memcpy(m_compressedData, bufPtr, m_compressedLength);
112
113 m_ic.freeBuffer(dstBuf);
114}
115
116//
117// Update image size and make sure that our buffer pools will allocate
118// properly-sized buffers.
119//
120// FIXME: Handle image quality separately.
121//
122
123bool
124IrixDMJpegCompressor::updateImageSize(int w, int h)
125{
126 // Configure image formats and parameters, set JPEG image quality level.
127 if (w != m_width || h != m_height) {
128 if (!m_ic.setImageParams(w, h) || !m_ic.setImageQuality(m_quality)) {
129 return false;
130 }
131 m_width = w;
132 m_height = h;
133 }
134
135 // Set up source and destination buffer pools.
136 int dataLen = w * h * 4;
137 if (dataLen > m_bufferSize) {
138 if (m_bufferSize > 0) {
139 m_ic.destroyBufferPool(m_srcPool);
140 m_ic.destroyBufferPool(m_dstPool);
141 m_bufferSize = 0;
142 }
143 if (!m_ic.createSrcBufferPool(&m_srcPool, 1, dataLen)) {
144 return false;
145 }
146 if (!m_ic.registerDstBufferPool(&m_dstPool, 1, dataLen)) {
147 m_ic.destroyBufferPool(m_srcPool);
148 return false;
149 }
150 m_bufferSize = dataLen;
151 }
152
153 return true;
154}
155