media/webrtc/signaling/src/common/YuvStamper.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial