blob: c2ccea27c341c1785b39ec3dad9550d7a5b97daf [file] [log] [blame]
Ed Tanous93f987d2017-04-17 17:52:36 -07001#pragma once
2
Ed Tanous1ff48782017-04-18 12:45:08 -07003#include <ast_video_types.hpp>
Ed Tanous55c7b7a2018-05-22 15:27:24 -07004#include <cassert>
Ed Tanous93f987d2017-04-17 17:52:36 -07005#include <iostream>
Ed Tanouse2fc45a2017-04-26 09:19:10 -07006#include <mutex>
Ed Tanous1ff48782017-04-18 12:45:08 -07007#include <vector>
Ed Tanouse2fc45a2017-04-26 09:19:10 -07008#include <boost/asio.hpp>
Ed Tanous93f987d2017-04-17 17:52:36 -07009
Ed Tanous55c7b7a2018-05-22 15:27:24 -070010namespace ast_video {
Ed Tanousd5f39992017-04-18 13:41:22 -070011
Ed Tanouse2fc45a2017-04-26 09:19:10 -070012//
13// Cursor struct is used in User Mode
14//
Ed Tanous55c7b7a2018-05-22 15:27:24 -070015struct AstCurAttributionTag {
Ed Tanouse2fc45a2017-04-26 09:19:10 -070016 unsigned int posX;
17 unsigned int posY;
Ed Tanous55c7b7a2018-05-22 15:27:24 -070018 unsigned int curWidth;
19 unsigned int curHeight;
20 unsigned int curType; // 0:mono 1:color 2:disappear cursor
21 unsigned int curChangeFlag;
Ed Tanous911ac312017-08-15 09:37:42 -070022};
Ed Tanousd5f39992017-04-18 13:41:22 -070023
Ed Tanouse2fc45a2017-04-26 09:19:10 -070024//
25// For storing Cursor Information
26//
Ed Tanous55c7b7a2018-05-22 15:27:24 -070027struct AstCursorTag {
28 AstCurAttributionTag attr;
Ed Tanouse2fc45a2017-04-26 09:19:10 -070029 // unsigned char icon[MAX_CUR_OFFSETX*MAX_CUR_OFFSETY*2];
30 unsigned char *icon; //[64*64*2];
Ed Tanous911ac312017-08-15 09:37:42 -070031};
Ed Tanousd5f39992017-04-18 13:41:22 -070032
Ed Tanouse2fc45a2017-04-26 09:19:10 -070033//
34// For select image format, i.e. 422 JPG420, 444 JPG444, lumin/chrom table, 0
35// ~ 11, low to high
36//
Ed Tanous55c7b7a2018-05-22 15:27:24 -070037struct FeaturesTag {
38 short jpgFmt; // 422:JPG420, 444:JPG444
39 short luminTbl;
40 short chromTbl;
41 short toleranceNoise;
Ed Tanouse2fc45a2017-04-26 09:19:10 -070042 int w;
43 int h;
44 unsigned char *buf;
Ed Tanous911ac312017-08-15 09:37:42 -070045};
Ed Tanousd5f39992017-04-18 13:41:22 -070046
Ed Tanouse2fc45a2017-04-26 09:19:10 -070047//
48// For configure video engine control registers
49//
Ed Tanous55c7b7a2018-05-22 15:27:24 -070050struct ImageInfo {
51 short doImageRefresh; // Action 0:motion 1:fullframe 2:quick cursor
52 char qcValid; // quick cursor enable/disable
Ed Tanouse2fc45a2017-04-26 09:19:10 -070053 unsigned int len;
54 int crypttype;
55 char cryptkey[16];
56 union {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070057 FeaturesTag features;
58 AstCursorTag cursorInfo;
Ed Tanouse2fc45a2017-04-26 09:19:10 -070059 } parameter;
Ed Tanous911ac312017-08-15 09:37:42 -070060};
Ed Tanouse2fc45a2017-04-26 09:19:10 -070061
62class SimpleVideoPuller {
Ed Tanous93f987d2017-04-17 17:52:36 -070063 public:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070064 SimpleVideoPuller() : imageInfo(){};
Ed Tanous93f987d2017-04-17 17:52:36 -070065
66 void initialize() {
67 std::cout << "Opening /dev/video\n";
Ed Tanous55c7b7a2018-05-22 15:27:24 -070068 videoFd = open("/dev/video", O_RDWR);
69 if (videoFd == 0) {
Ed Tanous93f987d2017-04-17 17:52:36 -070070 std::cout << "Failed to open /dev/video\n";
Ed Tanouse2fc45a2017-04-26 09:19:10 -070071 throw std::runtime_error("Failed to open /dev/video");
Ed Tanous93f987d2017-04-17 17:52:36 -070072 }
Ed Tanouse2fc45a2017-04-26 09:19:10 -070073 std::cout << "Opened successfully\n";
Ed Tanous93f987d2017-04-17 17:52:36 -070074 }
75
Ed Tanous55c7b7a2018-05-22 15:27:24 -070076 RawVideoBuffer readVideo() {
77 assert(videoFd != 0);
Ed Tanous93f987d2017-04-17 17:52:36 -070078 RawVideoBuffer raw;
79
Ed Tanous55c7b7a2018-05-22 15:27:24 -070080 imageInfo.doImageRefresh = 1; // full frame refresh
81 imageInfo.qcValid = 0; // quick cursor disabled
82 imageInfo.parameter.features.buf =
Ed Tanous93f987d2017-04-17 17:52:36 -070083 reinterpret_cast<unsigned char *>(raw.buffer.data());
Ed Tanous55c7b7a2018-05-22 15:27:24 -070084 imageInfo.crypttype = -1;
Ed Tanous93f987d2017-04-17 17:52:36 -070085 std::cout << "Writing\n";
86
87 int status;
88 /*
Ed Tanous55c7b7a2018-05-22 15:27:24 -070089 status = write(videoFd, reinterpret_cast<char*>(&imageInfo),
90 sizeof(imageInfo));
91 if (status != sizeof(imageInfo)) {
Ed Tanous93f987d2017-04-17 17:52:36 -070092 std::cout << "Write failed. Return: " << status << "\n";
93 perror("perror output:");
94 }
Ed Tanous1ff48782017-04-18 12:45:08 -070095
Ed Tanous93f987d2017-04-17 17:52:36 -070096 std::cout << "Write done\n";
97 */
Ed Tanous4d92cbf2017-06-22 15:41:02 -070098 std::cout << "Reading\n";
Ed Tanous55c7b7a2018-05-22 15:27:24 -070099 status =
100 read(videoFd, reinterpret_cast<char *>(&imageInfo), sizeof(imageInfo));
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700101 std::cout << "Done reading\n";
Ed Tanous93f987d2017-04-17 17:52:36 -0700102
103 if (status != 0) {
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700104 std::cerr << "Read failed with status " << status << "\n";
Ed Tanous93f987d2017-04-17 17:52:36 -0700105 }
106
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700107 raw.buffer.resize(imageInfo.len);
Ed Tanous93f987d2017-04-17 17:52:36 -0700108
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700109 raw.height = imageInfo.parameter.features.h;
110 raw.width = imageInfo.parameter.features.w;
111 if (imageInfo.parameter.features.jpgFmt == 422) {
Ed Tanous93f987d2017-04-17 17:52:36 -0700112 raw.mode = YuvMode::YUV420;
113 } else {
114 raw.mode = YuvMode::YUV444;
115 }
116 return raw;
117 }
118
119 private:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700120 int videoFd{};
121 ImageInfo imageInfo;
Ed Tanous93f987d2017-04-17 17:52:36 -0700122};
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700123
124#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
125class AsyncVideoPuller {
126 public:
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700127 using video_callback = std::function<void(RawVideoBuffer &)>;
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700128
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700129 explicit AsyncVideoPuller(boost::asio::io_service &ioService)
130 : imageInfo(), devVideo(ioService, open("/dev/video", O_RDWR)) {
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700131 videobuf = std::make_shared<RawVideoBuffer>();
132
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700133 imageInfo.doImageRefresh = 1; // full frame refresh
134 imageInfo.qcValid = 0; // quick cursor disabled
135 imageInfo.parameter.features.buf =
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700136 reinterpret_cast<unsigned char *>(videobuf->buffer.data());
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700137 imageInfo.crypttype = -1;
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700138 };
139
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700140 void registerCallback(video_callback &callback) {
141 std::lock_guard<std::mutex> lock(callbackMutex);
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700142 callbacks.push_back(callback);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700143 startRead();
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700144 }
145
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700146 void startRead() {
147 auto mutableBuffer = boost::asio::buffer(&imageInfo, sizeof(imageInfo));
148 boost::asio::async_read(devVideo, mutableBuffer,
149 [this](const boost::system::error_code &ec,
150 std::size_t bytes_transferred) {
151 if (ec) {
152 std::cerr << "Read failed with status " << ec
153 << "\n";
154 } else {
155 this->readDone();
156 }
157 });
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700158 }
159
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700160 void readDone() {
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700161 std::cout << "Done reading\n";
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700162 videobuf->buffer.resize(imageInfo.len);
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700163
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700164 videobuf->height = imageInfo.parameter.features.h;
165 videobuf->width = imageInfo.parameter.features.w;
166 if (imageInfo.parameter.features.jpgFmt == 422) {
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700167 videobuf->mode = YuvMode::YUV420;
168 } else {
169 videobuf->mode = YuvMode::YUV444;
170 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700171 std::lock_guard<std::mutex> lock(callbackMutex);
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700172 for (auto &callback : callbacks) {
173 // TODO(ed) call callbacks async and double buffer frames
174 callback(*videobuf);
175 }
176 }
177
178 private:
179 std::shared_ptr<RawVideoBuffer> videobuf;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700180 boost::asio::posix::stream_descriptor devVideo;
181 ImageInfo imageInfo;
182 std::mutex callbackMutex;
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700183 std::vector<video_callback> callbacks;
184};
185#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700186} // namespace ast_video