Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifdef HAVE_NETINET_IN_H
6 #include <netinet/in.h>
7 #elif defined XP_WIN
8 #include <winsock2.h>
9 #endif
10 #include <string.h>
12 #include "nspr.h"
13 #include "YuvStamper.h"
15 typedef uint32_t UINT4; //Needed for r_crc32() call
16 extern "C" {
17 #include "r_crc32.h"
18 }
20 namespace mozilla {
22 #define ON_5 0x20
23 #define ON_4 0x10
24 #define ON_3 0x08
25 #define ON_2 0x04
26 #define ON_1 0x02
27 #define ON_0 0x01
29 /*
30 0, 0, 1, 1, 0, 0,
31 0, 1, 0, 0, 1, 0,
32 1, 0, 0, 0, 0, 1,
33 1, 0, 0, 0, 0, 1,
34 1, 0, 0, 0, 0, 1,
35 0, 1, 0, 0, 1, 0,
36 0, 0, 1, 1, 0, 0
37 */
38 static unsigned char DIGIT_0 [] =
39 { ON_3 | ON_2,
40 ON_4 | ON_1,
41 ON_5 | ON_0,
42 ON_5 | ON_0,
43 ON_5 | ON_0,
44 ON_4 | ON_1,
45 ON_3 | ON_2
46 };
48 /*
49 0, 0, 0, 1, 0, 0,
50 0, 0, 0, 1, 0, 0,
51 0, 0, 0, 1, 0, 0,
52 0, 0, 0, 1, 0, 0,
53 0, 0, 0, 1, 0, 0,
54 0, 0, 0, 1, 0, 0,
55 0, 0, 0, 1, 0, 0,
56 */
57 static unsigned char DIGIT_1 [] =
58 { ON_2,
59 ON_2,
60 ON_2,
61 ON_2,
62 ON_2,
63 ON_2,
64 ON_2
65 };
67 /*
68 1, 1, 1, 1, 1, 0,
69 0, 0, 0, 0, 0, 1,
70 0, 0, 0, 0, 0, 1,
71 0, 1, 1, 1, 1, 0,
72 1, 0, 0, 0, 0, 0,
73 1, 0, 0, 0, 0, 0,
74 0, 1, 1, 1, 1, 1,
75 */
76 static unsigned char DIGIT_2 [] =
77 { ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
78 ON_0,
79 ON_0,
80 ON_4 | ON_3 | ON_2 | ON_1,
81 ON_5,
82 ON_5,
83 ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
84 };
86 /*
87 1, 1, 1, 1, 1, 0,
88 0, 0, 0, 0, 0, 1,
89 0, 0, 0, 0, 0, 1,
90 0, 1, 1, 1, 1, 1,
91 0, 0, 0, 0, 0, 1,
92 0, 0, 0, 0, 0, 1,
93 1, 1, 1, 1, 1, 0,
94 */
95 static unsigned char DIGIT_3 [] =
96 { ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
97 ON_0,
98 ON_0,
99 ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
100 ON_0,
101 ON_0,
102 ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
103 };
105 /*
106 0, 1, 0, 0, 0, 1,
107 0, 1, 0, 0, 0, 1,
108 0, 1, 0, 0, 0, 1,
109 0, 1, 1, 1, 1, 1,
110 0, 0, 0, 0, 0, 1,
111 0, 0, 0, 0, 0, 1,
112 0, 0, 0, 0, 0, 1
113 */
114 static unsigned char DIGIT_4 [] =
115 { ON_4 | ON_0,
116 ON_4 | ON_0,
117 ON_4 | ON_0,
118 ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
119 ON_0,
120 ON_0,
121 ON_0,
122 };
124 /*
125 0, 1, 1, 1, 1, 1,
126 1, 0, 0, 0, 0, 0,
127 1, 0, 0, 0, 0, 0,
128 0, 1, 1, 1, 1, 0,
129 0, 0, 0, 0, 0, 1,
130 0, 0, 0, 0, 0, 1,
131 1, 1, 1, 1, 1, 0,
132 */
133 static unsigned char DIGIT_5 [] =
134 { ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
135 ON_5,
136 ON_5,
137 ON_4 | ON_3 | ON_2 | ON_1,
138 ON_0,
139 ON_0,
140 ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
141 };
143 /*
144 0, 1, 1, 1, 1, 1,
145 1, 0, 0, 0, 0, 0,
146 1, 0, 0, 0, 0, 0,
147 1, 1, 1, 1, 1, 0,
148 1, 0, 0, 0, 0, 1,
149 1, 0, 0, 0, 0, 1,
150 0, 1, 1, 1, 1, 0,
151 */
152 static unsigned char DIGIT_6 [] =
153 { ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
154 ON_5,
155 ON_5,
156 ON_4 | ON_3 | ON_2 | ON_1,
157 ON_5 | ON_0,
158 ON_5 | ON_0,
159 ON_4 | ON_3 | ON_2 | ON_1,
160 };
162 /*
163 1, 1, 1, 1, 1, 1,
164 0, 0, 0, 0, 0, 1,
165 0, 0, 0, 0, 1, 0,
166 0, 0, 0, 1, 0, 0,
167 0, 0, 1, 0, 0, 0,
168 0, 1, 0, 0, 0, 0,
169 1, 0, 0, 0, 0, 0
170 */
171 static unsigned char DIGIT_7 [] =
172 { ON_5 | ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
173 ON_0,
174 ON_1,
175 ON_2,
176 ON_3,
177 ON_4,
178 ON_5
179 };
181 /*
182 0, 1, 1, 1, 1, 1,
183 1, 0, 0, 0, 0, 1,
184 1, 0, 0, 0, 0, 1,
185 0, 1, 1, 1, 1, 0,
186 1, 0, 0, 0, 0, 1,
187 1, 0, 0, 0, 0, 1,
188 0, 1, 1, 1, 1, 0
189 */
190 static unsigned char DIGIT_8 [] =
191 { ON_4 | ON_3 | ON_2 | ON_1,
192 ON_5 | ON_0,
193 ON_5 | ON_0,
194 ON_4 | ON_3 | ON_2 | ON_1,
195 ON_5 | ON_0,
196 ON_5 | ON_0,
197 ON_4 | ON_3 | ON_2 | ON_1,
198 };
200 /*
201 0, 1, 1, 1, 1, 1,
202 1, 0, 0, 0, 0, 1,
203 1, 0, 0, 0, 0, 1,
204 0, 1, 1, 1, 1, 1,
205 0, 0, 0, 0, 0, 1,
206 0, 0, 0, 0, 0, 1,
207 0, 1, 1, 1, 1, 0
208 */
209 static unsigned char DIGIT_9 [] =
210 { ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
211 ON_5 | ON_0,
212 ON_5 | ON_0,
213 ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
214 ON_0,
215 ON_0,
216 ON_4 | ON_3 | ON_2 | ON_1,
217 };
219 static unsigned char *DIGITS[] = {
220 DIGIT_0,
221 DIGIT_1,
222 DIGIT_2,
223 DIGIT_3,
224 DIGIT_4,
225 DIGIT_5,
226 DIGIT_6,
227 DIGIT_7,
228 DIGIT_8,
229 DIGIT_9
230 };
232 YuvStamper::YuvStamper(unsigned char* pYData,
233 uint32_t width,
234 uint32_t height,
235 uint32_t stride,
236 uint32_t x,
237 uint32_t y,
238 unsigned char symbol_width,
239 unsigned char symbol_height):
240 pYData(pYData), mStride(stride),
241 mWidth(width), mHeight(height),
242 mSymbolWidth(symbol_width), mSymbolHeight(symbol_height),
243 mCursor(x, y) {}
245 bool YuvStamper::Encode(uint32_t width, uint32_t height, uint32_t stride,
246 unsigned char* pYData, unsigned char* pMsg, size_t msg_len,
247 uint32_t x, uint32_t y)
248 {
249 YuvStamper stamper(pYData, width, height, stride,
250 x, y, sBitSize, sBitSize);
252 // Reserve space for a checksum.
253 if (stamper.Capacity() < 8 * (msg_len + sizeof(uint32_t)))
254 {
255 return false;
256 }
258 bool ok = false;
259 uint32_t crc;
260 unsigned char* pCrc = reinterpret_cast<unsigned char*>(&crc);
261 r_crc32(reinterpret_cast<char*>(pMsg), (int)msg_len, &crc);
262 crc = htonl(crc);
264 while (msg_len-- > 0) {
265 if (!stamper.Write8(*pMsg++)) {
266 return false;
267 }
268 }
270 // Add checksum after the message.
271 ok = stamper.Write8(*pCrc++) &&
272 stamper.Write8(*pCrc++) &&
273 stamper.Write8(*pCrc++) &&
274 stamper.Write8(*pCrc++);
276 return ok;
277 }
279 bool YuvStamper::Decode(uint32_t width, uint32_t height, uint32_t stride,
280 unsigned char* pYData, unsigned char* pMsg, size_t msg_len,
281 uint32_t x, uint32_t y)
282 {
283 YuvStamper stamper(pYData, width, height, stride,
284 x, y, sBitSize, sBitSize);
286 unsigned char* ptr = pMsg;
287 size_t len = msg_len;
288 uint32_t crc, msg_crc;
289 unsigned char* pCrc = reinterpret_cast<unsigned char*>(&crc);
291 // Account for space reserved for the checksum
292 if (stamper.Capacity() < 8 * (len + sizeof(uint32_t))) {
293 return false;
294 }
296 while (len-- > 0) {
297 if(!stamper.Read8(*ptr++)) {
298 return false;
299 }
300 }
302 if (!(stamper.Read8(*pCrc++) &&
303 stamper.Read8(*pCrc++) &&
304 stamper.Read8(*pCrc++) &&
305 stamper.Read8(*pCrc++))) {
306 return false;
307 }
309 r_crc32(reinterpret_cast<char*>(pMsg), (int)msg_len, &msg_crc);
310 return crc == htonl(msg_crc);
311 }
313 inline uint32_t YuvStamper::Capacity()
314 {
315 // Enforce at least a symbol width and height offset from outer edges.
316 if (mCursor.y + mSymbolHeight > mHeight) {
317 return 0;
318 }
320 if (mCursor.x + mSymbolWidth > mWidth && !AdvanceCursor()) {
321 return 0;
322 }
324 // Normalize frame integral to mSymbolWidth x mSymbolHeight
325 uint32_t width = mWidth / mSymbolWidth;
326 uint32_t height = mHeight / mSymbolHeight;
327 uint32_t x = mCursor.x / mSymbolWidth;
328 uint32_t y = mCursor.y / mSymbolHeight;
330 return (width * height - width * y)- x;
331 }
333 bool YuvStamper::Write8(unsigned char value)
334 {
335 // Encode MSB to LSB.
336 unsigned char mask = 0x80;
337 while (mask) {
338 if (!WriteBit(!!(value & mask))) {
339 return false;
340 }
341 mask >>= 1;
342 }
343 return true;
344 }
346 bool YuvStamper::WriteBit(bool one)
347 {
348 // A bit is mapped to a mSymbolWidth x mSymbolHeight square of luma data points.
349 // Don't use ternary op.: https://bugzilla.mozilla.org/show_bug.cgi?id=1001708
350 unsigned char value;
351 if (one)
352 value = sYOn;
353 else
354 value = sYOff;
356 for (uint32_t y = 0; y < mSymbolHeight; y++) {
357 for (uint32_t x = 0; x < mSymbolWidth; x++) {
358 *(pYData + (mCursor.x + x) + ((mCursor.y + y) * mStride)) = value;
359 }
360 }
362 return AdvanceCursor();
363 }
365 bool YuvStamper::AdvanceCursor()
366 {
367 mCursor.x += mSymbolWidth;
368 if (mCursor.x + mSymbolWidth > mWidth) {
369 // move to the start of the next row if possible.
370 mCursor.y += mSymbolHeight;
371 if (mCursor.y + mSymbolHeight > mHeight) {
372 // end of frame, do not advance
373 mCursor.y -= mSymbolHeight;
374 mCursor.x -= mSymbolWidth;
375 return false;
376 } else {
377 mCursor.x = 0;
378 }
379 }
381 return true;
382 }
384 bool YuvStamper::Read8(unsigned char &value)
385 {
386 unsigned char octet = 0;
387 unsigned char bit = 0;
389 for (int i = 8; i > 0; --i) {
390 if (!ReadBit(bit)) {
391 return false;
392 }
393 octet <<= 1;
394 octet |= bit;
395 }
397 value = octet;
398 return true;
399 }
401 bool YuvStamper::ReadBit(unsigned char &bit)
402 {
403 uint32_t sum = 0;
404 for (uint32_t y = 0; y < mSymbolHeight; y++) {
405 for (uint32_t x = 0; x < mSymbolWidth; x++) {
406 sum += *(pYData + mStride * (mCursor.y + y) + mCursor.x + x);
407 }
408 }
410 // apply threshold to collected bit square
411 bit = (sum > (sBitThreshold * mSymbolWidth * mSymbolHeight)) ? 1 : 0;
412 return AdvanceCursor();
413 }
415 bool YuvStamper::WriteDigits(uint32_t value)
416 {
417 char buf[20];
418 PR_snprintf(buf, sizeof(buf), "%.5u", value);
419 size_t size = strlen(buf);
421 if (Capacity() < size) {
422 return false;
423 }
425 for (size_t i=0; i < size; ++i) {
426 if (!WriteDigit(buf[i] - '0'))
427 return false;
428 if (!AdvanceCursor()) {
429 return false;
430 }
431 }
433 return true;
434 }
436 bool YuvStamper::WriteDigit(unsigned char digit) {
437 if (digit > sizeof(DIGITS)/sizeof(DIGITS[0]))
438 return false;
440 unsigned char *dig = DIGITS[digit];
441 for (uint32_t row = 0; row < sDigitHeight; ++row) {
442 unsigned char mask = 0x01 << (sDigitWidth - 1);
443 for (uint32_t col = 0; col < sDigitWidth; ++col, mask >>= 1) {
444 if (dig[row] & mask) {
445 for (uint32_t xx=0; xx < sPixelSize; ++xx) {
446 for (uint32_t yy=0; yy < sPixelSize; ++yy) {
447 WritePixel(pYData,
448 mCursor.x + (col * sPixelSize) + xx,
449 mCursor.y + (row * sPixelSize) + yy);
450 }
451 }
452 }
453 }
454 }
456 return true;
457 }
459 void YuvStamper::WritePixel(unsigned char *data, uint32_t x, uint32_t y) {
460 unsigned char *ptr = &data[y * mStride + x];
461 // Don't use ternary op.: https://bugzilla.mozilla.org/show_bug.cgi?id=1001708
462 if (*ptr > sLumaThreshold)
463 *ptr = sLumaMin;
464 else
465 *ptr = sLumaMax;
466 }
468 } // Namespace mozilla.