blob: c97ca4860a9574185527d59d8ab8b1d9b23aa594 [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 Tanous1abe55e2018-09-05 08:30:59 -07004#include <boost/asio.hpp>
Ed Tanous55c7b7a2018-05-22 15:27:24 -07005#include <cassert>
Ed Tanous93f987d2017-04-17 17:52:36 -07006#include <iostream>
Ed Tanouse2fc45a2017-04-26 09:19:10 -07007#include <mutex>
Ed Tanous1ff48782017-04-18 12:45:08 -07008#include <vector>
Ed Tanous93f987d2017-04-17 17:52:36 -07009
Ed Tanous1abe55e2018-09-05 08:30:59 -070010namespace ast_video
11{
Ed Tanousd5f39992017-04-18 13:41:22 -070012
Ed Tanouse2fc45a2017-04-26 09:19:10 -070013//
14// Cursor struct is used in User Mode
15//
Ed Tanous1abe55e2018-09-05 08:30:59 -070016struct AstCurAttributionTag
17{
18 unsigned int posX;
19 unsigned int posY;
20 unsigned int curWidth;
21 unsigned int curHeight;
22 unsigned int curType; // 0:mono 1:color 2:disappear cursor
23 unsigned int curChangeFlag;
Ed Tanous911ac312017-08-15 09:37:42 -070024};
Ed Tanousd5f39992017-04-18 13:41:22 -070025
Ed Tanouse2fc45a2017-04-26 09:19:10 -070026//
27// For storing Cursor Information
28//
Ed Tanous1abe55e2018-09-05 08:30:59 -070029struct AstCursorTag
30{
31 AstCurAttributionTag attr;
32 // unsigned char icon[MAX_CUR_OFFSETX*MAX_CUR_OFFSETY*2];
33 unsigned char *icon; //[64*64*2];
Ed Tanous911ac312017-08-15 09:37:42 -070034};
Ed Tanousd5f39992017-04-18 13:41:22 -070035
Ed Tanouse2fc45a2017-04-26 09:19:10 -070036//
37// For select image format, i.e. 422 JPG420, 444 JPG444, lumin/chrom table, 0
38// ~ 11, low to high
39//
Ed Tanous1abe55e2018-09-05 08:30:59 -070040struct FeaturesTag
41{
42 short jpgFmt; // 422:JPG420, 444:JPG444
43 short luminTbl;
44 short chromTbl;
45 short toleranceNoise;
46 int w;
47 int h;
48 unsigned char *buf;
Ed Tanous911ac312017-08-15 09:37:42 -070049};
Ed Tanousd5f39992017-04-18 13:41:22 -070050
Ed Tanouse2fc45a2017-04-26 09:19:10 -070051//
52// For configure video engine control registers
53//
Ed Tanous1abe55e2018-09-05 08:30:59 -070054struct ImageInfo
55{
56 short doImageRefresh; // Action 0:motion 1:fullframe 2:quick cursor
57 char qcValid; // quick cursor enable/disable
58 unsigned int len;
59 int crypttype;
60 char cryptkey[16];
61 union
62 {
63 FeaturesTag features;
64 AstCursorTag cursorInfo;
65 } parameter;
Ed Tanous911ac312017-08-15 09:37:42 -070066};
Ed Tanouse2fc45a2017-04-26 09:19:10 -070067
Ed Tanous1abe55e2018-09-05 08:30:59 -070068class SimpleVideoPuller
69{
70 public:
71 SimpleVideoPuller() : imageInfo(){};
Ed Tanous93f987d2017-04-17 17:52:36 -070072
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 void initialize()
74 {
75 std::cout << "Opening /dev/video\n";
76 videoFd = open("/dev/video", O_RDWR);
77 if (videoFd == 0)
78 {
79 std::cout << "Failed to open /dev/video\n";
80 throw std::runtime_error("Failed to open /dev/video");
81 }
82 std::cout << "Opened successfully\n";
Ed Tanous93f987d2017-04-17 17:52:36 -070083 }
Ed Tanous1ff48782017-04-18 12:45:08 -070084
Ed Tanous1abe55e2018-09-05 08:30:59 -070085 RawVideoBuffer readVideo()
86 {
87 assert(videoFd != 0);
88 RawVideoBuffer raw;
Ed Tanous93f987d2017-04-17 17:52:36 -070089
Ed Tanous1abe55e2018-09-05 08:30:59 -070090 imageInfo.doImageRefresh = 1; // full frame refresh
91 imageInfo.qcValid = 0; // quick cursor disabled
92 imageInfo.parameter.features.buf =
93 reinterpret_cast<unsigned char *>(raw.buffer.data());
94 imageInfo.crypttype = -1;
95 std::cout << "Writing\n";
96
97 int status;
98 /*
99 status = write(videoFd, reinterpret_cast<char*>(&imageInfo),
100 sizeof(imageInfo));
101 if (status != sizeof(imageInfo)) {
102 std::cout << "Write failed. Return: " << status << "\n";
103 perror("perror output:");
104 }
105
106 std::cout << "Write done\n";
107 */
108 std::cout << "Reading\n";
109 status = read(videoFd, reinterpret_cast<char *>(&imageInfo),
110 sizeof(imageInfo));
111 std::cout << "Done reading\n";
112
113 if (status != 0)
114 {
115 std::cerr << "Read failed with status " << status << "\n";
116 }
117
118 raw.buffer.resize(imageInfo.len);
119
120 raw.height = imageInfo.parameter.features.h;
121 raw.width = imageInfo.parameter.features.w;
122 if (imageInfo.parameter.features.jpgFmt == 422)
123 {
124 raw.mode = YuvMode::YUV420;
125 }
126 else
127 {
128 raw.mode = YuvMode::YUV444;
129 }
130 return raw;
Ed Tanous93f987d2017-04-17 17:52:36 -0700131 }
132
Ed Tanous1abe55e2018-09-05 08:30:59 -0700133 private:
134 int videoFd{};
135 ImageInfo imageInfo;
Ed Tanous93f987d2017-04-17 17:52:36 -0700136};
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700137
138#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700139class AsyncVideoPuller
140{
141 public:
142 using video_callback = std::function<void(RawVideoBuffer &)>;
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700143
Ed Tanous8f626352018-12-19 14:51:54 -0800144 explicit AsyncVideoPuller(boost::asio::io_context &ioService) :
Ed Tanous1abe55e2018-09-05 08:30:59 -0700145 imageInfo(), devVideo(ioService, open("/dev/video", O_RDWR))
146 {
147 videobuf = std::make_shared<RawVideoBuffer>();
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700148
Ed Tanous1abe55e2018-09-05 08:30:59 -0700149 imageInfo.doImageRefresh = 1; // full frame refresh
150 imageInfo.qcValid = 0; // quick cursor disabled
151 imageInfo.parameter.features.buf =
152 reinterpret_cast<unsigned char *>(videobuf->buffer.data());
153 imageInfo.crypttype = -1;
154 };
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700155
Ed Tanous1abe55e2018-09-05 08:30:59 -0700156 void registerCallback(video_callback &callback)
157 {
158 std::lock_guard<std::mutex> lock(callbackMutex);
159 callbacks.push_back(callback);
160 startRead();
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700161 }
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700162
Ed Tanous1abe55e2018-09-05 08:30:59 -0700163 void startRead()
164 {
165 auto mutableBuffer = boost::asio::buffer(&imageInfo, sizeof(imageInfo));
166 boost::asio::async_read(devVideo, mutableBuffer,
167 [this](const boost::system::error_code &ec,
168 std::size_t bytes_transferred) {
169 if (ec)
170 {
171 std::cerr << "Read failed with status "
172 << ec << "\n";
173 }
174 else
175 {
176 this->readDone();
177 }
178 });
179 }
180
181 void readDone()
182 {
183 std::cout << "Done reading\n";
184 videobuf->buffer.resize(imageInfo.len);
185
186 videobuf->height = imageInfo.parameter.features.h;
187 videobuf->width = imageInfo.parameter.features.w;
188 if (imageInfo.parameter.features.jpgFmt == 422)
189 {
190 videobuf->mode = YuvMode::YUV420;
191 }
192 else
193 {
194 videobuf->mode = YuvMode::YUV444;
195 }
196 std::lock_guard<std::mutex> lock(callbackMutex);
197 for (auto &callback : callbacks)
198 {
199 // TODO(ed) call callbacks async and double buffer frames
200 callback(*videobuf);
201 }
202 }
203
204 private:
205 std::shared_ptr<RawVideoBuffer> videobuf;
206 boost::asio::posix::stream_descriptor devVideo;
207 ImageInfo imageInfo;
208 std::mutex callbackMutex;
209 std::vector<video_callback> callbacks;
Ed Tanouse2fc45a2017-04-26 09:19:10 -0700210};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
212} // namespace ast_video