blob: 6575d7e84775445002cb289af678a2a86f3144f6 [file] [log] [blame]
#pragma once
#include <assert.h>
#include <ast_video_types.hpp>
#include <iostream>
#include <mutex>
#include <vector>
#include <boost/asio.hpp>
namespace AstVideo {
//
// 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:
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";
throw std::runtime_error("Failed to open /dev/video");
}
std::cout << "Opened successfully\n";
}
RawVideoBuffer read_video() {
assert(video_fd != 0);
RawVideoBuffer raw;
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 *>(raw.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 != sizeof(image_info)) {
std::cout << "Write failed. Return: " << status << "\n";
perror("perror output:");
}
std::cout << "Write done\n";
*/
std::cout << "Reading\n";
status = read(video_fd, reinterpret_cast<char *>(&image_info),
sizeof(image_info));
std::cout << "Done reading\n";
if (status != 0) {
std::cerr << "Read failed with status " << status << "\n";
}
raw.buffer.resize(image_info.len);
raw.height = image_info.parameter.features.h;
raw.width = image_info.parameter.features.w;
if (image_info.parameter.features.jpg_fmt == 422) {
raw.mode = YuvMode::YUV420;
} else {
raw.mode = YuvMode::YUV444;
}
return raw;
}
private:
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) {
std::cerr << "Read failed with status " << ec << "\n";
} else {
this->read_done();
}
});
}
void read_done() {
std::cout << "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)
}