1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EMULVIDEOCAPTURE_H
17 #define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EMULVIDEOCAPTURE_H
18 
19 #include <android-base/chrono_utils.h>
20 #include <linux/videodev2.h>
21 #include <utils/Looper.h>
22 #include <utils/Mutex.h>
23 #include <utils/Timers.h>
24 
25 #include <atomic>
26 #include <filesystem>
27 #include <functional>
28 #include <thread>
29 
30 namespace {
31 
32 // Careful changing these -- we're using bit-wise ops to manipulate these
33 enum RunModes {
34     STOPPED = 0,
35     RUN = 1,
36     STOPPING = 2,
37 };
38 
39 enum StreamEvent {
40     INIT = 0,
41     PERIODIC,
42     STOP,
43     TERMINATED,
44 };
45 
46 struct imageMetadata {
47     uint32_t width;   // Image width in pixels
48     uint32_t height;  // Image height in pixels
49     uint32_t stride;  // Number of bytes from one row in memory
50     uint32_t format;  // Image format
51 };
52 }  // namespace
53 
54 typedef struct {
55     struct imageMetadata info;
56     uint32_t sequence;         // Counting frames in sequence
57     struct timeval timestamp;  // Tells when this frame is generated
58 } imageBufferDesc;
59 
60 namespace android {
61 namespace automotive {
62 namespace evs {
63 namespace V1_1 {
64 namespace implementation {
65 
66 class VideoCapture : public MessageHandler {
67 public:
VideoCapture()68     explicit VideoCapture() {};
69     virtual ~VideoCapture();
70     bool open(const std::string& path, const std::chrono::nanoseconds interval);
71     void close();
72 
73     bool startStream(
74             std::function<void(VideoCapture*, imageBufferDesc*, void*)> callback = nullptr);
75     void stopStream();
76 
77     // Valid only after open()
getWidth()78     __u32 getWidth() { return mBufferInfo.info.width; }
getHeight()79     __u32 getHeight() { return mBufferInfo.info.height; }
getStride()80     __u32 getStride() { return mBufferInfo.info.stride; }
getV4LFormat()81     __u32 getV4LFormat() { return mBufferInfo.info.format; }
82 
83     // NULL until stream is started
getLatestData()84     void* getLatestData() { return mPixelBuffer; }
isFrameReady()85     bool isFrameReady() { return mFrameReady; }
markFrameConsumed()86     void markFrameConsumed() { returnFrame(); }
isOpen()87     bool isOpen() { return mVideoReady; }
88 
89     int setParameter(struct v4l2_control& control);
90     int getParameter(struct v4l2_control& control);
91 
92 private:
93     void collectFrames();
94     void markFrameReady();
95     bool returnFrame();
96 
97     // Handles the message from the looper
98     void handleMessage(const android::Message& message) override;
99 
100     // Looper to message the frame generator thread
101     android::sp<android::Looper> mLooper;
102 
103     // Background thread to dispatch generated frames
104     std::thread mCaptureThread;
105 
106     // Stream event to control the looper
107     StreamEvent mCurrentStreamEvent = StreamEvent::INIT;
108 
109     // Directory where source files exist
110     std::filesystem::path mSourceDir;
111     std::filesystem::directory_iterator mSrcIter;
112 
113     // Last time the frame was generated and sent
114     nsecs_t mLastTimeFrameSent;
115 
116     // Desired interval to generate and send a frame
117     std::chrono::nanoseconds mDesiredFrameInterval = 1000ms;
118 
119     // Source image descriptor
120     imageBufferDesc mBufferInfo = {};
121 
122     // Buffer to store the source pixel data
123     char* mPixelBuffer = nullptr;
124 
125     // Current pixel buffer size
126     size_t mPixelBufferSize = 0;
127 
128     // Callback to tell about new frames
129     std::function<void(VideoCapture*, imageBufferDesc*, void*)> mCallback;
130 
131     // Used to signal the frame loop (see RunModes below)
132     std::atomic<int> mRunMode;
133 
134     // Set when a frame has been delivered
135     std::atomic<bool> mFrameReady;
136 
137     // flag to tell whether it is ready to start a stream
138     bool mVideoReady = false;
139 };
140 
141 }  // namespace implementation
142 }  // namespace V1_1
143 }  // namespace evs
144 }  // namespace automotive
145 }  // namespace android
146 
147 #endif  // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EMULVIDEOCAPTURE_
148