KVM WORKING! ! !
diff --git a/src/ast_jpeg_decoder_test.cpp b/src/ast_jpeg_decoder_test.cpp
new file mode 100644
index 0000000..bc6857e
--- /dev/null
+++ b/src/ast_jpeg_decoder_test.cpp
@@ -0,0 +1,156 @@
+#include "ast_jpeg_decoder.hpp"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+#ifdef BUILD_CIMG
+#define cimg_display 0
+#include <CImg.h>
+#endif
+
+using namespace testing;
+MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") +
+ " between " + PrintToString(a) + " and " +
+ PrintToString(b)) {
+ return a <= arg && arg <= b;
+};
+
+TEST(AstJpegDecoder, AllBlue) {
+ AstVideo::RawVideoBuffer out;
+
+ // This binary blog was created on the aspeed hardware using a blue screen
+ // consisting of the color 0x8EFFFA in a web browser window
+ FILE *fp = fopen("test_resources/aspeedbluescreen.bin", "rb");
+ EXPECT_NE(fp, nullptr);
+ size_t bufferlen = fread(out.buffer.data(), sizeof(char),
+ out.buffer.size() * sizeof(long), fp);
+ fclose(fp);
+
+ ASSERT_GT(bufferlen, 0);
+
+ out.y_selector = 0;
+ out.uv_selector = 0;
+ out.mode = AstVideo::YuvMode::YUV444;
+ out.width = 800;
+ out.height = 600;
+
+ AstVideo::AstJpegDecoder d;
+ d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector,
+ out.uv_selector);
+
+ int tolerance = 16;
+
+ // All pixels should be blue (0x8EFFFA) to within a tolerance (due to jpeg
+ // compression artifacts and quanitization)
+ for (int i = 0; i < out.width * out.height; i++) {
+ AstVideo::RGB &pixel = d.OutBuffer[i];
+ EXPECT_GT(pixel.R, 0x8E - tolerance);
+ EXPECT_LT(pixel.R, 0x8E + tolerance);
+ EXPECT_GT(pixel.G, 0xFF - tolerance);
+ EXPECT_LT(pixel.G, 0xFF + tolerance);
+ EXPECT_GT(pixel.B, 0xF1 - tolerance);
+ EXPECT_LT(pixel.B, 0xF1 + tolerance);
+ }
+}
+
+TEST(AstJpegDecoder, AllBlack) {
+ AstVideo::RawVideoBuffer out;
+
+ // This binary blog was created on the aspeed hardware using a black screen
+ FILE *fp = fopen("test_resources/aspeedblackscreen.bin", "rb");
+ EXPECT_NE(fp, nullptr);
+ size_t bufferlen = fread(out.buffer.data(), sizeof(char),
+ out.buffer.size() * sizeof(long), fp);
+ fclose(fp);
+
+ ASSERT_GT(bufferlen, 0);
+
+ out.y_selector = 0;
+ out.uv_selector = 0;
+ out.mode = AstVideo::YuvMode::YUV444;
+ out.width = 800;
+ out.height = 600;
+
+ AstVideo::AstJpegDecoder d;
+ d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector,
+ out.uv_selector);
+
+ // All pixels should be blue (0x8EFFFA) to within a tolerance (due to jpeg
+ // compression artifacts and quanitization)
+ for (int x = 0; x < out.width; x++) {
+ for (int y = 0; y < out.height; y++) {
+ AstVideo::RGB pixel = d.OutBuffer[x + (y * out.width)];
+ ASSERT_EQ(pixel.R, 0x00) << "X:" << x << " Y: " << y;
+ ASSERT_EQ(pixel.G, 0x00) << "X:" << x << " Y: " << y;
+ ASSERT_EQ(pixel.B, 0x00) << "X:" << x << " Y: " << y;
+ }
+ }
+}
+
+TEST(AstJpegDecoder, TestColors) {
+ AstVideo::RawVideoBuffer out;
+
+ // This binary blog was created on the aspeed hardware using a blue screen
+ // consisting of the color 0x8EFFFA in a web browser window
+ FILE *fp = fopen("test_resources/ubuntu_444_800x600_0chrom_0lum.bin", "rb");
+ EXPECT_NE(fp, nullptr);
+ size_t bufferlen = fread(out.buffer.data(), sizeof(char),
+ out.buffer.size() * sizeof(long), fp);
+ fclose(fp);
+
+ ASSERT_GT(bufferlen, 0);
+
+ out.y_selector = 0;
+ out.uv_selector = 0;
+ out.mode = AstVideo::YuvMode::YUV444;
+ out.width = 800;
+ out.height = 600;
+
+ AstVideo::AstJpegDecoder d;
+ d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector,
+ out.uv_selector);
+
+ int tolerance = 16;
+
+ for (int i = 0; i < out.width * out.height; i++) {
+ AstVideo::RGB &pixel = d.OutBuffer[i];
+ EXPECT_GT(pixel.R, 0x8E - tolerance);
+ EXPECT_LT(pixel.R, 0x8E + tolerance);
+ EXPECT_GT(pixel.G, 0xFF - tolerance);
+ EXPECT_LT(pixel.G, 0xFF + tolerance);
+ EXPECT_GT(pixel.B, 0xF1 - tolerance);
+ EXPECT_LT(pixel.B, 0xF1 + tolerance);
+ }
+}
+// Tests the buffers around the screen aren't written to
+TEST(AstJpegDecoder, BufferLimits) {
+ AstVideo::RawVideoBuffer out;
+
+ // This binary blog was created on the aspeed hardware using a black screen
+ FILE *fp = fopen("test_resources/aspeedblackscreen.bin", "rb");
+ EXPECT_NE(fp, nullptr);
+ size_t bufferlen = fread(out.buffer.data(), sizeof(char),
+ out.buffer.size() * sizeof(long), fp);
+ fclose(fp);
+
+ ASSERT_GT(bufferlen, 0);
+
+ out.y_selector = 0;
+ out.uv_selector = 0;
+ out.mode = AstVideo::YuvMode::YUV444;
+ out.width = 800;
+ out.height = 600;
+
+ AstVideo::AstJpegDecoder d;
+ d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector,
+ out.uv_selector);
+ // Reserved pixel should be default value
+ for (auto &pixel : d.OutBuffer) {
+ EXPECT_EQ(pixel.Reserved, 0xAA);
+ }
+ // All pixels beyond the buffer should be zero
+ for (int i = out.width * out.height; i < d.OutBuffer.size(); i++) {
+ EXPECT_EQ(d.OutBuffer[i].R, 0x00) << "index:" << i;
+ EXPECT_EQ(d.OutBuffer[i].B, 0x00) << "index:" << i;
+ EXPECT_EQ(d.OutBuffer[i].G, 0x00) << "index:" << i;
+ }
+}
\ No newline at end of file
diff --git a/src/getvideo_main.cpp b/src/getvideo_main.cpp
index 50889c9..4f375ca 100644
--- a/src/getvideo_main.cpp
+++ b/src/getvideo_main.cpp
@@ -9,120 +9,68 @@
#include <fcntl.h>
#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define BUILD_CIMG
+#ifdef BUILD_CIMG
+#define cimg_display 0
+#include <CImg.h>
+#endif
-namespace AstVideo {
-class VideoPuller {
- public:
- VideoPuller() {}
-
- void initialize() {
- std::cout << "Opening /dev/video\n";
- video_fd = open("/dev/video", O_RDWR);
- if (!video_fd) {
- std::cout << "Failed to open /dev/video\n";
- } else {
- std::cout << "Opened successfully\n";
- }
-
- std::vector<unsigned char> buffer(1024 * 1024, 0);
-
- IMAGE_INFO image_info{};
- image_info.do_image_refresh = 1; // full frame refresh
- image_info.qc_valid = 0; // quick cursor disabled
- image_info.parameter.features.w = 800;
- image_info.parameter.features.h = 600;
- image_info.parameter.features.chrom_tbl = 0; // level
- image_info.parameter.features.lumin_tbl = 0;
- image_info.parameter.features.jpg_fmt = 1;
- image_info.parameter.features.buf = buffer.data();
- image_info.crypttype = -1;
- std::cout << "Writing\n";
-
- int status;
-
- status = write(video_fd, reinterpret_cast<char*>(&image_info),
- sizeof(image_info));
- if (status != 0) {
- std::cout << "Write failed. Return: " << status <<"\n";
- perror("perror output:");
- }
-
- std::cout << "Write done\n";
- //std::this_thread::sleep_for(std::chrono::milliseconds(2000));
-
- std::cout << "Reading\n";
- status = read(video_fd, reinterpret_cast<char*>(&image_info), sizeof(image_info));
- std::cout << "Reading\n";
-
- if (status != 0) {
- std::cout << "Read failed with status " << status << "\n";
- }
-
- auto pt = reinterpret_cast<char*>(&image_info);
-
- for (int i = 0; i < sizeof(image_info); i++) {
- std::cout << std::hex << std::setfill('0') << std::setw(2)
- << int(*(pt + i)) << " ";
- }
-
- std::cout << "\nprinting buffer\n";
-
- for(int i = 0; i < 512; i++){
- if (i % 16 == 0){
- std::cout << "\n";
- }
- std::cout << std::hex << std::setfill('0') << std::setw(2)
- << int(buffer[i]) << " ";
- }
-
- buffer.resize(image_info.len);
-
- std::ofstream f("/tmp/screen.jpg",std::ios::out | std::ios::binary);
-
- f.write(reinterpret_cast<char*>(buffer.data()), buffer.size());
-
- std::cout << "\n";
-
- std::cout << "typedef struct _video_features {\n";
- std::cout << "short jpg_fmt: " << image_info.parameter.features.jpg_fmt
- << "\n";
- std::cout << "short lumin_tbl;" << image_info.parameter.features.lumin_tbl
- << "\n";
- std::cout << "short chrom_tbl;" << image_info.parameter.features.chrom_tbl
- << "\n";
- std::cout << "short tolerance_noise;"
- << image_info.parameter.features.tolerance_noise << "\n";
- std::cout << "int w; 0X" << image_info.parameter.features.w << "\n";
- std::cout << "int h; 0X" << image_info.parameter.features.h << "\n";
-
- std::cout << "void* buf; 0X" << static_cast<void*>(image_info.parameter.features.buf) << "\n";
- // std::cout << "unsigned char *buf;" << image_info.parameter.features.buf
- // << "\n";
- std::cout << "} FEATURES_TAG;\n";
-
- std::cout << "typedef struct _image_info {";
- std::cout << "short do_image_refresh;" << image_info.do_image_refresh
- << "\n";
- std::cout << "char qc_valid;" << image_info.qc_valid << "\n";
- std::cout << "unsigned int len;" << image_info.len << "\n";
- std::cout << "int crypttype;" << image_info.crypttype << "\n";
- std::cout << "char cryptkey[16];" << image_info.cryptkey << "\n";
- std::cout << "union {\n";
- std::cout << " FEATURES_TAG features;\n";
- std::cout << " AST_CURSOR_TAG cursor_info;\n";
- std::cout << "} parameter;\n";
- std::cout << "} IMAGE_INFO;\n";
- std::cout << std::endl;
-
- close(video_fd);
- }
- int video_fd;
-};
-}
+#include <ast_jpeg_decoder.hpp>
+#include <ast_video_puller.hpp>
int main() {
- AstVideo::VideoPuller p;
- p.initialize();
+ std::cout << "Started\n";
+ AstVideo::RawVideoBuffer out;
+ bool have_hardware = false;
+ if( access( "/dev/video", F_OK ) != -1 ) {
+ AstVideo::VideoPuller p;
+ p.initialize();
+ out = p.read_video();
+ } else {
+ FILE *fp = fopen("/home/ed/screendata.bin", "rb");
+ if (fp) {
+ size_t newLen = fread(out.buffer.data(), sizeof(char),
+ out.buffer.size() * sizeof(long), fp);
+ if (ferror(fp) != 0) {
+ fputs("Error reading file", stderr);
+ }
+ fclose(fp);
+ out.buffer.resize(newLen);
+ out.mode = AstVideo::YuvMode::YUV444;
+ out.width = 800;
+ out.height = 600;
+ out.y_selector = 0;
+ out.uv_selector = 0;
+
+ }
+ }
+
+ FILE *fp = fopen("/tmp/screendata.bin", "wb");
+ fwrite(out.buffer.data(), sizeof(char),
+ out.buffer.size(), fp);
+
+ AstVideo::AstJpegDecoder d;
+ std::cout << "MODE " << static_cast<int>(out.mode);
+ d.decode(out.buffer, out.width, out.height, out.mode, out.y_selector,
+ out.uv_selector);
+ #ifdef BUILD_CIMG
+ cimg_library::CImg<unsigned char> image(out.width, out.height, 1,
+ 3 /*numchannels*/);
+ for (int y = 0; y < out.height; y++) {
+ for (int x = 0; x < out.width; x++) {
+ auto pixel = d.OutBuffer[x + (y * out.width)];
+ image(x, y, 0) = pixel.R;
+ image(x, y, 1) = pixel.G;
+ image(x, y, 2) = pixel.B;
+ }
+ }
+ image.save("/tmp/file2.bmp");
+ #endif
+
+ std::cout << "Done!\n";
+
return 1;
-}
\ No newline at end of file
+}
diff --git a/src/test_resources/aspeedblackscreen.bin b/src/test_resources/aspeedblackscreen.bin
new file mode 100644
index 0000000..537216d
--- /dev/null
+++ b/src/test_resources/aspeedblackscreen.bin
Binary files differ
diff --git a/src/test_resources/aspeedbluescreen.bin b/src/test_resources/aspeedbluescreen.bin
new file mode 100644
index 0000000..829c674
--- /dev/null
+++ b/src/test_resources/aspeedbluescreen.bin
Binary files differ
diff --git a/src/test_resources/ubuntu_444_800x600_0chrom_0lum.bin b/src/test_resources/ubuntu_444_800x600_0chrom_0lum.bin
new file mode 100644
index 0000000..929540c
--- /dev/null
+++ b/src/test_resources/ubuntu_444_800x600_0chrom_0lum.bin
Binary files differ
diff --git a/src/token_authorization_middleware.cpp b/src/token_authorization_middleware.cpp
index a5ecd2d..82a5bde 100644
--- a/src/token_authorization_middleware.cpp
+++ b/src/token_authorization_middleware.cpp
@@ -65,7 +65,9 @@
std::random_device rand;
random_bytes_engine rbe;
std::string token('a', 20);
- std::generate(begin(token), end(token), std::ref(rbe));
+ // TODO(ed) for some reason clang-tidy finds a divide by zero error in cstdlibc here
+ // commented out for now. Needs investigation
+ std::generate(begin(token), end(token), std::ref(rbe)); // NOLINT
std::string encoded_token;
base64::base64_encode(token, encoded_token);
ctx.auth_token = encoded_token;