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 #define LOG_TAG "VtsHalEvsTest"
18
19 #include "FrameHandler.h"
20 #include "FormatConvert.h"
21
22 #include <stdio.h>
23 #include <string.h>
24
25 #include <android/log.h>
26 #include <cutils/native_handle.h>
27 #include <ui/GraphicBuffer.h>
28
29
FrameHandler(android::sp<IEvsCamera> pCamera,CameraDesc cameraInfo,android::sp<IEvsDisplay> pDisplay,BufferControlFlag mode)30 FrameHandler::FrameHandler(android::sp <IEvsCamera> pCamera, CameraDesc cameraInfo,
31 android::sp <IEvsDisplay> pDisplay,
32 BufferControlFlag mode) :
33 mCamera(pCamera),
34 mCameraInfo(cameraInfo),
35 mDisplay(pDisplay),
36 mReturnMode(mode) {
37 // Nothing but member initialization here...
38 }
39
40
shutdown()41 void FrameHandler::shutdown()
42 {
43 // Make sure we're not still streaming
44 blockingStopStream();
45
46 // At this point, the receiver thread is no longer running, so we can safely drop
47 // our remote object references so they can be freed
48 mCamera = nullptr;
49 mDisplay = nullptr;
50 }
51
52
startStream()53 bool FrameHandler::startStream() {
54 // Tell the camera to start streaming
55 Return<EvsResult> result = mCamera->startVideoStream(this);
56 if (result != EvsResult::OK) {
57 return false;
58 }
59
60 // Mark ourselves as running
61 mLock.lock();
62 mRunning = true;
63 mLock.unlock();
64
65 return true;
66 }
67
68
asyncStopStream()69 void FrameHandler::asyncStopStream() {
70 // Tell the camera to stop streaming.
71 // This will result in a null frame being delivered when the stream actually stops.
72 mCamera->stopVideoStream();
73 }
74
75
blockingStopStream()76 void FrameHandler::blockingStopStream() {
77 // Tell the stream to stop
78 asyncStopStream();
79
80 // Wait until the stream has actually stopped
81 std::unique_lock<std::mutex> lock(mLock);
82 if (mRunning) {
83 mSignal.wait(lock, [this]() { return !mRunning; });
84 }
85 }
86
87
returnHeldBuffer()88 bool FrameHandler::returnHeldBuffer() {
89 std::unique_lock<std::mutex> lock(mLock);
90
91 // Return the oldest buffer we're holding
92 if (mHeldBuffers.empty()) {
93 // No buffers are currently held
94 return false;
95 }
96
97 BufferDesc buffer = mHeldBuffers.front();
98 mHeldBuffers.pop();
99 mCamera->doneWithFrame(buffer);
100
101 return true;
102 }
103
104
isRunning()105 bool FrameHandler::isRunning() {
106 std::unique_lock<std::mutex> lock(mLock);
107 return mRunning;
108 }
109
110
waitForFrameCount(unsigned frameCount)111 void FrameHandler::waitForFrameCount(unsigned frameCount) {
112 // Wait until we've seen at least the requested number of frames (could be more)
113 std::unique_lock<std::mutex> lock(mLock);
114 mSignal.wait(lock, [this, frameCount](){ return mFramesReceived >= frameCount; });
115 }
116
117
getFramesCounters(unsigned * received,unsigned * displayed)118 void FrameHandler::getFramesCounters(unsigned* received, unsigned* displayed) {
119 std::unique_lock<std::mutex> lock(mLock);
120
121 if (received) {
122 *received = mFramesReceived;
123 }
124 if (displayed) {
125 *displayed = mFramesDisplayed;
126 }
127 }
128
129
deliverFrame(const BufferDesc & bufferArg)130 Return<void> FrameHandler::deliverFrame(const BufferDesc& bufferArg) {
131 ALOGD("Received a frame from the camera (%p)", bufferArg.memHandle.getNativeHandle());
132
133 // Local flag we use to keep track of when the stream is stopping
134 bool timeToStop = false;
135
136 // Another local flag telling whether or not current frame is displayed.
137 bool frameDisplayed = false;
138
139 if (bufferArg.memHandle.getNativeHandle() == nullptr) {
140 // Signal that the last frame has been received and the stream is stopped
141 timeToStop = true;
142 } else {
143 // Store a dimension of a received frame.
144 mFrameWidth = bufferArg.width;
145 mFrameHeight = bufferArg.height;
146
147 // If we were given an opened display at construction time, then send the received
148 // image back down the camera.
149 if (mDisplay.get()) {
150 // Get the output buffer we'll use to display the imagery
151 BufferDesc tgtBuffer = {};
152 mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
153 tgtBuffer = buff;
154 }
155 );
156
157 if (tgtBuffer.memHandle == nullptr) {
158 printf("Didn't get target buffer - frame lost\n");
159 ALOGE("Didn't get requested output buffer -- skipping this frame.");
160 } else {
161 // Copy the contents of the of buffer.memHandle into tgtBuffer
162 copyBufferContents(tgtBuffer, bufferArg);
163
164 // Send the target buffer back for display
165 Return <EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
166 if (!result.isOk()) {
167 printf("HIDL error on display buffer (%s)- frame lost\n",
168 result.description().c_str());
169 ALOGE("Error making the remote function call. HIDL said %s",
170 result.description().c_str());
171 } else if (result != EvsResult::OK) {
172 printf("Display reported error - frame lost\n");
173 ALOGE("We encountered error %d when returning a buffer to the display!",
174 (EvsResult) result);
175 } else {
176 // Everything looks good!
177 // Keep track so tests or watch dogs can monitor progress
178 frameDisplayed = true;
179 }
180 }
181 }
182
183
184 switch (mReturnMode) {
185 case eAutoReturn:
186 // Send the camera buffer back now that the client has seen it
187 ALOGD("Calling doneWithFrame");
188 // TODO: Why is it that we get a HIDL crash if we pass back the cloned buffer?
189 mCamera->doneWithFrame(bufferArg);
190 break;
191 case eNoAutoReturn:
192 // Hang onto the buffer handle for now -- the client will return it explicitly later
193 mHeldBuffers.push(bufferArg);
194 }
195
196
197 ALOGD("Frame handling complete");
198 }
199
200
201 // Update frame counters and notify anybody who cares that things have changed.
202 mLock.lock();
203 if (timeToStop) {
204 mRunning = false;
205 } else {
206 mFramesReceived++;
207 if (frameDisplayed) {
208 mFramesDisplayed++;
209 }
210 }
211 mLock.unlock();
212 mSignal.notify_all();
213
214
215 return Void();
216 }
217
218
copyBufferContents(const BufferDesc & tgtBuffer,const BufferDesc & srcBuffer)219 bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
220 const BufferDesc& srcBuffer) {
221 bool success = true;
222
223 // Make sure we don't run off the end of either buffer
224 const unsigned width = std::min(tgtBuffer.width,
225 srcBuffer.width);
226 const unsigned height = std::min(tgtBuffer.height,
227 srcBuffer.height);
228
229 sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
230 tgtBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
231 tgtBuffer.width, tgtBuffer.height, tgtBuffer.format, 1, tgtBuffer.usage,
232 tgtBuffer.stride);
233 sp<android::GraphicBuffer> src = new android::GraphicBuffer(
234 srcBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
235 srcBuffer.width, srcBuffer.height, srcBuffer.format, 1, srcBuffer.usage,
236 srcBuffer.stride);
237
238 // Lock our source buffer for reading (current expectation are for this to be NV21 format)
239 uint8_t* srcPixels = nullptr;
240 src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
241
242 // Lock our target buffer for writing (should be either RGBA8888 or BGRA8888 format)
243 uint32_t* tgtPixels = nullptr;
244 tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
245
246 if (srcPixels && tgtPixels) {
247 using namespace ::android::hardware::automotive::evs::common;
248 if (tgtBuffer.format == HAL_PIXEL_FORMAT_RGBA_8888) {
249 if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21
250 Utils::copyNV21toRGB32(width, height,
251 srcPixels,
252 tgtPixels, tgtBuffer.stride);
253 } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
254 Utils::copyYV12toRGB32(width, height,
255 srcPixels,
256 tgtPixels, tgtBuffer.stride);
257 } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
258 Utils::copyYUYVtoRGB32(width, height,
259 srcPixels, srcBuffer.stride,
260 tgtPixels, tgtBuffer.stride);
261 } else if (srcBuffer.format == tgtBuffer.format) { // 32bit RGBA
262 Utils::copyMatchedInterleavedFormats(width, height,
263 srcPixels, srcBuffer.stride,
264 tgtPixels, tgtBuffer.stride,
265 tgtBuffer.pixelSize);
266 } else {
267 ALOGE("Camera buffer format is not supported");
268 success = false;
269 }
270 } else if (tgtBuffer.format == HAL_PIXEL_FORMAT_BGRA_8888) {
271 if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21
272 Utils::copyNV21toBGR32(width, height,
273 srcPixels,
274 tgtPixels, tgtBuffer.stride);
275 } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
276 Utils::copyYV12toBGR32(width, height,
277 srcPixels,
278 tgtPixels, tgtBuffer.stride);
279 } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
280 Utils::copyYUYVtoBGR32(width, height,
281 srcPixels, srcBuffer.stride,
282 tgtPixels, tgtBuffer.stride);
283 } else if (srcBuffer.format == tgtBuffer.format) { // 32bit RGBA
284 Utils::copyMatchedInterleavedFormats(width, height,
285 srcPixels, srcBuffer.stride,
286 tgtPixels, tgtBuffer.stride,
287 tgtBuffer.pixelSize);
288 } else {
289 ALOGE("Camera buffer format is not supported");
290 success = false;
291 }
292 } else {
293 // We always expect 32 bit RGB for the display output for now. Is there a need for 565?
294 ALOGE("Diplay buffer is always expected to be 32bit RGBA");
295 success = false;
296 }
297 } else {
298 ALOGE("Failed to lock buffer contents for contents transfer");
299 success = false;
300 }
301
302 if (srcPixels) {
303 src->unlock();
304 }
305 if (tgtPixels) {
306 tgt->unlock();
307 }
308
309 return success;
310 }
311
getFrameDimension(unsigned * width,unsigned * height)312 void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
313 if (width) {
314 *width = mFrameWidth;
315 }
316
317 if (height) {
318 *height = mFrameHeight;
319 }
320 }
321