blob: 759aaebb007eecc5487af52038e01f324cfff999 [file] [log] [blame]
Ed Tanous93f987d2017-04-17 17:52:36 -07001#pragma once
2
Ed Tanous911ac312017-08-15 09:37:42 -07003#include <cassert>
Ed Tanous1ff48782017-04-18 12:45:08 -07004#include <ast_video_types.hpp>
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
10namespace AstVideo {
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 Tanous911ac312017-08-15 09:37:42 -070015struct AST_CUR_ATTRIBUTION_TAG {
Ed Tanouse2fc45a2017-04-26 09:19:10 -070016 unsigned int posX;
17 unsigned int posY;
18 unsigned int cur_width;
19 unsigned int cur_height;
20 unsigned int cur_type; // 0:mono 1:color 2:disappear cursor
21 unsigned int cur_change_flag;
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 Tanous911ac312017-08-15 09:37:42 -070027struct AST_CURSOR_TAG {
Ed Tanouse2fc45a2017-04-26 09:19:10 -070028 AST_CUR_ATTRIBUTION_TAG attr;
29 // 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 Tanous911ac312017-08-15 09:37:42 -070037struct FEATURES_TAG {
Ed Tanouse2fc45a2017-04-26 09:19:10 -070038 short jpg_fmt; // 422:JPG420, 444:JPG444
39 short lumin_tbl;
40 short chrom_tbl;
41 short tolerance_noise;
42 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 Tanous911ac312017-08-15 09:37:42 -070050struct IMAGE_INFO {
Ed Tanouse2fc45a2017-04-26 09:19:10 -070051 short do_image_refresh; // Action 0:motion 1:fullframe 2:quick cursor
52 char qc_valid; // quick cursor enable/disable
53 unsigned int len;
54 int crypttype;
55 char cryptkey[16];
56 union {
57 FEATURES_TAG features;
58 AST_CURSOR_TAG cursor_info;
59 } 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 Tanouse2fc45a2017-04-26 09:19:10 -070064 SimpleVideoPuller() : image_info(){};
Ed Tanous93f987d2017-04-17 17:52:36 -070065
66 void initialize() {
67 std::cout << "Opening /dev/video\n";
68 video_fd = open("/dev/video", O_RDWR);
Ed Tanous911ac312017-08-15 09:37:42 -070069 if (video_fd == 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
76 RawVideoBuffer read_video() {
77 assert(video_fd != 0);
78 RawVideoBuffer raw;
79
Ed Tanous93f987d2017-04-17 17:52:36 -070080 image_info.do_image_refresh = 1; // full frame refresh
81 image_info.qc_valid = 0; // quick cursor disabled
Ed Tanous93f987d2017-04-17 17:52:36 -070082 image_info.parameter.features.buf =
83 reinterpret_cast<unsigned char *>(raw.buffer.data());
84 image_info.crypttype = -1;
85 std::cout << "Writing\n";
86
87 int status;
88 /*
89 status = write(video_fd, reinterpret_cast<char*>(&image_info),
90 sizeof(image_info));
91 if (status != sizeof(image_info)) {
92 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 Tanous93f987d2017-04-17 17:52:36 -070099 status = read(video_fd, reinterpret_cast<char *>(&image_info),
100 sizeof(image_info));
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
107 raw.buffer.resize(image_info.len);
108
109 raw.height = image_info.parameter.features.h;
110 raw.width = image_info.parameter.features.w;
111 if (image_info.parameter.features.jpg_fmt == 422) {
112 raw.mode = YuvMode::YUV420;
113 } else {
114 raw.mode = YuvMode::YUV444;
115 }
116 return raw;
117 }
118
119 private:
Ed Tanous911ac312017-08-15 09:37:42 -0700120 int video_fd{};
Ed Tanous93f987d2017-04-17 17:52:36 -0700121 IMAGE_INFO image_info;
122};
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700123
124#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
125class AsyncVideoPuller {
126 public:
Ed Tanous911ac312017-08-15 09:37:42 -0700127 using video_callback = std::function<void (RawVideoBuffer &)>;
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700128
Ed Tanous911ac312017-08-15 09:37:42 -0700129 explicit AsyncVideoPuller(boost::asio::io_service &io_service)
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700130 : image_info(), dev_video(io_service, open("/dev/video", O_RDWR)) {
131 videobuf = std::make_shared<RawVideoBuffer>();
132
133 image_info.do_image_refresh = 1; // full frame refresh
134 image_info.qc_valid = 0; // quick cursor disabled
135 image_info.parameter.features.buf =
136 reinterpret_cast<unsigned char *>(videobuf->buffer.data());
137 image_info.crypttype = -1;
138 };
139
140 void register_callback(video_callback &callback) {
141 std::lock_guard<std::mutex> lock(callback_mutex);
142 callbacks.push_back(callback);
143 start_read();
144 }
145
146 void start_read() {
147 auto mutable_buffer = boost::asio::buffer(&image_info, sizeof(image_info));
148 boost::asio::async_read(
149 dev_video, mutable_buffer, [this](const boost::system::error_code &ec,
150 std::size_t bytes_transferred) {
Ed Tanous911ac312017-08-15 09:37:42 -0700151 if (ec != nullptr) {
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700152 std::cerr << "Read failed with status " << ec << "\n";
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700153 } else {
154 this->read_done();
155 }
156 });
157 }
158
159 void read_done() {
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700160 std::cout << "Done reading\n";
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700161 videobuf->buffer.resize(image_info.len);
162
163 videobuf->height = image_info.parameter.features.h;
164 videobuf->width = image_info.parameter.features.w;
165 if (image_info.parameter.features.jpg_fmt == 422) {
166 videobuf->mode = YuvMode::YUV420;
167 } else {
168 videobuf->mode = YuvMode::YUV444;
169 }
170 std::lock_guard<std::mutex> lock(callback_mutex);
171 for (auto &callback : callbacks) {
172 // TODO(ed) call callbacks async and double buffer frames
173 callback(*videobuf);
174 }
175 }
176
177 private:
178 std::shared_ptr<RawVideoBuffer> videobuf;
179 boost::asio::posix::stream_descriptor dev_video;
180 IMAGE_INFO image_info;
181 std::mutex callback_mutex;
182 std::vector<video_callback> callbacks;
183};
184#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
Ed Tanous911ac312017-08-15 09:37:42 -0700185} // namespace AstVideo