• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 CPP_EVS_SAMPLEDRIVER_AIDL_INCLUDE_VIDEOCAPTURE_H
17 #define CPP_EVS_SAMPLEDRIVER_AIDL_INCLUDE_VIDEOCAPTURE_H
18 
19 #include <linux/videodev2.h>
20 
21 #include <atomic>
22 #include <functional>
23 #include <set>
24 #include <thread>
25 
26 typedef v4l2_buffer imageBuffer;
27 
28 class VideoCapture final {
29 public:
30     bool open(const char* deviceName, const int32_t width = 0, const int32_t height = 0);
31     void close();
32 
33     bool startStream(std::function<void(VideoCapture*, imageBuffer*, void* [VIDEO_MAX_PLANES],
34                                         size_t[VIDEO_MAX_PLANES], size_t)>
35                              callback = nullptr);
36     void stopStream();
37 
38     // Valid only after open()
getWidth()39     __u32 getWidth() { return mWidth; };
getHeight()40     __u32 getHeight() { return mHeight; };
getStride()41     __u32 getStride() { return mStride; };
getV4LFormat()42     __u32 getV4LFormat() { return mFormat; };
43 
44     // NULL until stream is started
getLatestData(int * numPlanes)45     void** getLatestData(int *numPlanes) {
46         if (mFrames.empty()) {
47             // No frame is available
48             return nullptr;
49         }
50 
51         // Return a pointer to the buffer captured most recently
52         const int id = *mFrames.end();
53         *numPlanes = mBufferInfos[id].numPlanes;
54         return mBufferInfos[id].start;
55     }
56 
isFrameReady()57     bool isFrameReady() { return !mFrames.empty(); }
markFrameConsumed(int id)58     void markFrameConsumed(int id) { returnFrame(id); }
59 
isOpen()60     bool isOpen() { return mDeviceFd >= 0; }
61 
62     int setParameter(struct v4l2_control& control);
63     int getParameter(struct v4l2_control& control);
64     std::set<uint32_t> enumerateCameraControls();
65 
66 private:
67     void collectFrames();
68     bool returnFrame(int id);
69 
70     int mDeviceFd = -1;
71 
72     struct BufferDesc {
73         // Dequeued v4l2 buffer.
74         v4l2_buffer buffer;
75 
76         v4l2_plane planes[VIDEO_MAX_PLANES];
77         __u32 bytesused;
78 
79         void* start[VIDEO_MAX_PLANES];
80         size_t length[VIDEO_MAX_PLANES];
81         size_t numPlanes;
82     };
83 
84     int mNumBuffers = 0;
85     std::unique_ptr<BufferDesc[]> mBufferInfos = nullptr;
86 
87     __u32 mFormat = 0;
88     __u32 mWidth = 0;
89     __u32 mHeight = 0;
90     __u32 mStride = 0;
91     __u32 mNumPlanes = 1;
92     bool mIsMultiplanar = false;
93 
94     std::function<void(VideoCapture*, imageBuffer*, void* [VIDEO_MAX_PLANES],
95                        size_t[VIDEO_MAX_PLANES], size_t)>
96             mCallback;
97 
98     std::thread mCaptureThread;  // The thread we'll use to dispatch frames
99     std::atomic<int> mRunMode;   // Used to signal the frame loop (see RunModes below)
100     std::set<int> mFrames;       // Set of available frame buffers
101 
102     // Careful changing these -- we're using bit-wise ops to manipulate these
103     enum RunModes {
104         STOPPED = 0,
105         RUN = 1,
106         STOPPING = 2,
107     };
108 };
109 
110 #endif  // CPP_EVS_SAMPLEDRIVER_AIDL_INCLUDE_VIDEOCAPTURE_H
111