1 /*
2 * encoder-jpeg.cc --
3 *
4 * Motion Jpeg video encoder
5 *
6 * Copyright (c) 1994-2002 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * A. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * B. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * C. Neither the names of the copyright holders nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
22 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 static const char rcsid[] =
35 "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/encoder-jpeg.cc,v 1.20 2003/11/19 19:20:17 aswan Exp $";
36
37 #include <stdio.h>
38 #include <errno.h>
39 #include "rtp/inet.h"
40 #include "rtp/rtp.h"
41 #include "codec/dct.h"
42 #include "misc/bsd-endian.h"
43 #include "rtp/pktbuf-rtp.h"
44 #include "codec/module-list.h"
45
46 #include "codec/encoder-jpeg.h"
47
48
49 static class JpegEncoderClass : public TclClass {
50 public:
51 JpegEncoderClass() : TclClass("Module/VideoEncoder/Pixel/JPEG") {}
52 TclObject* create(int, const char*const*) {
53 return (new JpegEncoder);
54 }
55 } jpeg_encoder_class;
56
57 #define HDRSIZE (sizeof(rtphdr) + 8)
58
59 //
60 // STORE_BITS
61 //
62 // This macro copies bb (a 32 or 64-bit number) into the buffer pointed by
63 // bc. It escapes any byte-aligned 0xff with 0xff00
64 //
65 #if NBIT == 64
66 #define STORE_BITS(bb, bc) \
67 { \
68 u_char t = bb>>56; \
69 *bc++ = t; \
70 if (t == 0xff) *bc++ = 0; \
71 t = bb>>48; \
72 *bc++ = t; \
73 if (t == 0xff) *bc++ = 0; \
74 t = bb>>40; \
75 *bc++ = t; \
76 if (t == 0xff) *bc++ = 0; \
77 t = bb>>32; \
78 *bc++ = t; \
79 if (t == 0xff) *bc++ = 0; \
80 t = bb>>24; \
81 *bc++ = t; \
82 if (t == 0xff) *bc++ = 0; \
83 t = bb>>16; \
84 *bc++ = t; \
85 if (t == 0xff) *bc++ = 0; \
86 t = bb>>8; \
87 *bc++ = t; \
88 if (t == 0xff) *bc++ = 0; \
89 t = bb; \
90 *bc++ = t; \
91 if (t == 0xff) *bc++ = 0; \
92 }
93
94 #else
95
96 #define STORE_BITS(bb, bc) \
97 { \
98 u_char t = bb>>24; \
99 *bc++ = t; \
100 if (t == 0xff) *bc++ = 0; \
101 t = bb>>16; \
102 *bc++ = t; \
103 if (t == 0xff) *bc++ = 0; \
104 t = bb>>8; \
105 *bc++ = t; \
106 if (t == 0xff) *bc++ = 0; \
107 t = bb; \
108 *bc++ = t; \
109 if (t == 0xff) *bc++ = 0; \
110 }
111
112 #endif
113
114 //
115 // PUT_BITS
116 //
117 // This macro stores "n" bits located at "bits" into the buffer pointed
118 // by bc. It uses bb:nbb to cache bits in order to write an integer number
119 // of sizeof(NBITS).
120 //
121 // bits: the bits we want to write
122 // n: number of useful bits in "bits"
123 // bb: the NBIT-length cache integer
124 // nbb: occupied bits in bb so far
125 // bc: final buffer
126 //
127
128 #define PUT_BITS(bits, n, nbb, bb, bc) \
129 { \
130 nbb += (n); \
131 if (nbb > NBIT) { \
132 u_int extra = (nbb) - NBIT; \
133 bb |= (BB_INT)(bits) >> extra; \
134 STORE_BITS(bb, bc) \
135 bb = (BB_INT)(bits) << (NBIT - extra); \
136 nbb = extra; \
137 } else \
138 bb |= (BB_INT)(bits) << (NBIT - (nbb)); \
139 }
140
141
142 //
143 // JPEG tables definition
144 //
145 static const int stdlqt[] = {
146 16, 11, 10, 16, 24, 40, 51, 61,
147 12, 12, 14, 19, 26, 58, 60, 55,
148 14, 13, 16, 24, 40, 57, 69, 56,
149 14, 17, 22, 29, 51, 87, 80, 62,
150 18, 22, 37, 56, 68, 109, 103, 77,
151 24, 35, 55, 64, 81, 104, 113, 92,
152 49, 64, 78, 87, 103, 121, 120, 101,
153 72, 92, 95, 98, 112, 100, 103, 99 };
154
155 static const int stdcqt[] = {
156 17, 18, 24, 47, 99, 99, 99, 99,
157 18, 21, 26, 66, 99, 99, 99, 99,
158 24, 26, 56, 99, 99, 99, 99, 99,
159 47, 66, 99, 99, 99, 99, 99, 99,
160 99, 99, 99, 99, 99, 99, 99, 99,
161 99, 99, 99, 99, 99, 99, 99, 99,
162 99, 99, 99, 99, 99, 99, 99, 99,
163 99, 99, 99, 99, 99, 99, 99, 99 };
164
165 static struct JpegEncoder::huffentry ldht[] = {
166 {0x0, 2}, {0x2, 3}, {0x3, 3}, {0x4, 3}, {0x5, 3}, {0x6, 3},
167 {0xe, 4}, {0x1e, 5}, {0x3e, 6}, {0x7e, 7}, {0xfe, 8}, {0x1fe, 9}};
168
169 static struct JpegEncoder::huffentry cdht[] = {
170 {0x0, 2}, {0x1, 2}, {0x2, 2}, {0x6, 3}, {0xe, 4}, {0x1e, 5}, {0x3e, 6},
171 {0x7e, 7}, {0xfe, 8}, {0x1fe, 9}, {0x3fe, 10}, {0x7fe, 11}};
172
173 static struct JpegEncoder::huffentry laht[] = {
174 {0x0a, 4}, {0x00, 2}, {0x01, 2}, {0x04, 3},
175 {0x0b, 4}, {0x1a, 5}, {0x78, 7}, {0xf8, 8},
176 {0x3f6, 10}, {0xff82, 16}, {0xff83, 16}, {0x00, 0},
177 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
178 {0x00, 0}, {0x0c, 4}, {0x1b, 5}, {0x79, 7},
179 {0x1f6, 9}, {0x7f6, 11}, {0xff84, 16}, {0xff85, 16},
180 {0xff86, 16}, {0xff87, 16}, {0xff88, 16}, {0x00, 0},
181 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
182 {0x00, 0}, {0x1c, 5}, {0xf9, 8}, {0x3f7, 10},
183 {0xff4, 12}, {0xff89, 16}, {0xff8a, 16}, {0xff8b, 16},
184 {0xff8c, 16}, {0xff8d, 16}, {0xff8e, 16}, {0x00, 0},
185 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
186 {0x00, 0}, {0x3a, 6}, {0x1f7, 9}, {0xff5, 12},
187 {0xff8f, 16}, {0xff90, 16}, {0xff91, 16}, {0xff92, 16},
188 {0xff93, 16}, {0xff94, 16}, {0xff95, 16}, {0x00, 0},
189 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
190 {0x00, 0}, {0x3b, 6}, {0x3f8, 10}, {0xff96, 16},
191 {0xff97, 16}, {0xff98, 16}, {0xff99, 16}, {0xff9a, 16},
192 {0xff9b, 16}, {0xff9c, 16}, {0xff9d, 16}, {0x00, 0},
193 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
194 {0x00, 0}, {0x7a, 7}, {0x7f7, 11}, {0xff9e, 16},
195 {0xff9f, 16}, {0xffa0, 16}, {0xffa1, 16}, {0xffa2, 16},
196 {0xffa3, 16}, {0xffa4, 16}, {0xffa5, 16}, {0x00, 0},
197 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
198 {0x00, 0}, {0x7b, 7}, {0xff6, 12}, {0xffa6, 16},
199 {0xffa7, 16}, {0xffa8, 16}, {0xffa9, 16}, {0xffaa, 16},
200 {0xffab, 16}, {0xffac, 16}, {0xffad, 16}, {0x00, 0},
201 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
202 {0x00, 0}, {0xfa, 8}, {0xff7, 12}, {0xffae, 16},
203 {0xffaf, 16}, {0xffb0, 16}, {0xffb1, 16}, {0xffb2, 16},
204 {0xffb3, 16}, {0xffb4, 16}, {0xffb5, 16}, {0x00, 0},
205 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
206 {0x00, 0}, {0x1f8, 9}, {0x7fc0, 15}, {0xffb6, 16},
207 {0xffb7, 16}, {0xffb8, 16}, {0xffb9, 16}, {0xffba, 16},
208 {0xffbb, 16}, {0xffbc, 16}, {0xffbd, 16}, {0x00, 0},
209 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
210 {0x00, 0}, {0x1f9, 9}, {0xffbe, 16}, {0xffbf, 16},
211 {0xffc0, 16}, {0xffc1, 16}, {0xffc2, 16}, {0xffc3, 16},
212 {0xffc4, 16}, {0xffc5, 16}, {0xffc6, 16}, {0x00, 0},
213 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
214 {0x00, 0}, {0x1fa, 9}, {0xffc7, 16}, {0xffc8, 16},
215 {0xffc9, 16}, {0xffca, 16}, {0xffcb, 16}, {0xffcc, 16},
216 {0xffcd, 16}, {0xffce, 16}, {0xffcf, 16}, {0x00, 0},
217 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
218 {0x00, 0}, {0x3f9, 10}, {0xffd0, 16}, {0xffd1, 16},
219 {0xffd2, 16}, {0xffd3, 16}, {0xffd4, 16}, {0xffd5, 16},
220 {0xffd6, 16}, {0xffd7, 16}, {0xffd8, 16}, {0x00, 0},
221 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
222 {0x00, 0}, {0x3fa, 10}, {0xffd9, 16}, {0xffda, 16},
223 {0xffdb, 16}, {0xffdc, 16}, {0xffdd, 16}, {0xffde, 16},
224 {0xffdf, 16}, {0xffe0, 16}, {0xffe1, 16}, {0x00, 0},
225 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
226 {0x00, 0}, {0x7f8, 11}, {0xffe2, 16}, {0xffe3, 16},
227 {0xffe4, 16}, {0xffe5, 16}, {0xffe6, 16}, {0xffe7, 16},
228 {0xffe8, 16}, {0xffe9, 16}, {0xffea, 16}, {0x00, 0},
229 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
230 {0x00, 0}, {0xffeb, 16}, {0xffec, 16}, {0xffed, 16},
231 {0xffee, 16}, {0xffef, 16}, {0xfff0, 16}, {0xfff1, 16},
232 {0xfff2, 16}, {0xfff3, 16}, {0xfff4, 16}, {0x00, 0},
233 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
234 {0x7f9, 11}, {0xfff5, 16}, {0xfff6, 16}, {0xfff7, 16},
235 {0xfff8, 16}, {0xfff9, 16}, {0xfffa, 16}, {0xfffb, 16},
236 {0xfffc, 16}, {0xfffd, 16}, {0xfffe, 16}, {0x00, 0},
237 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} };
238
239 static struct JpegEncoder::huffentry caht[] = {
240 {0x00, 2}, {0x01, 2}, {0x04, 3}, {0x0a, 4},
241 {0x18, 5}, {0x19, 5}, {0x38, 6}, {0x78, 7},
242 {0x1f4, 9}, {0x3f6, 10}, {0xff4, 12}, {0x00, 0},
243 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
244 {0x00, 0}, {0x0b, 4}, {0x39, 6}, {0xf6, 8},
245 {0x1f5, 9}, {0x7f6, 11}, {0xff5, 12}, {0xff88, 16},
246 {0xff89, 16}, {0xff8a, 16}, {0xff8b, 16}, {0x00, 0},
247 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
248 {0x00, 0}, {0x1a, 5}, {0xf7, 8}, {0x3f7, 10},
249 {0xff6, 12}, {0x7fc2, 15}, {0xff8c, 16}, {0xff8d, 16},
250 {0xff8e, 16}, {0xff8f, 16}, {0xff90, 16}, {0x00, 0},
251 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
252 {0x00, 0}, {0x1b, 5}, {0xf8, 8}, {0x3f8, 10},
253 {0xff7, 12}, {0xff91, 16}, {0xff92, 16}, {0xff93, 16},
254 {0xff94, 16}, {0xff95, 16}, {0xff96, 16}, {0x00, 0},
255 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
256 {0x00, 0}, {0x3a, 6}, {0x1f6, 9}, {0xff97, 16},
257 {0xff98, 16}, {0xff99, 16}, {0xff9a, 16}, {0xff9b, 16},
258 {0xff9c, 16}, {0xff9d, 16}, {0xff9e, 16}, {0x00, 0},
259 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
260 {0x00, 0}, {0x3b, 6}, {0x3f9, 10}, {0xff9f, 16},
261 {0xffa0, 16}, {0xffa1, 16}, {0xffa2, 16}, {0xffa3, 16},
262 {0xffa4, 16}, {0xffa5, 16}, {0xffa6, 16}, {0x00, 0},
263 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
264 {0x00, 0}, {0x79, 7}, {0x7f7, 11}, {0xffa7, 16},
265 {0xffa8, 16}, {0xffa9, 16}, {0xffaa, 16}, {0xffab, 16},
266 {0xffac, 16}, {0xffad, 16}, {0xffae, 16}, {0x00, 0},
267 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
268 {0x00, 0}, {0x7a, 7}, {0x7f8, 11}, {0xffaf, 16},
269 {0xffb0, 16}, {0xffb1, 16}, {0xffb2, 16}, {0xffb3, 16},
270 {0xffb4, 16}, {0xffb5, 16}, {0xffb6, 16}, {0x00, 0},
271 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
272 {0x00, 0}, {0xf9, 8}, {0xffb7, 16}, {0xffb8, 16},
273 {0xffb9, 16}, {0xffba, 16}, {0xffbb, 16}, {0xffbc, 16},
274 {0xffbd, 16}, {0xffbe, 16}, {0xffbf, 16}, {0x00, 0},
275 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
276 {0x00, 0}, {0x1f7, 9}, {0xffc0, 16}, {0xffc1, 16},
277 {0xffc2, 16}, {0xffc3, 16}, {0xffc4, 16}, {0xffc5, 16},
278 {0xffc6, 16}, {0xffc7, 16}, {0xffc8, 16}, {0x00, 0},
279 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
280 {0x00, 0}, {0x1f8, 9}, {0xffc9, 16}, {0xffca, 16},
281 {0xffcb, 16}, {0xffcc, 16}, {0xffcd, 16}, {0xffce, 16},
282 {0xffcf, 16}, {0xffd0, 16}, {0xffd1, 16}, {0x00, 0},
283 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
284 {0x00, 0}, {0x1f9, 9}, {0xffd2, 16}, {0xffd3, 16},
285 {0xffd4, 16}, {0xffd5, 16}, {0xffd6, 16}, {0xffd7, 16},
286 {0xffd8, 16}, {0xffd9, 16}, {0xffda, 16}, {0x00, 0},
287 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
288 {0x00, 0}, {0x1fa, 9}, {0xffdb, 16}, {0xffdc, 16},
289 {0xffdd, 16}, {0xffde, 16}, {0xffdf, 16}, {0xffe0, 16},
290 {0xffe1, 16}, {0xffe2, 16}, {0xffe3, 16}, {0x00, 0},
291 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
292 {0x00, 0}, {0x7f9, 11}, {0xffe4, 16}, {0xffe5, 16},
293 {0xffe6, 16}, {0xffe7, 16}, {0xffe8, 16}, {0xffe9, 16},
294 {0xffea, 16}, {0xffeb, 16}, {0xffec, 16}, {0x00, 0},
295 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
296 {0x00, 0}, {0x3fe0, 14}, {0xffed, 16}, {0xffee, 16},
297 {0xffef, 16}, {0xfff0, 16}, {0xfff1, 16}, {0xfff2, 16},
298 {0xfff3, 16}, {0xfff4, 16}, {0xfff5, 16}, {0x00, 0},
299 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
300 {0x3fa, 10}, {0x7fc3, 15}, {0xfff6, 16}, {0xfff7, 16},
301 {0xfff8, 16}, {0xfff9, 16}, {0xfffa, 16}, {0xfffb, 16},
302 {0xfffc, 16}, {0xfffd, 16}, {0xfffe, 16}, {0x00, 0},
303 {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} };
304
305 static const char ss[] = {
306 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
307 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
308 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
309 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
310 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
311 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
312 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
313 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
314 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
315 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
316 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
317 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
318 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
319 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
320 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
321 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
322
323
324
325 //
326 // JpegEncoder
327 //
328 JpegEncoder::JpegEncoder() : EncoderModule(),
329 bb_(0), nbb_(0), bs_(0), bc_(0), quant_(0),
330 lpred_(0), crpred_(0), cbpred_(0), nmcu_(0), w_(0), h_(0)
331 {
332 setq(30);
333 }
334
335
336 void JpegEncoder::setq(int q)
337 {
338 int lqt[64], cqt[64];
339 quant_ = q;
340
341 int s = (q>50) ? 200-q*2 : 5000/q;
342 for (int i=0; i<64; i++) {
343 int v = (stdlqt[i] * s + 50)/ 100;
344 if (v < 1) {
345 lqt[i] = 1;
346 } else if (v > 255) {
347 lqt[i] = 255;
348 } else {
349 lqt[i] = v;
350 }
351
352 v = (stdcqt[i] * s + 50)/ 100;
353 if (v < 1) {
354 cqt[i] = 1;
355 } else if (v > 255) {
356 cqt[i] = 255;
357 } else {
358 cqt[i] = v;
359 }
360 }
361 fdct_fold_q(lqt, lqt_);
362 fdct_fold_q(cqt, cqt_);
363 }
364
365
366 void JpegEncoder::size(int w, int h)
367 {
368 FrameModule::size(w, h);
369 if ((w & 0xf) || (h & 0xf)) {
370 fprintf(stderr, "JpegEncoder: bad geometry: %dx%d\n", w, h);
371 exit(1);
372 }
373 w_ = w>>3;
374 h_ = h>>3;
375 nmcu_ = (w_>>1) * h_;
376 }
377
378
379 int JpegEncoder::command(int argc, const char*const* argv)
380 {
381 // let the encoder choose the color-subsampling scheme
382 if (argc == 2 && strcmp(argv[1], "frame-format") == 0) {
383 Tcl& tcl = Tcl::instance();
384 tcl.result("422");
385 return (TCL_OK);
386 }
387
388 if (argc == 3 && strcmp(argv[1], "q") == 0) {
389 setq(atoi(argv[2]));
390 return (TCL_OK);
391 }
392 return (EncoderModule::command(argc, argv));
393 }
394
395
396 void JpegEncoder::recv(Buffer* bp)
397 {
398 YuvFrame* vf = (YuvFrame*)bp;
399 if (!samesize(vf)) {
400 size(vf->width_, vf->height_);
401 }
402
403 encode(vf);
404 }
405
406
407 //
408 // JpegEncoder::flush
409 //
410 // Description: This method prepares the format-specific RTP header and
411 // sends it to PacketModule::recv() in order to be sent
412 //
413 int JpegEncoder::flush(pktbuf* pb, int nbit, pktbuf* npb)
414 {
415 u_char* obc = bc_;
416
417 /* flush bit buffer */
418 STORE_BITS(bb_, bc_);
419
420 int cc = (nbit + 7) >> 3;
421
422 /*FIXME*/
423 if ((cc == 0) && (npb != 0)) {
424 abort();
425 }
426
427 pb->len = cc + HDRSIZE;
428 rtphdr* rh = (rtphdr*)pb->data;
429 if (npb == 0) {
430 rh->rh_flags |= htons(RTP_M);
431 }
432
433 if (npb != 0) {
434 u_char* nbs = &npb->data[HDRSIZE];
435 int extra = obc - (bs_ + (nbit >> 3));
436 if (extra > 0) {
437 memcpy(nbs, bs_ + (nbit >> 3), extra);
438 }
439 bs_ = nbs;
440 bc_ = nbs + extra;
441 }
442
443 // do send the packet
444 pb->attach();
445 target_->recv(pb);
446
447 Module * target;
448 target = target_list_->first_;
449 while (target != NULL) {
450 pb->attach();
451 target->recv(pb);
452 target = target->next();
453 }
454 pb->release();
455
456 return (cc + HDRSIZE);
457 }
458
459 #define SSSS(n) (((n)&~0xff) ? (8+ss[(n)>>8]) : ss[n])
460
461
462 void JpegEncoder::encode_blk(const short* blk, short* dcpred,
463 struct huffentry* dcht, struct huffentry* acht)
464 {
465 BB_INT bb = bb_;
466 u_int nbb = nbb_;
467 u_char* bc = bc_;
468
469 /* code dc */
470 short diff = blk[0] - *dcpred;
471 *dcpred = blk[0];
472
473 u_char len;
474
475 if (diff < 0){
476 len = SSSS(-diff);
477 huffentry e = dcht[len];
478 PUT_BITS(e.val, e.nb, nbb, bb, bc);
479 PUT_BITS((diff-1)&(~(-1<<len)), len, nbb, bb, bc);
480 } else {
481 len = SSSS(diff);
482 huffentry e = dcht[len];
483 PUT_BITS(e.val, e.nb, nbb, bb, bc);
484 PUT_BITS(diff, len, nbb, bb, bc);
485 }
486
487 /* code ac terms */
488 int run = 0;
489 const u_char* colzag = &COLZAG[0];
490 for (int zag; (zag = *++colzag) != 0; ) {
491 int level = blk[zag];
492 if (level != 0) {
493 if (level < 0) {
494 len = SSSS(-level);
495 while (run & ~0xf) {
496 huffentry e = acht[0xf0];
497 PUT_BITS(e.val, e.nb, nbb, bb, bc);
498 run -= 16;
499 }
500 huffentry e = acht[(run<<4) | len];
501 PUT_BITS(e.val, e.nb, nbb, bb, bc);
502 PUT_BITS((level-1)&(~(-1<<len)), len, nbb, bb, bc);
503 } else {
504 len = SSSS(level);
505 while (run & ~0xf) {
506 huffentry e = acht[0xf0];
507 PUT_BITS(e.val, e.nb, nbb, bb, bc);
508 run -= 16;
509 }
510 huffentry e = acht[(run<<4) | len];
511 PUT_BITS(e.val, e.nb, nbb, bb, bc);
512 PUT_BITS(level, len, nbb, bb, bc);
513 }
514 run = 0;
515 } else {
516 run++;
517 }
518 }
519
520 if (run > 0) {
521 /* EOB */
522 huffentry e = acht[0];
523 PUT_BITS(e.val, e.nb, nbb, bb, bc);
524 }
525
526 bb_ = bb;
527 nbb_ = nbb;
528 bc_ = bc;
529 }
530
531
532 void JpegEncoder::encode_mcu(u_int mcu, const u_char* frm)
533 {
534 short blk[64];
535 register int stride = w_ << 3;
536
537 u_char mx = mcu % (w_ >> 1);
538 u_char my = mcu / (w_ >> 1);
539
540 /* luminance */
541 const u_char* p = &frm[8*stride*my + 16*mx];
542 fdct(p, stride, blk, lqt_);
543 encode_blk(blk, &lpred_, ldht, laht);
544
545 p += 8;
546 fdct(p, stride, blk, lqt_);
547 encode_blk(blk, &lpred_, ldht, laht);
548
549 /* chrominance */
550 stride >>= 1;
551 int fs = framesize_;
552 p = &frm[fs + 8*stride*my + 8*mx];
553 fdct(p, stride, blk, cqt_);
554 encode_blk(blk, &crpred_, cdht, caht);
555
556 p += (fs>>1);
557 fdct(p, stride, blk, cqt_);
558 encode_blk(blk, &cbpred_, cdht, caht);
559 }
560
561
562 int JpegEncoder::encode(const VideoFrame* vf)
563 {
564 if (!pool_) {
565 printf("WARNING no buffer pool installed for encoder");
566 return 0;
567 }
568 pktbuf* pb = pool_->alloc(vf->ts_, RTP_PT_JPEG);
569 bs_ = &pb->data[HDRSIZE];
570 bc_ = bs_;
571 int fragsize = mtu_ - HDRSIZE;
572
573 bb_ = 0;
574 nbb_ = 0;
575 lpred_ = 0;
576 crpred_ = 0;
577 cbpred_ = 0;
578 u_int offset = 0;
579
580 /* RTP/JPEG header */
581 rtphdr* rh = (rtphdr*)pb->data;
582 u_int* h = (u_int*)(rh+1);
583 h[0] = htonl(offset);
584 h[1] = htonl(quant_ << 16 | w_ << 8 | h_);
585
586 int cc = 0;
587
588 u_int8_t* frm = vf->bp_;
589 for (u_int mcu = 0; mcu < nmcu_; mcu++) {
590 encode_mcu(mcu, frm);
591 int cbytes = bc_ - bs_;
592 if (cbytes > fragsize) {
593 pktbuf* npb = pool_->alloc(vf->ts_, RTP_PT_JPEG);
594 cc += flush(pb, fragsize<<3, npb);
595 offset += fragsize;
596 pb = npb;
597
598 /* RTP/JPEG header */
599 rh = (rtphdr*)pb->data;
600 u_int* h = (u_int*)(rh+1);
601 h[0] = htonl(offset);
602 h[1] = htonl(quant_ << 16 | w_ << 8 | h_);
603 }
604 }
605
606 cc += flush(pb, ((bc_ - bs_)<<3) + nbb_, 0);
607 return (cc);
608 }
609
610
611 /*
612 * fdct() from dct.cc slightly modified to fold in the jpeg 128 bias.
613 */
614 #define FA1 (0.707106781f)
615 #define FA2 (0.541196100f)
616 #define FA3 FA1
617 #define FA4 (1.306562965f)
618 #define FA5 (0.382683433f)
619 #define FWD_DandQ(v, iq) short((v) * qt[iq] + 0.5)
620
621
622 void JpegEncoder::fdct(const u_char* in, int stride, short* out,
623 const float* qt)
624 {
625 float tmp[64];
626 float* tp = tmp;
627
628 int i;
629 for (i = 8; --i >= 0; ) {
630 float x0, x1, x2, x3, t0, t1, t2, t3, t4, t5, t6, t7;
631 t0 = float(in[0] + in[7] - 256);
632 t7 = float(in[0] - in[7]);
633 t1 = float(in[1] + in[6] - 256);
634 t6 = float(in[1] - in[6]);
635 t2 = float(in[2] + in[5] - 256);
636 t5 = float(in[2] - in[5]);
637 t3 = float(in[3] + in[4] - 256);
638 t4 = float(in[3] - in[4]);
639
640 /* even part */
641 x0 = t0 + t3;
642 x2 = t1 + t2;
643 tp[8*0] = x0 + x2;
644 tp[8*4] = x0 - x2;
645
646 x1 = t0 - t3;
647 x3 = t1 - t2;
648 t0 = (x1 + x3) * FA1;
649 tp[8*2] = x1 + t0;
650 tp[8*6] = x1 - t0;
651
652 /* odd part */
653 x0 = t4 + t5;
654 x1 = t5 + t6;
655 x2 = t6 + t7;
656
657 t3 = x1 * FA1;
658 t4 = t7 - t3;
659
660 t0 = (x0 - x2) * FA5;
661 t1 = x0 * FA2 + t0;
662 tp[8*3] = t4 - t1;
663 tp[8*5] = t4 + t1;
664
665 t7 += t3;
666 t2 = x2 * FA4 + t0;
667 tp[8*1] = t7 + t2;
668 tp[8*7] = t7 - t2;
669
670 in += stride;
671 tp += 1;
672 }
673 tp -= 8;
674
675 for (i = 8; --i >= 0; ) {
676 float x0, x1, x2, x3, t0, t1, t2, t3, t4, t5, t6, t7;
677 t0 = tp[0] + tp[7];
678 t7 = tp[0] - tp[7];
679 t1 = tp[1] + tp[6];
680 t6 = tp[1] - tp[6];
681 t2 = tp[2] + tp[5];
682 t5 = tp[2] - tp[5];
683 t3 = tp[3] + tp[4];
684 t4 = tp[3] - tp[4];
685
686 /* even part */
687 x0 = t0 + t3;
688 x2 = t1 + t2;
689 out[0] = FWD_DandQ(x0 + x2, 0);
690 out[4] = FWD_DandQ(x0 - x2, 4);
691
692 x1 = t0 - t3;
693 x3 = t1 - t2;
694 t0 = (x1 + x3) * FA1;
695 out[2] = FWD_DandQ(x1 + t0, 2);
696 out[6] = FWD_DandQ(x1 - t0, 6);
697
698 /* odd part */
699 x0 = t4 + t5;
700 x1 = t5 + t6;
701 x2 = t6 + t7;
702
703 t3 = x1 * FA1;
704 t4 = t7 - t3;
705
706 t0 = (x0 - x2) * FA5;
707 t1 = x0 * FA2 + t0;
708 out[3] = FWD_DandQ(t4 - t1, 3);
709 out[5] = FWD_DandQ(t4 + t1, 5);
710
711 t7 += t3;
712 t2 = x2 * FA4 + t0;
713 out[1] = FWD_DandQ(t7 + t2, 1);
714 out[7] = FWD_DandQ(t7 - t2, 7);
715
716 out += 8;
717 tp += 8;
718 qt += 8;
719 }
720 }
721
722
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.