• 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 #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     if (bufferArg.memHandle.getNativeHandle() == nullptr) {
137         // Signal that the last frame has been received and the stream is stopped
138         timeToStop = true;
139     } else {
140         // Store a dimension of a received frame.
141         mFrameWidth = bufferArg.width;
142         mFrameHeight = bufferArg.height;
143 
144         // If we were given an opened display at construction time, then send the received
145         // image back down the camera.
146         if (mDisplay.get()) {
147             // Get the output buffer we'll use to display the imagery
148             BufferDesc tgtBuffer = {};
149             mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
150                                           tgtBuffer = buff;
151                                       }
152             );
153 
154             if (tgtBuffer.memHandle == nullptr) {
155                 printf("Didn't get target buffer - frame lost\n");
156                 ALOGE("Didn't get requested output buffer -- skipping this frame.");
157             } else {
158                 // Copy the contents of the of buffer.memHandle into tgtBuffer
159                 copyBufferContents(tgtBuffer, bufferArg);
160 
161                 // Send the target buffer back for display
162                 Return <EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
163                 if (!result.isOk()) {
164                     printf("HIDL error on display buffer (%s)- frame lost\n",
165                            result.description().c_str());
166                     ALOGE("Error making the remote function call.  HIDL said %s",
167                           result.description().c_str());
168                 } else if (result != EvsResult::OK) {
169                     printf("Display reported error - frame lost\n");
170                     ALOGE("We encountered error %d when returning a buffer to the display!",
171                           (EvsResult) result);
172                 } else {
173                     // Everything looks good!
174                     // Keep track so tests or watch dogs can monitor progress
175                     mLock.lock();
176                     mFramesDisplayed++;
177                     mLock.unlock();
178                 }
179             }
180         }
181 
182 
183         switch (mReturnMode) {
184         case eAutoReturn:
185             // Send the camera buffer back now that the client has seen it
186             ALOGD("Calling doneWithFrame");
187             // TODO:  Why is it that we get a HIDL crash if we pass back the cloned buffer?
188             mCamera->doneWithFrame(bufferArg);
189             break;
190         case eNoAutoReturn:
191             // Hang onto the buffer handle for now -- the client will return it explicitly later
192             mHeldBuffers.push(bufferArg);
193         }
194 
195 
196         ALOGD("Frame handling complete");
197     }
198 
199 
200     // Update our received frame count and notify anybody who cares that things have changed
201     mLock.lock();
202     if (timeToStop) {
203         mRunning = false;
204     } else {
205         mFramesReceived++;
206     }
207     mLock.unlock();
208     mSignal.notify_all();
209 
210 
211     return Void();
212 }
213 
214 
copyBufferContents(const BufferDesc & tgtBuffer,const BufferDesc & srcBuffer)215 bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
216                                       const BufferDesc& srcBuffer) {
217     bool success = true;
218 
219     // Make sure we don't run off the end of either buffer
220     const unsigned width     = std::min(tgtBuffer.width,
221                                         srcBuffer.width);
222     const unsigned height    = std::min(tgtBuffer.height,
223                                         srcBuffer.height);
224 
225     sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
226         tgtBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
227         tgtBuffer.width, tgtBuffer.height, tgtBuffer.format, 1, tgtBuffer.usage,
228         tgtBuffer.stride);
229     sp<android::GraphicBuffer> src = new android::GraphicBuffer(
230         srcBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
231         srcBuffer.width, srcBuffer.height, srcBuffer.format, 1, srcBuffer.usage,
232         srcBuffer.stride);
233 
234     // Lock our source buffer for reading (current expectation are for this to be NV21 format)
235     uint8_t* srcPixels = nullptr;
236     src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
237 
238     // Lock our target buffer for writing (should be either RGBA8888 or BGRA8888 format)
239     uint32_t* tgtPixels = nullptr;
240     tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
241 
242     if (srcPixels && tgtPixels) {
243         if (tgtBuffer.format == HAL_PIXEL_FORMAT_RGBA_8888) {
244             if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) {   // 420SP == NV21
245                 copyNV21toRGB32(width, height,
246                                 srcPixels,
247                                 tgtPixels, tgtBuffer.stride);
248             } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
249                 copyYV12toRGB32(width, height,
250                                 srcPixels,
251                                 tgtPixels, tgtBuffer.stride);
252             } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
253                 copyYUYVtoRGB32(width, height,
254                                 srcPixels, srcBuffer.stride,
255                                 tgtPixels, tgtBuffer.stride);
256             } else if (srcBuffer.format == tgtBuffer.format) {  // 32bit RGBA
257                 copyMatchedInterleavedFormats(width, height,
258                                               srcPixels, srcBuffer.stride,
259                                               tgtPixels, tgtBuffer.stride,
260                                               tgtBuffer.pixelSize);
261             } else {
262                 ALOGE("Camera buffer format is not supported");
263                 success = false;
264             }
265         } else if (tgtBuffer.format == HAL_PIXEL_FORMAT_BGRA_8888) {
266             if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) {   // 420SP == NV21
267                 copyNV21toBGR32(width, height,
268                                 srcPixels,
269                                 tgtPixels, tgtBuffer.stride);
270             } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
271                 copyYV12toBGR32(width, height,
272                                 srcPixels,
273                                 tgtPixels, tgtBuffer.stride);
274             } else if (srcBuffer.format == HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
275                 copyYUYVtoBGR32(width, height,
276                                 srcPixels, srcBuffer.stride,
277                                 tgtPixels, tgtBuffer.stride);
278             } else if (srcBuffer.format == tgtBuffer.format) {  // 32bit RGBA
279                 copyMatchedInterleavedFormats(width, height,
280                                               srcPixels, srcBuffer.stride,
281                                               tgtPixels, tgtBuffer.stride,
282                                               tgtBuffer.pixelSize);
283             } else {
284                 ALOGE("Camera buffer format is not supported");
285                 success = false;
286             }
287         } else {
288             // We always expect 32 bit RGB for the display output for now.  Is there a need for 565?
289             ALOGE("Diplay buffer is always expected to be 32bit RGBA");
290             success = false;
291         }
292     } else {
293         ALOGE("Failed to lock buffer contents for contents transfer");
294         success = false;
295     }
296 
297     if (srcPixels) {
298         src->unlock();
299     }
300     if (tgtPixels) {
301         tgt->unlock();
302     }
303 
304     return success;
305 }
306 
getFrameDimension(unsigned * width,unsigned * height)307 void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
308     if (width) {
309         *width = mFrameWidth;
310     }
311 
312     if (height) {
313         *height = mFrameHeight;
314     }
315 }
316