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