blob: e813a0074aea0de9786bdf51a9d2a1cad7324b03 [file] [log] [blame]
Jim Ostrowski977850f2022-01-22 21:04:22 -08001#ifndef FRC971_VISION_V4L2_READER_H_
2#define FRC971_VISION_V4L2_READER_H_
Brian Silverman9dd793b2020-01-31 23:52:21 -08003
4#include <array>
5#include <string>
6
7#include "absl/types/span.h"
Brian Silverman9dd793b2020-01-31 23:52:21 -08008#include "aos/events/event_loop.h"
9#include "aos/scoped/scoped_fd.h"
Jim Ostrowski977850f2022-01-22 21:04:22 -080010#include "frc971/vision/vision_generated.h"
Austin Schuh77d0bbd2022-12-26 14:00:51 -080011#include "glog/logging.h"
Brian Silverman9dd793b2020-01-31 23:52:21 -080012
13namespace frc971 {
14namespace vision {
15
16// Reads images from a V4L2 capture device (aka camera).
Austin Schuh77d0bbd2022-12-26 14:00:51 -080017class V4L2ReaderBase {
Brian Silverman9dd793b2020-01-31 23:52:21 -080018 public:
19 // device_name is the name of the device file (like "/dev/video0").
Austin Schuh77d0bbd2022-12-26 14:00:51 -080020 V4L2ReaderBase(aos::EventLoop *event_loop, const std::string &device_name);
Brian Silverman9dd793b2020-01-31 23:52:21 -080021
Austin Schuh77d0bbd2022-12-26 14:00:51 -080022 V4L2ReaderBase(const V4L2ReaderBase &) = delete;
23 V4L2ReaderBase &operator=(const V4L2ReaderBase &) = delete;
Brian Silverman9dd793b2020-01-31 23:52:21 -080024
25 // Reads the latest image.
26 //
Brian Silverman967e5df2020-02-09 16:43:34 -080027 // Returns false if no image was available since the last image was read.
28 // Call LatestImage() to get a reference to the data, which will be valid
29 // until this method is called again.
30 bool ReadLatestImage();
Brian Silverman9dd793b2020-01-31 23:52:21 -080031
32 // Sends the latest image.
33 //
34 // ReadLatestImage() must have returned a non-empty span the last time it was
35 // called. After calling this, the data which was returned from
36 // ReadLatestImage() will no longer be valid.
37 void SendLatestImage();
38
Brian Silverman967e5df2020-02-09 16:43:34 -080039 const CameraImage &LatestImage() {
40 Buffer *const buffer = &buffers_[saved_buffer_.index];
41 return *flatbuffers::GetTemporaryPointer(*buffer->builder.fbb(),
42 buffer->message_offset);
43 }
44
milind-udaebe9b2022-01-09 18:25:24 -080045 // Sets the exposure duration of the camera. duration is the number of 100
46 // microsecond units.
47 void SetExposure(size_t duration);
48
49 // Switches from manual to auto exposure.
50 void UseAutoExposure();
51
Austin Schuh77d0bbd2022-12-26 14:00:51 -080052 protected:
53 void StreamOff();
54 void StreamOn();
55
56 int Ioctl(unsigned long number, void *arg);
57
58 bool multiplanar() const { return multiplanar_; }
59
60 // TODO(Brian): This concept won't exist once we start using variable-size
61 // H.264 frames.
62 size_t ImageSize() const { return rows_ * cols_ * 2 /* bytes per pixel */; }
63
Brian Silverman9dd793b2020-01-31 23:52:21 -080064 private:
Austin Schuh77d0bbd2022-12-26 14:00:51 -080065 static constexpr int kNumberBuffers = 4;
Brian Silverman9dd793b2020-01-31 23:52:21 -080066
67 struct Buffer {
Brian Silverman967e5df2020-02-09 16:43:34 -080068 void InitializeMessage(size_t max_image_size);
Brian Silverman9dd793b2020-01-31 23:52:21 -080069
Brian Silverman967e5df2020-02-09 16:43:34 -080070 void PrepareMessage(int rows, int cols, size_t image_size,
71 aos::monotonic_clock::time_point monotonic_eof);
72
73 void Send() {
milind1f1dca32021-07-03 13:50:07 -070074 (void)builder.Send(message_offset);
Brian Silverman967e5df2020-02-09 16:43:34 -080075 message_offset = flatbuffers::Offset<CameraImage>();
Brian Silverman9dd793b2020-01-31 23:52:21 -080076 }
77
78 absl::Span<const char> DataSpan(size_t image_size) {
Brian Silverman967e5df2020-02-09 16:43:34 -080079 return absl::Span<const char>(
80 reinterpret_cast<char *>(CHECK_NOTNULL(data_pointer)), image_size);
Brian Silverman9dd793b2020-01-31 23:52:21 -080081 }
82
83 aos::Sender<CameraImage> sender;
84 aos::Sender<CameraImage>::Builder builder;
Brian Silverman967e5df2020-02-09 16:43:34 -080085 flatbuffers::Offset<CameraImage> message_offset;
Brian Silverman9dd793b2020-01-31 23:52:21 -080086
87 uint8_t *data_pointer = nullptr;
88 };
89
Brian Silverman967e5df2020-02-09 16:43:34 -080090 struct BufferInfo {
91 int index = -1;
92 aos::monotonic_clock::time_point monotonic_eof =
93 aos::monotonic_clock::min_time;
94
95 explicit operator bool() const { return index != -1; }
96
97 void Clear() {
98 index = -1;
99 monotonic_eof = aos::monotonic_clock::min_time;
100 }
101 };
102
Brian Silverman9dd793b2020-01-31 23:52:21 -0800103 // Attempts to dequeue a buffer (nonblocking). Returns the index of the new
Brian Silverman967e5df2020-02-09 16:43:34 -0800104 // buffer, or BufferInfo() if there wasn't a frame to dequeue.
105 BufferInfo DequeueBuffer();
Brian Silverman9dd793b2020-01-31 23:52:21 -0800106
107 void EnqueueBuffer(int buffer);
108
Brian Silverman9dd793b2020-01-31 23:52:21 -0800109 // The mmaped V4L2 buffers.
110 std::array<Buffer, kNumberBuffers> buffers_;
111
112 // If this is non-negative, it's the buffer number we're currently holding
113 // onto.
Brian Silverman967e5df2020-02-09 16:43:34 -0800114 BufferInfo saved_buffer_;
Brian Silverman9dd793b2020-01-31 23:52:21 -0800115
Austin Schuh77d0bbd2022-12-26 14:00:51 -0800116 bool multiplanar_ = false;
117
118 int rows_ = 0;
119 int cols_ = 0;
Brian Silverman9dd793b2020-01-31 23:52:21 -0800120
121 aos::ScopedFD fd_;
Austin Schuh77d0bbd2022-12-26 14:00:51 -0800122
123 aos::EventLoop *event_loop_;
124 aos::Ftrace ftrace_;
125};
126
127// Generic V4L2 reader for pi's and older.
128class V4L2Reader : public V4L2ReaderBase {
129 public:
130 V4L2Reader(aos::EventLoop *event_loop, const std::string &device_name);
131
132 private:
133 const int rows_ = 480;
134 const int cols_ = 640;
135};
136
137// Rockpi specific v4l2 reader. This assumes that the media device has been
138// properly configured before this class is constructed.
139class RockchipV4L2Reader : public V4L2ReaderBase {
140 public:
141 RockchipV4L2Reader(aos::EventLoop *event_loop, const std::string &device_name);
Brian Silverman9dd793b2020-01-31 23:52:21 -0800142};
143
144} // namespace vision
145} // namespace frc971
146
Jim Ostrowski977850f2022-01-22 21:04:22 -0800147#endif // FRC971_VISION_V4L2_READER_H_