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