1 /*
2  * Copyright (C) 2017 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 
17 #ifndef EVS_VTS_STREAMHANDLER_H
18 #define EVS_VTS_STREAMHANDLER_H
19 
20 #include "BaseAnalyzeCallback.h"
21 #include "BaseRenderCallback.h"
22 
23 #include <android/hardware/automotive/evs/1.0/IEvsCamera.h>
24 #include <android/hardware/automotive/evs/1.0/IEvsCameraStream.h>
25 #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
26 #include <ui/GraphicBuffer.h>
27 
28 #include <condition_variable>
29 #include <queue>
30 #include <shared_mutex>
31 #include <thread>
32 
33 namespace android {
34 namespace automotive {
35 namespace evs {
36 namespace support {
37 
38 using ::android::hardware::hidl_handle;
39 using ::android::hardware::hidl_vec;
40 using ::android::hardware::Return;
41 using ::android::hardware::Void;
42 using ::android::hardware::automotive::evs::V1_0::BufferDesc;
43 using ::android::hardware::automotive::evs::V1_0::IEvsCamera;
44 using ::android::hardware::automotive::evs::V1_0::IEvsCameraStream;
45 
46 /*
47  * StreamHandler:
48  * This class can be used to receive camera imagery from an IEvsCamera implementation.  It will
49  * hold onto the most recent image buffer, returning older ones.
50  * Note that the video frames are delivered on a background thread, while the control interface
51  * is actuated from the applications foreground thread.
52  */
53 class StreamHandler : public IEvsCameraStream {
54 public:
~StreamHandler()55     virtual ~StreamHandler() {
56         // The shutdown logic is supposed to be handled by ResourceManager
57         // class. But if something goes wrong, we want to make sure that the
58         // related resources are still released properly.
59         if (mCamera != nullptr) {
60             shutdown();
61         }
62     };
63 
64     StreamHandler(android::sp<IEvsCamera> pCamera);
65     void shutdown();
66 
67     bool startStream();
68 
69     bool newDisplayFrameAvailable();
70     const BufferDesc& getNewDisplayFrame();
71     void doneWithFrame(const BufferDesc& buffer);
72 
73     /*
74      * Attaches a render callback to the StreamHandler.
75      *
76      * Every frame will be processed by the attached render callback before it
77      * is delivered to the client by method getNewDisplayFrame().
78      *
79      * Since there is only one DisplayUseCase allowed at the same time, at most
80      * only one render callback can be attached. The current render callback
81      * needs to be detached first (by method detachRenderCallback()), before a
82      * new callback can be attached. In other words, the call will be ignored
83      * if the current render callback is not null.
84      *
85      * @see detachRenderCallback()
86      * @see getNewDisplayFrame()
87      */
88     void attachRenderCallback(BaseRenderCallback*);
89 
90     /*
91      * Detaches the current render callback.
92      *
93      * If no render callback is attached, this call will be ignored.
94      *
95      * @see attachRenderCallback(BaseRenderCallback*)
96      */
97     void detachRenderCallback();
98 
99     /*
100      * Attaches an analyze callback to the StreamHandler.
101      *
102      * When there is a valid analyze callback attached, a thread dedicated for
103      * the analyze callback will be allocated. When the thread is not busy, the
104      * next available evs frame will be copied (now happens in binder thread).
105      * And the copy will be passed into the analyze thread, and be processed by
106      * the analyze callback.
107      *
108      * Since there is only one AnalyzeUseCase allowed at the same time, at most
109      * only one analyze callback can be attached. The current analyze callback
110      * needs to be detached first (by method detachAnalyzeCallback()), before a
111      * new callback can be attached. In other words, the call will be ignored
112      * if the current analyze callback is not null.
113      *
114      * @see detachAnalyzeCallback()
115      */
116     // TODO(b/130246434): now only one analyze use case is supported, so one
117     // analyze thread id good enough. But we should be able to support several
118     // analyze use cases running at the same time, so we should probably use a
119     // thread pool to handle the cases.
120     void attachAnalyzeCallback(BaseAnalyzeCallback*);
121 
122     /*
123      * Detaches the current analyze callback.
124      *
125      * If no analyze callback is attached, this call will be ignored.
126      *
127      * @see attachAnalyzeCallback(BaseAnalyzeCallback*)
128      */
129     void detachAnalyzeCallback();
130 
131 private:
132     // Implementation for ::android::hardware::automotive::evs::V1_0::ICarCameraStream
133     Return<void> deliverFrame(const BufferDesc& buffer) override;
134 
135     bool processFrame(const BufferDesc&, BufferDesc&);
136     bool copyAndAnalyzeFrame(const BufferDesc&);
137 
138     // Values initialized as startup
139     android::sp<IEvsCamera> mCamera;
140 
141     // Since we get frames delivered to us asnchronously via the ICarCameraStream interface,
142     // we need to protect all member variables that may be modified while we're streaming
143     // (ie: those below)
144     std::mutex mLock;
145     std::condition_variable mSignal;
146 
147     bool mRunning = false;
148 
149     BufferDesc mOriginalBuffers[2];
150     int mHeldBuffer = -1;   // Index of the one currently held by the client
151     int mReadyBuffer = -1;  // Index of the newest available buffer
152 
153     BufferDesc mProcessedBuffers[2];
154     BufferDesc mAnalyzeBuffer GUARDED_BY(mAnalyzerLock);
155 
156     BaseRenderCallback* mRenderCallback = nullptr;
157 
158     BaseAnalyzeCallback* mAnalyzeCallback GUARDED_BY(mAnalyzerLock);
159     std::atomic<bool> mAnalyzerRunning;
160     std::shared_mutex mAnalyzerLock;
161     std::condition_variable_any mAnalyzerSignal;
162 };
163 
164 }  // namespace support
165 }  // namespace evs
166 }  // namespace automotive
167 }  // namespace android
168 
169 #endif  // EVS_VTS_STREAMHANDLER_H
170