diff options
| -rw-r--r-- | CMakeLists.txt | 5 | ||||
| -rw-r--r-- | aspeed_purley.cmake | 32 | ||||
| -rw-r--r-- | include/ast_video_puller.hpp | 179 | ||||
| -rw-r--r-- | include/web_kvm.hpp | 2 | ||||
| -rw-r--r-- | src/ast_video_puller_test.cpp | 49 | ||||
| -rw-r--r-- | src/getvideo_main.cpp | 2 |
6 files changed, 208 insertions, 61 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e9b3e75..501c2c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,9 +94,10 @@ add_definitions(-DBOOST_ALL_NO_LIB) set(Boost_USE_STATIC_LIBS ON) hunter_add_package(Boost) find_package(Boost) +include_directories(${Boost_INCLUDE_DIRS}) #Openssl -hunter_add_package(OpenSSL) +#hunter_add_package(OpenSSL) find_package(OpenSSL REQUIRED) #g3 logging @@ -200,7 +201,7 @@ set(UT_FILES src/test_utils.cpp src/msan_test.cpp src/ci_map_tests.cpp - + src/ast_video_puller_test.cpp ${CMAKE_BINARY_DIR}/generated/blns.hpp ) diff --git a/aspeed_purley.cmake b/aspeed_purley.cmake new file mode 100644 index 0000000..2c48ed2 --- /dev/null +++ b/aspeed_purley.cmake @@ -0,0 +1,32 @@ +# this one is important +SET(CMAKE_SYSTEM_NAME Linux) +#this one not so much +SET(CMAKE_SYSTEM_VERSION 1) +SET(CMAKE_SYSTEM_PROCESSOR "armv6") +set(ARCH "armv6") + +SET(CMAKE_CROSSCOMPILING True) + +# specify the cross compiler +#SET(CMAKE_C_COMPILER arm-linux-gnueabi-gcc-4.9) +#SET(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-4.9) +#SET(CMAKE_C_LINK_EXECUTABLE "clang <OBJECTS> -o <TARGET> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>") +#SET(CMAKE_CXX_LINK_EXECUTABLE "clang++ <OBJECTS> -o <TARGET> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>") + +set(CMAKE_C_COMPILER /home/ed/deg-bmcfw-core/ToolChain/Host/AST2500/x-tools/arm-aspeed-linux-gnueabi/bin/arm-linux-gcc) +set(CMAKE_CXX_COMPILER /home/ed/deg-bmcfw-core/ToolChain/Host/AST2500/x-tools/arm-aspeed-linux-gnueabi/bin/arm-linux-g++) + + +set(triple arm-linux-gnueabi) +set(CMAKE_C_COMPILER_TARGET ${triple}) +set(CMAKE_CXX_COMPILER_TARGET ${triple}) + +# where is the target environment +SET(CMAKE_FIND_ROOT_PATH /home/ed/deg-bmcfw-core/_sysroot/AST2500) + +# search for programs in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/include/ast_video_puller.hpp b/include/ast_video_puller.hpp index 214e2df..fd29ca5 100644 --- a/include/ast_video_puller.hpp +++ b/include/ast_video_puller.hpp @@ -2,73 +2,76 @@ #include <assert.h> #include <ast_video_types.hpp> +#include <g3log/g3log.hpp> #include <iostream> +#include <mutex> #include <vector> +#include <boost/asio.hpp> namespace AstVideo { -class VideoPuller { - // - // Cursor struct is used in User Mode - // - typedef struct _cursor_attribution_tag { - unsigned int posX; - unsigned int posY; - unsigned int cur_width; - unsigned int cur_height; - unsigned int cur_type; // 0:mono 1:color 2:disappear cursor - unsigned int cur_change_flag; - } AST_CUR_ATTRIBUTION_TAG; - - // - // For storing Cursor Information - // - typedef struct _cursor_tag { - AST_CUR_ATTRIBUTION_TAG attr; - // unsigned char icon[MAX_CUR_OFFSETX*MAX_CUR_OFFSETY*2]; - unsigned char *icon; //[64*64*2]; - } AST_CURSOR_TAG; - - // - // For select image format, i.e. 422 JPG420, 444 JPG444, lumin/chrom table, 0 - // ~ 11, low to high - // - typedef struct _video_features { - short jpg_fmt; // 422:JPG420, 444:JPG444 - short lumin_tbl; - short chrom_tbl; - short tolerance_noise; - int w; - int h; - unsigned char *buf; - } FEATURES_TAG; - - // - // For configure video engine control registers - // - typedef struct _image_info { - short do_image_refresh; // Action 0:motion 1:fullframe 2:quick cursor - char qc_valid; // quick cursor enable/disable - unsigned int len; - int crypttype; - char cryptkey[16]; - union { - FEATURES_TAG features; - AST_CURSOR_TAG cursor_info; - } parameter; - } IMAGE_INFO; +// +// Cursor struct is used in User Mode +// +typedef struct _cursor_attribution_tag { + unsigned int posX; + unsigned int posY; + unsigned int cur_width; + unsigned int cur_height; + unsigned int cur_type; // 0:mono 1:color 2:disappear cursor + unsigned int cur_change_flag; +} AST_CUR_ATTRIBUTION_TAG; + +// +// For storing Cursor Information +// +typedef struct _cursor_tag { + AST_CUR_ATTRIBUTION_TAG attr; + // unsigned char icon[MAX_CUR_OFFSETX*MAX_CUR_OFFSETY*2]; + unsigned char *icon; //[64*64*2]; +} AST_CURSOR_TAG; + +// +// For select image format, i.e. 422 JPG420, 444 JPG444, lumin/chrom table, 0 +// ~ 11, low to high +// +typedef struct _video_features { + short jpg_fmt; // 422:JPG420, 444:JPG444 + short lumin_tbl; + short chrom_tbl; + short tolerance_noise; + int w; + int h; + unsigned char *buf; +} FEATURES_TAG; + +// +// For configure video engine control registers +// +typedef struct _image_info { + short do_image_refresh; // Action 0:motion 1:fullframe 2:quick cursor + char qc_valid; // quick cursor enable/disable + unsigned int len; + int crypttype; + char cryptkey[16]; + union { + FEATURES_TAG features; + AST_CURSOR_TAG cursor_info; + } parameter; +} IMAGE_INFO; + +class SimpleVideoPuller { public: - VideoPuller() : image_info(){}; + SimpleVideoPuller() : image_info(){}; 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"; - // TODO(Ed) throw exception? - } else { - std::cout << "Opened successfully\n"; + throw std::runtime_error("Failed to open /dev/video"); } + std::cout << "Opened successfully\n"; } RawVideoBuffer read_video() { @@ -93,13 +96,13 @@ class VideoPuller { std::cout << "Write done\n"; */ - std::cout << "Reading\n"; + LOG(DEBUG) << "Reading\n"; status = read(video_fd, reinterpret_cast<char *>(&image_info), sizeof(image_info)); - std::cout << "Reading\n"; + LOG(DEBUG) << "Done reading\n"; if (status != 0) { - std::cout << "Read failed with status " << status << "\n"; + LOG(WARNING) << "Read failed with status " << status << "\n"; } raw.buffer.resize(image_info.len); @@ -118,4 +121,66 @@ class VideoPuller { int video_fd; IMAGE_INFO image_info; }; + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +class AsyncVideoPuller { + public: + typedef std::function<void(RawVideoBuffer &)> video_callback; + + AsyncVideoPuller(boost::asio::io_service &io_service) + : image_info(), dev_video(io_service, open("/dev/video", O_RDWR)) { + videobuf = std::make_shared<RawVideoBuffer>(); + + image_info.do_image_refresh = 1; // full frame refresh + image_info.qc_valid = 0; // quick cursor disabled + image_info.parameter.features.buf = + reinterpret_cast<unsigned char *>(videobuf->buffer.data()); + image_info.crypttype = -1; + }; + + void register_callback(video_callback &callback) { + std::lock_guard<std::mutex> lock(callback_mutex); + callbacks.push_back(callback); + start_read(); + } + + void start_read() { + auto mutable_buffer = boost::asio::buffer(&image_info, sizeof(image_info)); + boost::asio::async_read( + dev_video, mutable_buffer, [this](const boost::system::error_code &ec, + std::size_t bytes_transferred) { + if (ec) { + LOG(WARNING) << "Read failed with status " << ec << "\n"; + } else { + this->read_done(); + } + }); + } + + void read_done() { + LOG(DEBUG) << "Done reading\n"; + videobuf->buffer.resize(image_info.len); + + videobuf->height = image_info.parameter.features.h; + videobuf->width = image_info.parameter.features.w; + if (image_info.parameter.features.jpg_fmt == 422) { + videobuf->mode = YuvMode::YUV420; + } else { + videobuf->mode = YuvMode::YUV444; + } + std::lock_guard<std::mutex> lock(callback_mutex); + for (auto &callback : callbacks) { + // TODO(ed) call callbacks async and double buffer frames + callback(*videobuf); + } + } + + private: + std::shared_ptr<RawVideoBuffer> videobuf; + boost::asio::posix::stream_descriptor dev_video; + IMAGE_INFO image_info; + std::mutex callback_mutex; + std::vector<video_callback> callbacks; +}; +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) } diff --git a/include/web_kvm.hpp b/include/web_kvm.hpp index 10291ca..1671382 100644 --- a/include/web_kvm.hpp +++ b/include/web_kvm.hpp @@ -282,7 +282,7 @@ void request_routes(Crow<Middlewares...>& app) { // Todo(ed) lifecycle of the video puller and decoder // should be // with the websocket, not recreated every time - AstVideo::VideoPuller p; + AstVideo::SimpleVideoPuller p; p.initialize(); auto out = p.read_video(); AstVideo::AstJpegDecoder d; diff --git a/src/ast_video_puller_test.cpp b/src/ast_video_puller_test.cpp new file mode 100644 index 0000000..ef1cbe3 --- /dev/null +++ b/src/ast_video_puller_test.cpp @@ -0,0 +1,49 @@ +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <ast_jpeg_decoder.hpp> +#include <ast_video_puller.hpp> +#include <chrono> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <thread> +#include <vector> +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +TEST(AstvideoPuller, BasicRead) { + std::cout << "Started\n"; + AstVideo::RawVideoBuffer out; + bool have_hardware = false; + if (access("/dev/video", F_OK) != -1) { + AstVideo::SimpleVideoPuller p; + p.initialize(); + out = p.read_video(); + } else { + FILE *fp = fopen("test_resources/ubuntu_444_800x600_0chrom_0lum.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); +} diff --git a/src/getvideo_main.cpp b/src/getvideo_main.cpp index 8c92bd3..33885ee 100644 --- a/src/getvideo_main.cpp +++ b/src/getvideo_main.cpp @@ -24,7 +24,7 @@ int main() { AstVideo::RawVideoBuffer out; bool have_hardware = false; if (access("/dev/video", F_OK) != -1) { - AstVideo::VideoPuller p; + AstVideo::SimpleVideoPuller p; p.initialize(); out = p.read_video(); } else { |

