summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/libjingle/source/talk/media/base/yuvframegenerator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/libjingle/source/talk/media/base/yuvframegenerator.cc')
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/yuvframegenerator.cc262
1 files changed, 262 insertions, 0 deletions
diff --git a/chromium/third_party/libjingle/source/talk/media/base/yuvframegenerator.cc b/chromium/third_party/libjingle/source/talk/media/base/yuvframegenerator.cc
new file mode 100644
index 00000000000..57b5314361a
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/media/base/yuvframegenerator.cc
@@ -0,0 +1,262 @@
+#include "talk/media/base/yuvframegenerator.h"
+
+#include <string.h>
+#include <sstream>
+
+#include "talk/base/basictypes.h"
+#include "talk/base/common.h"
+
+namespace cricket {
+
+// These values were figured out by trial and error. If you change any
+// basic parameters e.g. unit-bar size or bars-x-offset, you may need to change
+// background-width/background-height.
+const int kBarcodeBackgroundWidth = 160;
+const int kBarcodeBackgroundHeight = 100;
+const int kBarsXOffset = 12;
+const int kBarsYOffset = 4;
+const int kUnitBarSize = 2;
+const int kBarcodeNormalBarHeight = 80;
+const int kBarcodeGuardBarHeight = 96;
+const int kBarcodeMaxEncodableDigits = 7;
+
+YuvFrameGenerator::YuvFrameGenerator(int width, int height,
+ bool enable_barcode) {
+ width_ = width;
+ height_ = height;
+ frame_index_ = 0;
+ int size = width_ * height_;
+ int qsize = size / 4;
+ frame_data_size_ = size + 2 * qsize;
+ y_data_ = new uint8[size];
+ u_data_ = new uint8[qsize];
+ v_data_ = new uint8[qsize];
+ if (enable_barcode) {
+ ASSERT(width_ >= kBarcodeBackgroundWidth);
+ ASSERT(height_>= kBarcodeBackgroundHeight);
+ barcode_start_x_ = 0;
+ barcode_start_y_ = height_ - kBarcodeBackgroundHeight;
+ } else {
+ barcode_start_x_ = -1;
+ barcode_start_y_ = -1;
+ }
+}
+
+YuvFrameGenerator::~YuvFrameGenerator() {
+ delete y_data_;
+ delete u_data_;
+ delete v_data_;
+}
+
+void YuvFrameGenerator::GenerateNextFrame(uint8* frame_buffer,
+ int32 barcode_value) {
+ int size = width_ * height_;
+ int qsize = size / 4;
+ memset(y_data_, 0, size);
+ memset(u_data_, 0, qsize);
+ memset(v_data_, 0, qsize);
+
+ DrawLandscape(y_data_, width_, height_);
+ DrawGradientX(u_data_, width_/2, height_/2);
+ DrawGradientY(v_data_, width_/2, height_/2);
+ DrawMovingLineX(u_data_, width_/2, height_/2, frame_index_);
+ DrawMovingLineY(v_data_, width_/2, height_/2, frame_index_);
+ DrawBouncingCube(y_data_, width_, height_, frame_index_);
+
+ if (barcode_value >= 0) {
+ ASSERT(barcode_start_x_ != -1);
+ DrawBarcode(barcode_value);
+ }
+
+ memcpy(frame_buffer, y_data_, size);
+ frame_buffer += size;
+ memcpy(frame_buffer, u_data_, qsize);
+ frame_buffer += qsize;
+ memcpy(frame_buffer, v_data_, qsize);
+
+ frame_index_ = (frame_index_ + 1) & 0x0000FFFF;
+}
+
+void YuvFrameGenerator::DrawLandscape(uint8 *p, int w, int h) {
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ p[x + y * w] = x % (y+1);
+ if (((x > w / 2 - (w / 32)) && (x < w / 2 + (w / 32))) ||
+ ((y > h / 2 - (h / 32)) && (y < h / 2 + (h / 32)))) {
+ p[x + y * w] = (((x + y) / 8 % 2)) ? 255 : 0;
+ }
+ }
+ }
+}
+
+void YuvFrameGenerator::DrawGradientX(uint8 *p, int w, int h) {
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ p[x + y * w] = (x << 8) / w;
+ }
+ }
+}
+
+void YuvFrameGenerator::DrawGradientY(uint8 *p, int w, int h) {
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ p[x + y * w] = (y << 8) / h;
+ }
+ }
+}
+
+void YuvFrameGenerator::DrawMovingLineX(uint8 *p, int w, int h, int n) {
+ int x, y;
+ x = n % (w * 2);
+ if (x >= w) x = w + w - x - 1;
+ for (y = 0; y < h; y++) {
+ p[x + y * w] = 255;
+ }
+}
+
+void YuvFrameGenerator::DrawMovingLineY(uint8 *p, int w, int h, int n) {
+ int x, y;
+ y = n % (h * 2);
+ if (y >= h) y = h + h - y - 1;
+ for (x = 0; x < w; x++) {
+ p[x + y * w] = 255;
+ }
+}
+
+void YuvFrameGenerator::DrawBouncingCube(uint8 *p, int w, int h, int n) {
+ int x, y, pw, ph, px, py;
+ pw = w / 16;
+ ph = h / 16;
+ px = n % (w * 2);
+ py = n % (h * 2);
+ if (px >= w) px = w + w - px - 1;
+ if (py >= h) py = h + h - py - 1;
+ for (y = py - ph; y < py + ph; y++) {
+ if (y >=0 && y < h) {
+ for (x = px - pw; x < px + pw; x++) {
+ if (x >= 0 && x < w) {
+ p[x + y * w] = 255;
+ }
+ }
+ }
+ }
+}
+
+void YuvFrameGenerator::GetBarcodeBounds(int* top, int* left,
+ int* width, int* height) {
+ ASSERT(barcode_start_x_ != -1);
+ *top = barcode_start_y_;
+ *left = barcode_start_x_;
+ *width = kBarcodeBackgroundWidth;
+ *height = kBarcodeBackgroundHeight;
+}
+
+static void ComputeBarcodeDigits(uint32 value, std::stringstream* result) {
+ // Serialize |value| as 7-char string, padded with 0's to the left.
+ result->width(kBarcodeMaxEncodableDigits);
+ result->fill('0');
+ *result << value;
+
+ // Compute check-digit and append to result. Steps described here:
+ // http://en.wikipedia.org/wiki/European_Article_Number#Calculation_of_checksum_digit
+ int sum = 0;
+ for (int pos = 1; pos <= kBarcodeMaxEncodableDigits; pos++) {
+ char next_char;
+ result->get(next_char);
+ uint8 digit = next_char - '0';
+ sum += digit * (pos % 2 ? 3 : 1);
+ }
+ uint8 check_digit = sum % 10;
+ if (check_digit != 0) {
+ check_digit = 10 - check_digit;
+ }
+
+ *result << static_cast<int>(check_digit);
+ result->seekg(0);
+}
+
+void YuvFrameGenerator::DrawBarcode(uint32 value) {
+ std::stringstream value_str_stream;
+ ComputeBarcodeDigits(value, &value_str_stream);
+
+ // Draw white filled rectangle as background to barcode.
+ DrawBlockRectangle(y_data_, barcode_start_x_, barcode_start_y_,
+ kBarcodeBackgroundWidth, kBarcodeBackgroundHeight,
+ width_, 255);
+ DrawBlockRectangle(u_data_, barcode_start_x_ / 2, barcode_start_y_ / 2,
+ kBarcodeBackgroundWidth / 2, kBarcodeBackgroundHeight / 2,
+ width_ / 2, 128);
+ DrawBlockRectangle(v_data_, barcode_start_x_ / 2, barcode_start_y_ / 2,
+ kBarcodeBackgroundWidth / 2, kBarcodeBackgroundHeight / 2,
+ width_ / 2, 128);
+
+ // Scan through chars (digits) and draw black bars.
+ int x = barcode_start_x_ + kBarsXOffset;
+ int y = barcode_start_y_ + kBarsYOffset;
+ int pos = 0;
+ x = DrawSideGuardBars(x, y, kBarcodeGuardBarHeight);
+ while (true) {
+ char next_char;
+ value_str_stream.get(next_char);
+ if (!value_str_stream.good()) {
+ break;
+ }
+ if (pos++ == 4) {
+ x = DrawMiddleGuardBars(x, y, kBarcodeGuardBarHeight);
+ }
+ uint8 digit = next_char - '0';
+ x = DrawEanEncodedDigit(digit, x, y, kBarcodeNormalBarHeight, pos > 4);
+ }
+ x = DrawSideGuardBars(x, y, kBarcodeGuardBarHeight);
+}
+
+int YuvFrameGenerator::DrawMiddleGuardBars(int x, int y, int height) {
+ x += kUnitBarSize;
+ DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0);
+ x += (kUnitBarSize * 2);
+ DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0);
+ return x + (kUnitBarSize * 2);
+}
+
+int YuvFrameGenerator::DrawSideGuardBars(int x, int y, int height) {
+ DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0);
+ x += (kUnitBarSize * 2);
+ DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0);
+ return x + kUnitBarSize;
+}
+
+// For each digit: 0-9, |kEanEncodings| contains a bit-mask indicating
+// which bars are black (1) and which are blank (0). These are for the L-code
+// only. R-code values are bitwise negation of these. Reference:
+// http://en.wikipedia.org/wiki/European_Article_Number#Binary_encoding_of_data_digits_into_EAN-13_barcode // NOLINT
+const uint8 kEanEncodings[] = { 13, 25, 19, 61, 35, 49, 47, 59, 55, 11 };
+
+int YuvFrameGenerator::DrawEanEncodedDigit(int digit, int x, int y,
+ int height, bool flip) {
+ uint8 ean_encoding = kEanEncodings[digit];
+ if (flip) {
+ ean_encoding = ~ean_encoding;
+ }
+ uint8 mask = 0x40;
+ for (int i = 6; i >= 0; i--, mask >>= 1) {
+ if (ean_encoding & mask) {
+ DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0);
+ }
+ x += kUnitBarSize;
+ }
+ return x;
+}
+
+void YuvFrameGenerator::DrawBlockRectangle(uint8* p,
+ int x_start, int y_start, int width, int height, int pitch, uint8 value) {
+ for (int x = x_start; x < x_start + width; x++) {
+ for (int y = y_start; y < y_start + height; y++) {
+ p[x + y * pitch] = value;
+ }
+ }
+}
+
+} // namespace cricket