• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "StreamHandler.h"
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include <android-base/logging.h>
23 #include <cutils/native_handle.h>
24 #include <ui/GraphicBufferAllocator.h>
25 
26 using ::android::hardware::automotive::evs::V1_0::EvsResult;
27 
28 
29 buffer_handle_t memHandle = nullptr;
StreamHandler(android::sp<IEvsCamera> pCamera,uint32_t numBuffers,bool useOwnBuffers,android_pixel_format_t format,int32_t width,int32_t height)30 StreamHandler::StreamHandler(android::sp <IEvsCamera> pCamera,
31                              uint32_t numBuffers,
32                              bool useOwnBuffers,
33                              android_pixel_format_t format,
34                              int32_t width,
35                              int32_t height)
36     : mCamera(pCamera),
37       mUseOwnBuffers(useOwnBuffers) {
38     if (!useOwnBuffers) {
39         // We rely on the camera having at least two buffers available since we'll hold one and
40         // expect the camera to be able to capture a new image in the background.
41         pCamera->setMaxFramesInFlight(numBuffers);
42     } else {
43         mOwnBuffers.resize(numBuffers);
44 
45         // Acquire the graphics buffer allocator
46         android::GraphicBufferAllocator &alloc(android::GraphicBufferAllocator::get());
47         const auto usage = GRALLOC_USAGE_HW_TEXTURE |
48                            GRALLOC_USAGE_SW_READ_RARELY |
49                            GRALLOC_USAGE_SW_WRITE_OFTEN;
50         for (auto i = 0; i < numBuffers; ++i) {
51             unsigned pixelsPerLine;
52             android::status_t result = alloc.allocate(width,
53                                                       height,
54                                                       format,
55                                                       1,
56                                                       usage,
57                                                       &memHandle,
58                                                       &pixelsPerLine,
59                                                       0,
60                                                       "EvsApp");
61             if (result != android::NO_ERROR) {
62                 LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
63             } else {
64                 BufferDesc_1_1 buf;
65                 AHardwareBuffer_Desc* pDesc =
66                     reinterpret_cast<AHardwareBuffer_Desc *>(&buf.buffer.description);
67                 pDesc->width = width;
68                 pDesc->height = height;
69                 pDesc->layers = 1;
70                 pDesc->format = format;
71                 pDesc->usage = GRALLOC_USAGE_HW_TEXTURE |
72                                GRALLOC_USAGE_SW_READ_RARELY |
73                                GRALLOC_USAGE_SW_WRITE_OFTEN;
74                 pDesc->stride = pixelsPerLine;
75                 buf.buffer.nativeHandle = memHandle;
76                 buf.bufferId = i;   // Unique number to identify this buffer
77                 mOwnBuffers[i] = buf;
78             }
79         }
80 
81         int delta = 0;
82         EvsResult result = EvsResult::OK;
83         pCamera->importExternalBuffers(mOwnBuffers,
84                                        [&](auto _result, auto _delta) {
85                                            result = _result;
86                                            delta = _delta;
87                                        });
88 
89         LOG(INFO) << delta << " buffers are imported by EVS.";
90     }
91 }
92 
93 
shutdown()94 void StreamHandler::shutdown()
95 {
96     // Make sure we're not still streaming
97     blockingStopStream();
98 
99     // At this point, the receiver thread is no longer running, so we can safely drop
100     // our remote object references so they can be freed
101     mCamera = nullptr;
102 
103     if (mUseOwnBuffers) {
104         android::GraphicBufferAllocator &alloc(android::GraphicBufferAllocator::get());
105         for (auto& b : mOwnBuffers) {
106             alloc.free(b.buffer.nativeHandle);
107         }
108 
109         mOwnBuffers.resize(0);
110     }
111 }
112 
113 
startStream()114 bool StreamHandler::startStream() {
115     std::unique_lock<std::mutex> lock(mLock);
116 
117     if (!mRunning) {
118         // Tell the camera to start streaming
119         Return <EvsResult> result = mCamera->startVideoStream(this);
120         if (result != EvsResult::OK) {
121             return false;
122         }
123 
124         // Mark ourselves as running
125         mRunning = true;
126     }
127 
128     return true;
129 }
130 
131 
asyncStopStream()132 void StreamHandler::asyncStopStream() {
133     // Tell the camera to stop streaming.
134     // This will result in a null frame being delivered when the stream actually stops.
135     mCamera->stopVideoStream();
136 }
137 
138 
blockingStopStream()139 void StreamHandler::blockingStopStream() {
140     // Tell the stream to stop
141     asyncStopStream();
142 
143     // Wait until the stream has actually stopped
144     std::unique_lock<std::mutex> lock(mLock);
145     if (mRunning) {
146         mSignal.wait(lock, [this]() { return !mRunning; });
147     }
148 }
149 
150 
isRunning()151 bool StreamHandler::isRunning() {
152     std::unique_lock<std::mutex> lock(mLock);
153     return mRunning;
154 }
155 
156 
newFrameAvailable()157 bool StreamHandler::newFrameAvailable() {
158     std::unique_lock<std::mutex> lock(mLock);
159     return (mReadyBuffer >= 0);
160 }
161 
162 
getNewFrame()163 const BufferDesc_1_1& StreamHandler::getNewFrame() {
164     std::unique_lock<std::mutex> lock(mLock);
165 
166     if (mHeldBuffer >= 0) {
167         LOG(ERROR) << "Ignored call for new frame while still holding the old one.";
168     } else {
169         if (mReadyBuffer < 0) {
170             LOG(ERROR) << "Returning invalid buffer because we don't have any.  "
171                        << "Call newFrameAvailable first?";
172             mReadyBuffer = 0;   // This is a lie!
173         }
174 
175         // Move the ready buffer into the held position, and clear the ready position
176         mHeldBuffer = mReadyBuffer;
177         mReadyBuffer = -1;
178     }
179 
180     return mBuffers[mHeldBuffer];
181 }
182 
183 
doneWithFrame(const BufferDesc_1_1 & bufDesc_1_1)184 void StreamHandler::doneWithFrame(const BufferDesc_1_1& bufDesc_1_1) {
185     std::unique_lock<std::mutex> lock(mLock);
186 
187     // We better be getting back the buffer we original delivered!
188     if ((mHeldBuffer < 0) || (bufDesc_1_1.bufferId != mBuffers[mHeldBuffer].bufferId)) {
189         LOG(ERROR) << "StreamHandler::doneWithFrame got an unexpected bufDesc_1_1!";
190     }
191 
192     // Send the buffer back to the underlying camera
193     hidl_vec<BufferDesc_1_1> frames;
194     frames.resize(1);
195     frames[0] = mBuffers[mHeldBuffer];
196     auto ret = mCamera->doneWithFrame_1_1(frames);
197     if (!ret.isOk()) {
198         LOG(WARNING) << __FUNCTION__ << " fails to return a buffer";
199     }
200 
201     // Clear the held position
202     mHeldBuffer = -1;
203 }
204 
205 
deliverFrame(const BufferDesc_1_0 & bufDesc_1_0)206 Return<void> StreamHandler::deliverFrame(const BufferDesc_1_0& bufDesc_1_0) {
207     LOG(INFO) << "Ignores a frame delivered from v1.0 EVS service.";
208     auto ret = mCamera->doneWithFrame(bufDesc_1_0);
209     if (!ret.isOk()) {
210         LOG(WARNING) << __FUNCTION__ << " fails to return a buffer";
211     }
212 
213     return Void();
214 }
215 
216 
deliverFrame_1_1(const hidl_vec<BufferDesc_1_1> & buffers)217 Return<void> StreamHandler::deliverFrame_1_1(const hidl_vec<BufferDesc_1_1>& buffers) {
218     LOG(DEBUG) << "Received frames from the camera";
219 
220     // Take the lock to protect our frame slots and running state variable
221     std::unique_lock <std::mutex> lock(mLock);
222     BufferDesc_1_1 bufDesc = buffers[0];
223     if (bufDesc.buffer.nativeHandle.getNativeHandle() == nullptr) {
224         // Signal that the last frame has been received and the stream is stopped
225         LOG(WARNING) << "Invalid null frame (id: " << std::hex << bufDesc.bufferId
226                      << ") is ignored";
227     } else {
228         // Do we already have a "ready" frame?
229         if (mReadyBuffer >= 0) {
230             // Send the previously saved buffer back to the camera unused
231             hidl_vec<BufferDesc_1_1> frames;
232             frames.resize(1);
233             frames[0] = mBuffers[mReadyBuffer];
234             auto ret = mCamera->doneWithFrame_1_1(frames);
235             if (!ret.isOk()) {
236                 LOG(WARNING) << __FUNCTION__ << " fails to return a buffer";
237             }
238 
239             // We'll reuse the same ready buffer index
240         } else if (mHeldBuffer >= 0) {
241             // The client is holding a buffer, so use the other slot for "on deck"
242             mReadyBuffer = 1 - mHeldBuffer;
243         } else {
244             // This is our first buffer, so just pick a slot
245             mReadyBuffer = 0;
246         }
247 
248         // Save this frame until our client is interested in it
249         mBuffers[mReadyBuffer] = bufDesc;
250     }
251 
252     // Notify anybody who cares that things have changed
253     lock.unlock();
254     mSignal.notify_all();
255 
256     return Void();
257 }
258 
259 
notify(const EvsEventDesc & event)260 Return<void> StreamHandler::notify(const EvsEventDesc& event) {
261     switch(event.aType) {
262         case EvsEventType::STREAM_STOPPED:
263         {
264             {
265                 std::lock_guard<std::mutex> lock(mLock);
266 
267                 // Signal that the last frame has been received and the stream is stopped
268                 mRunning = false;
269             }
270             LOG(INFO) << "Received a STREAM_STOPPED event";
271             break;
272         }
273 
274         case EvsEventType::PARAMETER_CHANGED:
275             LOG(INFO) << "Camera parameter " << std::hex << event.payload[0]
276                       << " is set to " << event.payload[1];
277             break;
278 
279         // Below events are ignored in reference implementation.
280         case EvsEventType::STREAM_STARTED:
281         [[fallthrough]];
282         case EvsEventType::FRAME_DROPPED:
283         [[fallthrough]];
284         case EvsEventType::TIMEOUT:
285             LOG(INFO) << "Event " << std::hex << static_cast<unsigned>(event.aType)
286                       << "is received but ignored.";
287             break;
288         default:
289             LOG(ERROR) << "Unknown event id: " << static_cast<unsigned>(event.aType);
290             break;
291     }
292 
293     return Void();
294 }
295 
296