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