1 /*
2  * Copyright (C) 2016 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 "EvsV4lCamera.h"
18 #include "EvsEnumerator.h"
19 #include "bufferCopy.h"
20 
21 #include <android/hardware_buffer.h>
22 #include <android-base/logging.h>
23 #include <ui/GraphicBufferAllocator.h>
24 #include <ui/GraphicBufferMapper.h>
25 #include <utils/SystemClock.h>
26 
27 
28 namespace android {
29 namespace hardware {
30 namespace automotive {
31 namespace evs {
32 namespace V1_1 {
33 namespace implementation {
34 
35 // Default camera output image resolution
36 const std::array<int32_t, 2> kDefaultResolution = {640, 480};
37 
38 // Arbitrary limit on number of graphics buffers allowed to be allocated
39 // Safeguards against unreasonable resource consumption and provides a testable limit
40 static const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
41 
EvsV4lCamera(const char * deviceName,unique_ptr<ConfigManager::CameraInfo> & camInfo)42 EvsV4lCamera::EvsV4lCamera(const char *deviceName,
43                            unique_ptr<ConfigManager::CameraInfo> &camInfo) :
44         mFramesAllowed(0),
45         mFramesInUse(0),
46         mCameraInfo(camInfo) {
47     LOG(DEBUG) << "EvsV4lCamera instantiated";
48 
49     mDescription.v1.cameraId = deviceName;
50     if (camInfo != nullptr) {
51         mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
52                                             get_camera_metadata_size(camInfo->characteristics));
53     }
54 
55     // Default output buffer format.
56     mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
57 
58     // How we expect to use the gralloc buffers we'll exchange with our client
59     mUsage  = GRALLOC_USAGE_HW_TEXTURE     |
60               GRALLOC_USAGE_SW_READ_RARELY |
61               GRALLOC_USAGE_SW_WRITE_OFTEN;
62 }
63 
64 
~EvsV4lCamera()65 EvsV4lCamera::~EvsV4lCamera() {
66     LOG(DEBUG) << "EvsV4lCamera being destroyed";
67     shutdown();
68 }
69 
70 
71 //
72 // This gets called if another caller "steals" ownership of the camera
73 //
shutdown()74 void EvsV4lCamera::shutdown()
75 {
76     LOG(DEBUG) << "EvsV4lCamera shutdown";
77 
78     // Make sure our output stream is cleaned up
79     // (It really should be already)
80     stopVideoStream();
81 
82     // Note:  Since stopVideoStream is blocking, no other threads can now be running
83 
84     // Close our video capture device
85     mVideo.close();
86 
87     // Drop all the graphics buffers we've been using
88     if (mBuffers.size() > 0) {
89         GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
90         for (auto&& rec : mBuffers) {
91             if (rec.inUse) {
92                 LOG(WARNING) << "Releasing buffer despite remote ownership";
93             }
94             alloc.free(rec.handle);
95             rec.handle = nullptr;
96         }
97         mBuffers.clear();
98     }
99 }
100 
101 
102 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
getCameraInfo(getCameraInfo_cb _hidl_cb)103 Return<void> EvsV4lCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
104     LOG(DEBUG) << __FUNCTION__;
105 
106     // Send back our self description
107     _hidl_cb(mDescription.v1);
108     return Void();
109 }
110 
111 
setMaxFramesInFlight(uint32_t bufferCount)112 Return<EvsResult> EvsV4lCamera::setMaxFramesInFlight(uint32_t bufferCount) {
113     LOG(DEBUG) << __FUNCTION__;
114     std::lock_guard<std::mutex> lock(mAccessLock);
115 
116     // If we've been displaced by another owner of the camera, then we can't do anything else
117     if (!mVideo.isOpen()) {
118         LOG(WARNING) << "Ignoring setMaxFramesInFlight call when camera has been lost.";
119         return EvsResult::OWNERSHIP_LOST;
120     }
121 
122     // We cannot function without at least one video buffer to send data
123     if (bufferCount < 1) {
124         LOG(ERROR) << "Ignoring setMaxFramesInFlight with less than one buffer requested";
125         return EvsResult::INVALID_ARG;
126     }
127 
128     // Update our internal state
129     if (setAvailableFrames_Locked(bufferCount)) {
130         return EvsResult::OK;
131     } else {
132         return EvsResult::BUFFER_NOT_AVAILABLE;
133     }
134 }
135 
136 
startVideoStream(const sp<IEvsCameraStream_1_0> & stream)137 Return<EvsResult> EvsV4lCamera::startVideoStream(const sp<IEvsCameraStream_1_0>& stream)  {
138     LOG(DEBUG) << __FUNCTION__;
139     std::lock_guard<std::mutex> lock(mAccessLock);
140 
141     // If we've been displaced by another owner of the camera, then we can't do anything else
142     if (!mVideo.isOpen()) {
143         LOG(WARNING) << "Ignoring startVideoStream call when camera has been lost.";
144         return EvsResult::OWNERSHIP_LOST;
145     }
146     if (mStream.get() != nullptr) {
147         LOG(ERROR) << "Ignoring startVideoStream call when a stream is already running.";
148         return EvsResult::STREAM_ALREADY_RUNNING;
149     }
150 
151     // If the client never indicated otherwise, configure ourselves for a single streaming buffer
152     if (mFramesAllowed < 1) {
153         if (!setAvailableFrames_Locked(1)) {
154             LOG(ERROR) << "Failed to start stream because we couldn't get a graphics buffer";
155             return EvsResult::BUFFER_NOT_AVAILABLE;
156         }
157     }
158 
159     // Choose which image transfer function we need
160     // Map from V4L2 to Android graphic buffer format
161     const uint32_t videoSrcFormat = mVideo.getV4LFormat();
162     LOG(INFO) << "Configuring to accept " << (char*)&videoSrcFormat
163               << " camera data and convert to " << std::hex << mFormat;
164 
165     switch (mFormat) {
166     case HAL_PIXEL_FORMAT_YCRCB_420_SP:
167         switch (videoSrcFormat) {
168         case V4L2_PIX_FMT_NV21:     mFillBufferFromVideo = fillNV21FromNV21;    break;
169         case V4L2_PIX_FMT_YUYV:     mFillBufferFromVideo = fillNV21FromYUYV;    break;
170         default:
171             LOG(ERROR) << "Unhandled camera output format: "
172                        << ((char*)&videoSrcFormat)[0]
173                        << ((char*)&videoSrcFormat)[1]
174                        << ((char*)&videoSrcFormat)[2]
175                        << ((char*)&videoSrcFormat)[3]
176                        << std::hex << videoSrcFormat;
177         }
178         break;
179     case HAL_PIXEL_FORMAT_RGBA_8888:
180         switch (videoSrcFormat) {
181         case V4L2_PIX_FMT_YUYV:     mFillBufferFromVideo = fillRGBAFromYUYV;    break;
182         default:
183             LOG(ERROR) << "Unhandled camera format " << (char*)&videoSrcFormat;
184         }
185         break;
186     case HAL_PIXEL_FORMAT_YCBCR_422_I:
187         switch (videoSrcFormat) {
188         case V4L2_PIX_FMT_YUYV:     mFillBufferFromVideo = fillYUYVFromYUYV;    break;
189         case V4L2_PIX_FMT_UYVY:     mFillBufferFromVideo = fillYUYVFromUYVY;    break;
190         default:
191             LOG(ERROR) << "Unhandled camera format " << (char*)&videoSrcFormat;
192         }
193         break;
194     default:
195         LOG(ERROR) << "Unhandled camera format " << (char*)&mFormat;
196     }
197 
198 
199     // Record the user's callback for use when we have a frame ready
200     mStream = stream;
201     mStream_1_1 = IEvsCameraStream_1_1::castFrom(mStream).withDefault(nullptr);
202 
203     // Set up the video stream with a callback to our member function forwardFrame()
204     if (!mVideo.startStream([this](VideoCapture*, imageBuffer* tgt, void* data) {
205                                 this->forwardFrame(tgt, data);
206                             })
207     ) {
208         // No need to hold onto this if we failed to start
209         mStream = nullptr;
210         mStream_1_1 = nullptr;
211         LOG(ERROR) << "Underlying camera start stream failed";
212         return EvsResult::UNDERLYING_SERVICE_ERROR;
213     }
214 
215     return EvsResult::OK;
216 }
217 
218 
doneWithFrame(const BufferDesc_1_0 & buffer)219 Return<void> EvsV4lCamera::doneWithFrame(const BufferDesc_1_0& buffer)  {
220     LOG(DEBUG) << __FUNCTION__;
221     doneWithFrame_impl(buffer.bufferId, buffer.memHandle);
222 
223     return Void();
224 }
225 
226 
stopVideoStream()227 Return<void> EvsV4lCamera::stopVideoStream()  {
228     LOG(DEBUG) << __FUNCTION__;
229 
230     // Tell the capture device to stop (and block until it does)
231     mVideo.stopStream();
232 
233     if (mStream_1_1 != nullptr) {
234         // V1.1 client is waiting on STREAM_STOPPED event.
235         std::unique_lock <std::mutex> lock(mAccessLock);
236 
237         EvsEventDesc event;
238         event.aType = EvsEventType::STREAM_STOPPED;
239         auto result = mStream_1_1->notify(event);
240         if (!result.isOk()) {
241             LOG(ERROR) << "Error delivering end of stream event";
242         }
243 
244         // Drop our reference to the client's stream receiver
245         mStream_1_1 = nullptr;
246         mStream     = nullptr;
247     } else if (mStream != nullptr) {
248         std::unique_lock <std::mutex> lock(mAccessLock);
249 
250         // Send one last NULL frame to signal the actual end of stream
251         BufferDesc_1_0 nullBuff = {};
252         auto result = mStream->deliverFrame(nullBuff);
253         if (!result.isOk()) {
254             LOG(ERROR) << "Error delivering end of stream marker";
255         }
256 
257         // Drop our reference to the client's stream receiver
258         mStream = nullptr;
259     }
260 
261     return Void();
262 }
263 
264 
getExtendedInfo(uint32_t)265 Return<int32_t> EvsV4lCamera::getExtendedInfo(uint32_t /*opaqueIdentifier*/)  {
266     LOG(DEBUG) << __FUNCTION__;
267     // Return zero by default as required by the spec
268     return 0;
269 }
270 
271 
setExtendedInfo(uint32_t,int32_t)272 Return<EvsResult> EvsV4lCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/,
273                                                 int32_t  /*opaqueValue*/)  {
274     LOG(DEBUG) << __FUNCTION__;
275     std::lock_guard<std::mutex> lock(mAccessLock);
276 
277     // If we've been displaced by another owner of the camera, then we can't do anything else
278     if (!mVideo.isOpen()) {
279         LOG(WARNING) << "Ignoring setExtendedInfo call when camera has been lost.";
280         return EvsResult::OWNERSHIP_LOST;
281     }
282 
283     // We don't store any device specific information in this implementation
284     return EvsResult::INVALID_ARG;
285 }
286 
287 
288 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb)289 Return<void> EvsV4lCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
290     LOG(DEBUG) << __FUNCTION__;
291 
292     // Send back our self description
293     _hidl_cb(mDescription);
294     return Void();
295 }
296 
297 
getPhysicalCameraInfo(const hidl_string & id,getPhysicalCameraInfo_cb _hidl_cb)298 Return<void> EvsV4lCamera::getPhysicalCameraInfo(const hidl_string& id,
299                                                  getPhysicalCameraInfo_cb _hidl_cb) {
300     LOG(DEBUG) << __FUNCTION__;
301 
302     // This method works exactly same as getCameraInfo_1_1() in EVS HW module.
303     (void)id;
304     _hidl_cb(mDescription);
305     return Void();
306 }
307 
308 
doneWithFrame_1_1(const hidl_vec<BufferDesc_1_1> & buffers)309 Return<EvsResult> EvsV4lCamera::doneWithFrame_1_1(const hidl_vec<BufferDesc_1_1>& buffers)  {
310     LOG(DEBUG) << __FUNCTION__;
311 
312     for (auto&& buffer : buffers) {
313         doneWithFrame_impl(buffer.bufferId, buffer.buffer.nativeHandle);
314     }
315 
316     return EvsResult::OK;
317 }
318 
319 
pauseVideoStream()320 Return<EvsResult> EvsV4lCamera::pauseVideoStream() {
321     return EvsResult::UNDERLYING_SERVICE_ERROR;
322 }
323 
324 
resumeVideoStream()325 Return<EvsResult> EvsV4lCamera::resumeVideoStream() {
326     return EvsResult::UNDERLYING_SERVICE_ERROR;
327 }
328 
329 
setMaster()330 Return<EvsResult> EvsV4lCamera::setMaster() {
331     /* Because EVS HW module reference implementation expects a single client at
332      * a time, this returns a success code always.
333      */
334     return EvsResult::OK;
335 }
336 
337 
forceMaster(const sp<IEvsDisplay_1_0> &)338 Return<EvsResult> EvsV4lCamera::forceMaster(const sp<IEvsDisplay_1_0>&) {
339     /* Because EVS HW module reference implementation expects a single client at
340      * a time, this returns a success code always.
341      */
342     return EvsResult::OK;
343 }
344 
345 
unsetMaster()346 Return<EvsResult> EvsV4lCamera::unsetMaster() {
347     /* Because EVS HW module reference implementation expects a single client at
348      * a time, there is no chance that this is called by a non-master client and
349      * therefore returns a success code always.
350      */
351     return EvsResult::OK;
352 }
353 
354 
getParameterList(getParameterList_cb _hidl_cb)355 Return<void> EvsV4lCamera::getParameterList(getParameterList_cb _hidl_cb) {
356     hidl_vec<CameraParam> hidlCtrls;
357     if (mCameraInfo != nullptr) {
358         hidlCtrls.resize(mCameraInfo->controls.size());
359         unsigned idx = 0;
360         for (auto& [cid, range]: mCameraInfo->controls) {
361             hidlCtrls[idx++] = cid;
362         }
363     }
364 
365     _hidl_cb(hidlCtrls);
366     return Void();
367 }
368 
369 
getIntParameterRange(CameraParam id,getIntParameterRange_cb _hidl_cb)370 Return<void> EvsV4lCamera::getIntParameterRange(CameraParam id,
371                                                 getIntParameterRange_cb _hidl_cb) {
372     if (mCameraInfo != nullptr) {
373         auto range = mCameraInfo->controls[id];
374         _hidl_cb(get<0>(range), get<1>(range), get<2>(range));
375     } else {
376         _hidl_cb(0, 0, 0);
377     }
378 
379     return Void();
380 }
381 
382 
setIntParameter(CameraParam id,int32_t value,setIntParameter_cb _hidl_cb)383 Return<void> EvsV4lCamera::setIntParameter(CameraParam id, int32_t value,
384                                            setIntParameter_cb _hidl_cb) {
385     uint32_t v4l2cid = V4L2_CID_BASE;
386     hidl_vec<int32_t> values;
387     values.resize(1);
388     if (!convertToV4l2CID(id, v4l2cid)) {
389         _hidl_cb(EvsResult::INVALID_ARG, values);
390     } else {
391         EvsResult result = EvsResult::OK;
392         v4l2_control control = {v4l2cid, value};
393         if (mVideo.setParameter(control) < 0 ||
394             mVideo.getParameter(control) < 0) {
395             result = EvsResult::UNDERLYING_SERVICE_ERROR;
396         }
397 
398         values[0] = control.value;
399         _hidl_cb(result, values);
400     }
401 
402     return Void();
403 }
404 
405 
getIntParameter(CameraParam id,getIntParameter_cb _hidl_cb)406 Return<void> EvsV4lCamera::getIntParameter(CameraParam id,
407                                            getIntParameter_cb _hidl_cb) {
408     uint32_t v4l2cid = V4L2_CID_BASE;
409     hidl_vec<int32_t> values;
410     values.resize(1);
411     if (!convertToV4l2CID(id, v4l2cid)) {
412         _hidl_cb(EvsResult::INVALID_ARG, values);
413     } else {
414         EvsResult result = EvsResult::OK;
415         v4l2_control control = {v4l2cid, 0};
416         if (mVideo.getParameter(control) < 0) {
417             result = EvsResult::INVALID_ARG;
418         }
419 
420         // Report a result
421         values[0] = control.value;
422         _hidl_cb(result, values);
423     }
424 
425     return Void();
426 }
427 
428 
setExtendedInfo_1_1(uint32_t opaqueIdentifier,const hidl_vec<uint8_t> & opaqueValue)429 Return<EvsResult> EvsV4lCamera::setExtendedInfo_1_1(uint32_t opaqueIdentifier,
430                                                     const hidl_vec<uint8_t>& opaqueValue) {
431     mExtInfo.insert_or_assign(opaqueIdentifier, opaqueValue);
432     return EvsResult::OK;
433 }
434 
435 
getExtendedInfo_1_1(uint32_t opaqueIdentifier,getExtendedInfo_1_1_cb _hidl_cb)436 Return<void> EvsV4lCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
437                                                getExtendedInfo_1_1_cb _hidl_cb) {
438     const auto it = mExtInfo.find(opaqueIdentifier);
439     hidl_vec<uint8_t> value;
440     auto status = EvsResult::OK;
441     if (it == mExtInfo.end()) {
442         status = EvsResult::INVALID_ARG;
443     } else {
444         value = mExtInfo[opaqueIdentifier];
445     }
446 
447     _hidl_cb(status, value);
448     return Void();
449 }
450 
451 
452 Return<void>
importExternalBuffers(const hidl_vec<BufferDesc_1_1> & buffers,importExternalBuffers_cb _hidl_cb)453 EvsV4lCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
454                                     importExternalBuffers_cb _hidl_cb) {
455     LOG(DEBUG) << __FUNCTION__;
456 
457     // If we've been displaced by another owner of the camera, then we can't do anything else
458     if (!mVideo.isOpen()) {
459         LOG(WARNING) << "Ignoring a request add external buffers "
460                      << "when camera has been lost.";
461         _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, mFramesAllowed);
462         return {};
463     }
464 
465     auto numBuffersToAdd = buffers.size();
466     if (numBuffersToAdd < 1) {
467         LOG(DEBUG) << "No buffers to add.";
468         _hidl_cb(EvsResult::OK, mFramesAllowed);
469         return {};
470     }
471 
472     {
473         std::scoped_lock<std::mutex> lock(mAccessLock);
474 
475         if (numBuffersToAdd > (MAX_BUFFERS_IN_FLIGHT - mFramesAllowed)) {
476             numBuffersToAdd -= (MAX_BUFFERS_IN_FLIGHT - mFramesAllowed);
477             LOG(WARNING) << "Exceed the limit on number of buffers.  "
478                          << numBuffersToAdd << " buffers will be added only.";
479         }
480 
481         GraphicBufferMapper& mapper = GraphicBufferMapper::get();
482         const auto before = mFramesAllowed;
483         for (auto i = 0; i < numBuffersToAdd; ++i) {
484             // TODO: reject if external buffer is configured differently.
485             auto& b = buffers[i];
486             const AHardwareBuffer_Desc* pDesc =
487                 reinterpret_cast<const AHardwareBuffer_Desc *>(&b.buffer.description);
488 
489             // Import a buffer to add
490             buffer_handle_t memHandle = nullptr;
491             status_t result = mapper.importBuffer(b.buffer.nativeHandle,
492                                                   pDesc->width,
493                                                   pDesc->height,
494                                                   1,
495                                                   pDesc->format,
496                                                   pDesc->usage,
497                                                   pDesc->stride,
498                                                   &memHandle);
499             if (result != android::NO_ERROR || !memHandle) {
500                 LOG(WARNING) << "Failed to import a buffer " << b.bufferId;
501                 continue;
502             }
503 
504             auto stored = false;
505             for (auto&& rec : mBuffers) {
506                 if (rec.handle == nullptr) {
507                     // Use this existing entry
508                     rec.handle = memHandle;
509                     rec.inUse = false;
510 
511                     stored = true;
512                     break;
513                 }
514             }
515 
516             if (!stored) {
517                 // Add a BufferRecord wrapping this handle to our set of available buffers
518                 mBuffers.emplace_back(memHandle);
519             }
520 
521             ++mFramesAllowed;
522         }
523 
524         _hidl_cb(EvsResult::OK, mFramesAllowed - before);
525         return {};
526     }
527 }
528 
529 
doneWithFrame_impl(const uint32_t bufferId,const buffer_handle_t memHandle)530 EvsResult EvsV4lCamera::doneWithFrame_impl(const uint32_t bufferId,
531                                            const buffer_handle_t memHandle) {
532     std::lock_guard <std::mutex> lock(mAccessLock);
533 
534     // If we've been displaced by another owner of the camera, then we can't do anything else
535     if (!mVideo.isOpen()) {
536         LOG(WARNING) << "Ignoring doneWithFrame call when camera has been lost.";
537     } else {
538         if (memHandle == nullptr) {
539             LOG(ERROR) << "Ignoring doneWithFrame called with null handle";
540         } else if (bufferId >= mBuffers.size()) {
541             LOG(ERROR) << "Ignoring doneWithFrame called with invalid bufferId " << bufferId
542                        << " (max is " << mBuffers.size() - 1 << ")";
543         } else if (!mBuffers[bufferId].inUse) {
544             LOG(ERROR) << "Ignoring doneWithFrame called on frame " << bufferId
545                        << " which is already free";
546         } else {
547             // Mark the frame as available
548             mBuffers[bufferId].inUse = false;
549             mFramesInUse--;
550 
551             // If this frame's index is high in the array, try to move it down
552             // to improve locality after mFramesAllowed has been reduced.
553             if (bufferId >= mFramesAllowed) {
554                 // Find an empty slot lower in the array (which should always exist in this case)
555                 for (auto&& rec : mBuffers) {
556                     if (rec.handle == nullptr) {
557                         rec.handle = mBuffers[bufferId].handle;
558                         mBuffers[bufferId].handle = nullptr;
559                         break;
560                     }
561                 }
562             }
563         }
564     }
565 
566     return EvsResult::OK;
567 }
568 
569 
setAvailableFrames_Locked(unsigned bufferCount)570 bool EvsV4lCamera::setAvailableFrames_Locked(unsigned bufferCount) {
571     if (bufferCount < 1) {
572         LOG(ERROR) << "Ignoring request to set buffer count to zero";
573         return false;
574     }
575     if (bufferCount > MAX_BUFFERS_IN_FLIGHT) {
576         LOG(ERROR) << "Rejecting buffer request in excess of internal limit";
577         return false;
578     }
579 
580     // Is an increase required?
581     if (mFramesAllowed < bufferCount) {
582         // An increase is required
583         unsigned needed = bufferCount - mFramesAllowed;
584         LOG(INFO) << "Allocating " << needed << " buffers for camera frames";
585 
586         unsigned added = increaseAvailableFrames_Locked(needed);
587         if (added != needed) {
588             // If we didn't add all the frames we needed, then roll back to the previous state
589             LOG(ERROR) << "Rolling back to previous frame queue size";
590             decreaseAvailableFrames_Locked(added);
591             return false;
592         }
593     } else if (mFramesAllowed > bufferCount) {
594         // A decrease is required
595         unsigned framesToRelease = mFramesAllowed - bufferCount;
596         LOG(INFO) << "Returning " << framesToRelease << " camera frame buffers";
597 
598         unsigned released = decreaseAvailableFrames_Locked(framesToRelease);
599         if (released != framesToRelease) {
600             // This shouldn't happen with a properly behaving client because the client
601             // should only make this call after returning sufficient outstanding buffers
602             // to allow a clean resize.
603             LOG(ERROR) << "Buffer queue shrink failed -- too many buffers currently in use?";
604         }
605     }
606 
607     return true;
608 }
609 
610 
increaseAvailableFrames_Locked(unsigned numToAdd)611 unsigned EvsV4lCamera::increaseAvailableFrames_Locked(unsigned numToAdd) {
612     // Acquire the graphics buffer allocator
613     GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
614 
615     unsigned added = 0;
616 
617 
618     while (added < numToAdd) {
619         unsigned pixelsPerLine;
620         buffer_handle_t memHandle = nullptr;
621         status_t result = alloc.allocate(mVideo.getWidth(), mVideo.getHeight(),
622                                          mFormat, 1,
623                                          mUsage,
624                                          &memHandle, &pixelsPerLine, 0, "EvsV4lCamera");
625         if (result != NO_ERROR) {
626             LOG(ERROR) << "Error " << result << " allocating "
627                        << mVideo.getWidth() << " x " << mVideo.getHeight()
628                        << " graphics buffer";
629             break;
630         }
631         if (!memHandle) {
632             LOG(ERROR) << "We didn't get a buffer handle back from the allocator";
633             break;
634         }
635         if (mStride) {
636             if (mStride != pixelsPerLine) {
637                 LOG(ERROR) << "We did not expect to get buffers with different strides!";
638             }
639         } else {
640             // Gralloc defines stride in terms of pixels per line
641             mStride = pixelsPerLine;
642         }
643 
644         // Find a place to store the new buffer
645         bool stored = false;
646         for (auto&& rec : mBuffers) {
647             if (rec.handle == nullptr) {
648                 // Use this existing entry
649                 rec.handle = memHandle;
650                 rec.inUse = false;
651                 stored = true;
652                 break;
653             }
654         }
655         if (!stored) {
656             // Add a BufferRecord wrapping this handle to our set of available buffers
657             mBuffers.emplace_back(memHandle);
658         }
659 
660         mFramesAllowed++;
661         added++;
662     }
663 
664     return added;
665 }
666 
667 
decreaseAvailableFrames_Locked(unsigned numToRemove)668 unsigned EvsV4lCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) {
669     // Acquire the graphics buffer allocator
670     GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
671 
672     unsigned removed = 0;
673 
674     for (auto&& rec : mBuffers) {
675         // Is this record not in use, but holding a buffer that we can free?
676         if ((rec.inUse == false) && (rec.handle != nullptr)) {
677             // Release buffer and update the record so we can recognize it as "empty"
678             alloc.free(rec.handle);
679             rec.handle = nullptr;
680 
681             mFramesAllowed--;
682             removed++;
683 
684             if (removed == numToRemove) {
685                 break;
686             }
687         }
688     }
689 
690     return removed;
691 }
692 
693 
694 // This is the async callback from the video camera that tells us a frame is ready
forwardFrame(imageBuffer * pV4lBuff,void * pData)695 void EvsV4lCamera::forwardFrame(imageBuffer* pV4lBuff, void* pData) {
696     bool readyForFrame = false;
697     size_t idx = 0;
698 
699     // Lock scope for updating shared state
700     {
701         std::lock_guard<std::mutex> lock(mAccessLock);
702 
703         // Are we allowed to issue another buffer?
704         if (mFramesInUse >= mFramesAllowed) {
705             // Can't do anything right now -- skip this frame
706             LOG(WARNING) << "Skipped a frame because too many are in flight";
707         } else {
708             // Identify an available buffer to fill
709             for (idx = 0; idx < mBuffers.size(); idx++) {
710                 if (!mBuffers[idx].inUse) {
711                     if (mBuffers[idx].handle != nullptr) {
712                         // Found an available record, so stop looking
713                         break;
714                     }
715                 }
716             }
717             if (idx >= mBuffers.size()) {
718                 // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed
719                 LOG(ERROR) << "Failed to find an available buffer slot";
720             } else {
721                 // We're going to make the frame busy
722                 mBuffers[idx].inUse = true;
723                 mFramesInUse++;
724                 readyForFrame = true;
725             }
726         }
727     }
728 
729     if (!readyForFrame) {
730         // We need to return the video buffer so it can capture a new frame
731         mVideo.markFrameConsumed();
732     } else {
733         // Assemble the buffer description we'll transmit below
734         BufferDesc_1_1 bufDesc_1_1 = {};
735         AHardwareBuffer_Desc* pDesc =
736             reinterpret_cast<AHardwareBuffer_Desc *>(&bufDesc_1_1.buffer.description);
737         pDesc->width  = mVideo.getWidth();
738         pDesc->height = mVideo.getHeight();
739         pDesc->layers = 1;
740         pDesc->format = mFormat;
741         pDesc->usage  = mUsage;
742         pDesc->stride = mStride;
743         bufDesc_1_1.buffer.nativeHandle = mBuffers[idx].handle;
744         bufDesc_1_1.bufferId = idx;
745         bufDesc_1_1.deviceId = mDescription.v1.cameraId;
746         // timestamp in microseconds.
747         bufDesc_1_1.timestamp =
748             pV4lBuff->timestamp.tv_sec * 1e+6 + pV4lBuff->timestamp.tv_usec;
749 
750         // Lock our output buffer for writing
751         // TODO(b/145459970): Sometimes, physical camera device maps a buffer
752         // into the address that is about to be unmapped by another device; this
753         // causes SEGV_MAPPER.
754         void *targetPixels = nullptr;
755         GraphicBufferMapper &mapper = GraphicBufferMapper::get();
756         status_t result =
757             mapper.lock(bufDesc_1_1.buffer.nativeHandle,
758                         GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
759                         android::Rect(pDesc->width, pDesc->height),
760                         (void **)&targetPixels);
761 
762         // If we failed to lock the pixel buffer, we're about to crash, but log it first
763         if (!targetPixels) {
764             // TODO(b/145457727): When EvsHidlTest::CameraToDisplayRoundTrip
765             // test case was repeatedly executed, EVS occasionally fails to map
766             // a buffer.
767             LOG(ERROR) << "Camera failed to gain access to image buffer for writing - "
768                        << " status: " << statusToString(result)
769                        << " , error: " << strerror(errno);
770         }
771 
772         // Transfer the video image into the output buffer, making any needed
773         // format conversion along the way
774         mFillBufferFromVideo(bufDesc_1_1, (uint8_t *)targetPixels, pData, mVideo.getStride());
775 
776         // Unlock the output buffer
777         mapper.unlock(bufDesc_1_1.buffer.nativeHandle);
778 
779         // Give the video frame back to the underlying device for reuse
780         // Note that we do this before making the client callback to give the
781         // underlying camera more time to capture the next frame
782         mVideo.markFrameConsumed();
783 
784         // Issue the (asynchronous) callback to the client -- can't be holding
785         // the lock
786         bool flag = false;
787         if (mStream_1_1 != nullptr) {
788             hidl_vec<BufferDesc_1_1> frames;
789             frames.resize(1);
790             frames[0] = bufDesc_1_1;
791             auto result = mStream_1_1->deliverFrame_1_1(frames);
792             flag = result.isOk();
793         } else {
794             BufferDesc_1_0 bufDesc_1_0 = {
795                 pDesc->width,
796                 pDesc->height,
797                 pDesc->stride,
798                 bufDesc_1_1.pixelSize,
799                 static_cast<uint32_t>(pDesc->format),
800                 static_cast<uint32_t>(pDesc->usage),
801                 bufDesc_1_1.bufferId,
802                 bufDesc_1_1.buffer.nativeHandle
803             };
804 
805             auto result = mStream->deliverFrame(bufDesc_1_0);
806             flag = result.isOk();
807         }
808 
809         if (flag) {
810             LOG(DEBUG) << "Delivered " << bufDesc_1_1.buffer.nativeHandle.getNativeHandle()
811                        << " as id " << bufDesc_1_1.bufferId;
812         } else {
813             // This can happen if the client dies and is likely unrecoverable.
814             // To avoid consuming resources generating failing calls, we stop sending
815             // frames.  Note, however, that the stream remains in the "STREAMING" state
816             // until cleaned up on the main thread.
817             LOG(ERROR) << "Frame delivery call failed in the transport layer.";
818 
819             // Since we didn't actually deliver it, mark the frame as available
820             std::lock_guard<std::mutex> lock(mAccessLock);
821             mBuffers[idx].inUse = false;
822 
823             mFramesInUse--;
824         }
825     }
826 }
827 
828 
convertToV4l2CID(CameraParam id,uint32_t & v4l2cid)829 bool EvsV4lCamera::convertToV4l2CID(CameraParam id, uint32_t& v4l2cid) {
830     switch (id) {
831         case CameraParam::BRIGHTNESS:
832             v4l2cid = V4L2_CID_BRIGHTNESS;
833             break;
834         case CameraParam::CONTRAST:
835             v4l2cid = V4L2_CID_CONTRAST;
836             break;
837         case CameraParam::AUTO_WHITE_BALANCE:
838             v4l2cid = V4L2_CID_AUTO_WHITE_BALANCE;
839             break;
840         case CameraParam::WHITE_BALANCE_TEMPERATURE:
841             v4l2cid = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
842             break;
843         case CameraParam::SHARPNESS:
844             v4l2cid = V4L2_CID_SHARPNESS;
845             break;
846         case CameraParam::AUTO_EXPOSURE:
847             v4l2cid = V4L2_CID_EXPOSURE_AUTO;
848             break;
849         case CameraParam::ABSOLUTE_EXPOSURE:
850             v4l2cid = V4L2_CID_EXPOSURE_ABSOLUTE;
851             break;
852         case CameraParam::AUTO_FOCUS:
853             v4l2cid = V4L2_CID_FOCUS_AUTO;
854             break;
855         case CameraParam::ABSOLUTE_FOCUS:
856             v4l2cid = V4L2_CID_FOCUS_ABSOLUTE;
857             break;
858         case CameraParam::ABSOLUTE_ZOOM:
859             v4l2cid = V4L2_CID_ZOOM_ABSOLUTE;
860             break;
861         default:
862             LOG(ERROR) << "Camera parameter " << static_cast<unsigned>(id) << " is unknown.";
863             return false;
864     }
865 
866     return mCameraControls.find(v4l2cid) != mCameraControls.end();
867 }
868 
869 
Create(const char * deviceName)870 sp<EvsV4lCamera> EvsV4lCamera::Create(const char *deviceName) {
871     unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
872 
873     return Create(deviceName, nullCamInfo);
874 }
875 
876 
Create(const char * deviceName,unique_ptr<ConfigManager::CameraInfo> & camInfo,const Stream * requestedStreamCfg)877 sp<EvsV4lCamera> EvsV4lCamera::Create(const char *deviceName,
878                                       unique_ptr<ConfigManager::CameraInfo> &camInfo,
879                                       const Stream *requestedStreamCfg) {
880     LOG(INFO) << "Create " << deviceName;
881     sp<EvsV4lCamera> evsCamera = new EvsV4lCamera(deviceName, camInfo);
882     if (evsCamera == nullptr) {
883         return nullptr;
884     }
885 
886     // Initialize the video device
887     bool success = false;
888     if (camInfo != nullptr && requestedStreamCfg != nullptr) {
889         // Validate a given stream configuration.  If there is no exact match,
890         // this will try to find the best match based on:
891         // 1) same output format
892         // 2) the largest resolution that is smaller that a given configuration.
893         int32_t streamId = -1, area = INT_MIN;
894         for (auto& [id, cfg] : camInfo->streamConfigurations) {
895             // RawConfiguration has id, width, height, format, direction, and
896             // fps.
897             if (cfg[3] == static_cast<uint32_t>(requestedStreamCfg->format)) {
898                 if (cfg[1] == requestedStreamCfg->width &&
899                     cfg[2] == requestedStreamCfg->height) {
900                     // Find exact match.
901                     streamId = id;
902                     break;
903                 } else if (requestedStreamCfg->width  > cfg[1] &&
904                            requestedStreamCfg->height > cfg[2] &&
905                            cfg[1] * cfg[2] > area) {
906                     streamId = id;
907                     area = cfg[1] * cfg[2];
908                 }
909             }
910 
911         }
912 
913         if (streamId >= 0) {
914             LOG(INFO) << "Try to open a video with "
915                       << "width: " << camInfo->streamConfigurations[streamId][1]
916                       << ", height: " << camInfo->streamConfigurations[streamId][2]
917                       << ", format: " << camInfo->streamConfigurations[streamId][3];
918             success =
919                 evsCamera->mVideo.open(deviceName,
920                                        camInfo->streamConfigurations[streamId][1],
921                                        camInfo->streamConfigurations[streamId][2]);
922             evsCamera->mFormat = static_cast<uint32_t>(camInfo->streamConfigurations[streamId][3]);
923         }
924     }
925 
926     if (!success) {
927         // Create a camera object with the default resolution and format
928         // , HAL_PIXEL_FORMAT_RGBA_8888.
929         LOG(INFO) << "Open a video with default parameters";
930         success =
931             evsCamera->mVideo.open(deviceName, kDefaultResolution[0], kDefaultResolution[1]);
932         if (!success) {
933             LOG(ERROR) << "Failed to open a video stream";
934             return nullptr;
935         }
936     }
937 
938     // List available camera parameters
939     evsCamera->mCameraControls = evsCamera->mVideo.enumerateCameraControls();
940 
941     // Please note that the buffer usage flag does not come from a given stream
942     // configuration.
943     evsCamera->mUsage  = GRALLOC_USAGE_HW_TEXTURE     |
944                          GRALLOC_USAGE_SW_READ_RARELY |
945                          GRALLOC_USAGE_SW_WRITE_OFTEN;
946 
947     return evsCamera;
948 }
949 
950 
951 } // namespace implementation
952 } // namespace V1_1
953 } // namespace evs
954 } // namespace automotive
955 } // namespace hardware
956 } // namespace android
957