1b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph/* 2b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * Copyright (C) 2016 The Android Open Source Project 3b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * 4b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * Licensed under the Apache License, Version 2.0 (the "License"); 5b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * you may not use this file except in compliance with the License. 6b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * You may obtain a copy of the License at 7b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * 8b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * http://www.apache.org/licenses/LICENSE-2.0 9b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * 10b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * Unless required by applicable law or agreed to in writing, software 11b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * distributed under the License is distributed on an "AS IS" BASIS, 12b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * See the License for the specific language governing permissions and 14b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph * limitations under the License. 15b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph */ 16b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 17b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include "EvsV4lCamera.h" 18b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include "EvsEnumerator.h" 19b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include "bufferCopy.h" 20b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 21b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <ui/GraphicBufferAllocator.h> 22b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph#include <ui/GraphicBufferMapper.h> 23b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 24b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 25b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphnamespace android { 26b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphnamespace hardware { 27b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphnamespace automotive { 28b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphnamespace evs { 29b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphnamespace V1_0 { 30b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphnamespace implementation { 31b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 32b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 33b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// Arbitrary limit on number of graphics buffers allowed to be allocated 34b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// Safeguards against unreasonable resource consumption and provides a testable limit 35b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphstatic const unsigned MAX_BUFFERS_IN_FLIGHT = 100; 36b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 37b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 38b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphEvsV4lCamera::EvsV4lCamera(const char *deviceName) : 39b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesAllowed(0), 40b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesInUse(0) { 41b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("EvsV4lCamera instantiated"); 42b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 43b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mDescription.cameraId = deviceName; 44b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 45b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Initialize the video device 46b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mVideo.open(deviceName)) { 47b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to open v4l device %s\n", deviceName); 48b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 49b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 50b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // NOTE: Our current spec says only support NV21 -- can we stick to that with software 51b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // conversion? Will this work with the hardware texture units? 52b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Settle on the one official format that works on all platforms 53b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Get NV21 working? It is scrambled somewhere along the way right now. 54b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// mFormat = HAL_PIXEL_FORMAT_YCRCB_420_SP; // 420SP == NV21 55b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// mFormat = HAL_PIXEL_FORMAT_RGBA_8888; 56b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFormat = HAL_PIXEL_FORMAT_YCBCR_422_I; 57b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 58b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // How we expect to use the gralloc buffers we'll exchange with our client 59b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mUsage = GRALLOC_USAGE_HW_TEXTURE | 60b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GRALLOC_USAGE_SW_READ_RARELY | 61b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GRALLOC_USAGE_SW_WRITE_OFTEN; 62b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 63b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 64b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 65b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphEvsV4lCamera::~EvsV4lCamera() { 66b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("EvsV4lCamera being destroyed"); 67b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph shutdown(); 68b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 69b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 70b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 71b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// 72b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// This gets called if another caller "steals" ownership of the camera 73b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// 74b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphvoid EvsV4lCamera::shutdown() 75b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph{ 76b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("EvsV4lCamera shutdown"); 77b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 78b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Make sure our output stream is cleaned up 79b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // (It really should be already) 80b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph stopVideoStream(); 81b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 82b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Note: Since stopVideoStream is blocking, no other threads can now be running 83b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 84b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Close our video capture device 85b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mVideo.close(); 86b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 87b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Drop all the graphics buffers we've been using 88b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mBuffers.size() > 0) { 89b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); 90b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph for (auto&& rec : mBuffers) { 91b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (rec.inUse) { 92b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGW("Error - releasing buffer despite remote ownership"); 93b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 94b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph alloc.free(rec.handle); 95b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph rec.handle = nullptr; 96b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 97b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mBuffers.clear(); 98b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 99b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 100b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 101b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 102b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow. 103b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<void> EvsV4lCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) { 104b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("getCameraInfo"); 105b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 106b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Send back our self description 107b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph _hidl_cb(mDescription); 108b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return Void(); 109b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 110b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 111b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 112b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<EvsResult> EvsV4lCamera::setMaxFramesInFlight(uint32_t bufferCount) { 113b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("setMaxFramesInFlight"); 114b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::lock_guard<std::mutex> lock(mAccessLock); 115b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 116b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we've been displaced by another owner of the camera, then we can't do anything else 117b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mVideo.isOpen()) { 118b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGW("ignoring setMaxFramesInFlight call when camera has been lost."); 119b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::OWNERSHIP_LOST; 120b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 121b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 122b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // We cannot function without at least one video buffer to send data 123b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (bufferCount < 1) { 124b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Ignoring setMaxFramesInFlight with less than one buffer requested"); 125b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::INVALID_ARG; 126b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 127b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 128b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Update our internal state 129b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (setAvailableFrames_Locked(bufferCount)) { 130b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::OK; 131b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 132b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::BUFFER_NOT_AVAILABLE; 133b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 134b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 135b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 136b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 137b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<EvsResult> EvsV4lCamera::startVideoStream(const ::android::sp<IEvsCameraStream>& stream) { 138b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("startVideoStream"); 139b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::lock_guard<std::mutex> lock(mAccessLock); 140b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 141b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we've been displaced by another owner of the camera, then we can't do anything else 142b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mVideo.isOpen()) { 143b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGW("ignoring startVideoStream call when camera has been lost."); 144b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::OWNERSHIP_LOST; 145b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 146b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mStream.get() != nullptr) { 147b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("ignoring startVideoStream call when a stream is already running."); 148b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::STREAM_ALREADY_RUNNING; 149b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 150b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 151b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If the client never indicated otherwise, configure ourselves for a single streaming buffer 152b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mFramesAllowed < 1) { 153b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!setAvailableFrames_Locked(1)) { 154b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to start stream because we couldn't get a graphics buffer"); 155b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::BUFFER_NOT_AVAILABLE; 156b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 157b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 158b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 159b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Choose which image transfer function we need 160b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Map from V4L2 to Android graphic buffer format 161b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph const uint32_t videoSrcFormat = mVideo.getV4LFormat(); 162f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph ALOGI("Configuring to accept %4.4s camera data and convert to %4.4s", 163f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph (char*)&videoSrcFormat, (char*)&mFormat); 164b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 165b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Simplify this by supporting only ONE fixed output format 166b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph switch (mFormat) { 167b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case HAL_PIXEL_FORMAT_YCRCB_420_SP: 168b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph switch (videoSrcFormat) { 169b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case V4L2_PIX_FMT_NV21: mFillBufferFromVideo = fillNV21FromNV21; break; 170b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // case V4L2_PIX_FMT_YV12: mFillBufferFromVideo = fillNV21FromYV12; break; 171b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case V4L2_PIX_FMT_YUYV: mFillBufferFromVideo = fillNV21FromYUYV; break; 172b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // case V4L2_PIX_FORMAT_NV16: mFillBufferFromVideo = fillNV21FromNV16; break; 173b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph default: 174b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Are there other V4L2 formats we must support? 175b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Unhandled camera output format %c%c%c%c (0x%8X)\n", 176b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ((char*)&videoSrcFormat)[0], 177b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ((char*)&videoSrcFormat)[1], 178b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ((char*)&videoSrcFormat)[2], 179b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ((char*)&videoSrcFormat)[3], 180b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph videoSrcFormat); 181b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 182b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 183b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case HAL_PIXEL_FORMAT_RGBA_8888: 184b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph switch (videoSrcFormat) { 185b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case V4L2_PIX_FMT_YUYV: mFillBufferFromVideo = fillRGBAFromYUYV; break; 186b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph default: 187b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Are there other V4L2 formats we must support? 188b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Unhandled camera format %4.4s", (char*)&videoSrcFormat); 189b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 190b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 191b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case HAL_PIXEL_FORMAT_YCBCR_422_I: 192b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph switch (videoSrcFormat) { 193b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph case V4L2_PIX_FMT_YUYV: mFillBufferFromVideo = fillYUYVFromYUYV; break; 194f91b3fccfe62a0361f64c89218d3a7a2443f8d0aScott Randolph case V4L2_PIX_FMT_UYVY: mFillBufferFromVideo = fillYUYVFromUYVY; break; 195b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph default: 196b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Are there other V4L2 formats we must support? 197b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Unhandled camera format %4.4s", (char*)&videoSrcFormat); 198b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 199b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 200b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph default: 201b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // TODO: Why have we told ourselves to output something we don't understand!? 202b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Unhandled output format %4.4s", (char*)&mFormat); 203b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 204b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 205b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 206b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Record the user's callback for use when we have a frame ready 207b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mStream = stream; 208b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 209b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Set up the video stream with a callback to our member function forwardFrame() 210b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mVideo.startStream([this](VideoCapture*, imageBuffer* tgt, void* data) { 211b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph this->forwardFrame(tgt, data); 212b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph }) 213b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ) { 214b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mStream = nullptr; // No need to hold onto this if we failed to start 215b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("underlying camera start stream failed"); 216b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::UNDERLYING_SERVICE_ERROR; 217b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 218b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 219b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::OK; 220b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 221b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 222b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 223b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<void> EvsV4lCamera::doneWithFrame(const BufferDesc& buffer) { 224b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("doneWithFrame"); 225b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::lock_guard <std::mutex> lock(mAccessLock); 226b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 227b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we've been displaced by another owner of the camera, then we can't do anything else 228b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mVideo.isOpen()) { 229b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGW("ignoring doneWithFrame call when camera has been lost."); 230b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 231b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (buffer.memHandle == nullptr) { 232b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("ignoring doneWithFrame called with null handle"); 233b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else if (buffer.bufferId >= mBuffers.size()) { 234b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)", 235b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.bufferId, mBuffers.size()-1); 236b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else if (!mBuffers[buffer.bufferId].inUse) { 237b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("ignoring doneWithFrame called on frame %d which is already free", 238b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer.bufferId); 239b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 240b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Mark the frame as available 241b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mBuffers[buffer.bufferId].inUse = false; 242b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesInUse--; 243b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 244b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If this frame's index is high in the array, try to move it down 245b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // to improve locality after mFramesAllowed has been reduced. 246b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (buffer.bufferId >= mFramesAllowed) { 247b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Find an empty slot lower in the array (which should always exist in this case) 248b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph for (auto&& rec : mBuffers) { 249b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (rec.handle == nullptr) { 250b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph rec.handle = mBuffers[buffer.bufferId].handle; 251b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mBuffers[buffer.bufferId].handle = nullptr; 252b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 253b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 254b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 255b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 256b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 257b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 258b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 259b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return Void(); 260b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 261b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 262b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 263b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<void> EvsV4lCamera::stopVideoStream() { 264b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("stopVideoStream"); 265b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 266b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Tell the capture device to stop (and block until it does) 267b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mVideo.stopStream(); 268b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 269b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mStream != nullptr) { 270b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::unique_lock <std::mutex> lock(mAccessLock); 271b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 272b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Send one last NULL frame to signal the actual end of stream 273b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph BufferDesc nullBuff = {}; 274b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph auto result = mStream->deliverFrame(nullBuff); 275b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!result.isOk()) { 276b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Error delivering end of stream marker"); 277b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 278b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 279b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Drop our reference to the client's stream receiver 280b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mStream = nullptr; 281b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 282b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 283b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return Void(); 284b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 285b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 286b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 287b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<int32_t> EvsV4lCamera::getExtendedInfo(uint32_t /*opaqueIdentifier*/) { 288b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("getExtendedInfo"); 289b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Return zero by default as required by the spec 290b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return 0; 291b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 292b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 293b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 294b342cb163393317d8af77339ff8ff5e921bd4a8fScott RandolphReturn<EvsResult> EvsV4lCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, 295b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph int32_t /*opaqueValue*/) { 296b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("setExtendedInfo"); 297b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::lock_guard<std::mutex> lock(mAccessLock); 298b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 299b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we've been displaced by another owner of the camera, then we can't do anything else 300b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mVideo.isOpen()) { 301b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGW("ignoring setExtendedInfo call when camera has been lost."); 302b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::OWNERSHIP_LOST; 303b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 304b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 305b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // We don't store any device specific information in this implementation 306b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return EvsResult::INVALID_ARG; 307b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 308b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 309b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 310b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphbool EvsV4lCamera::setAvailableFrames_Locked(unsigned bufferCount) { 311b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (bufferCount < 1) { 312b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Ignoring request to set buffer count to zero"); 313b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 314b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 315b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (bufferCount > MAX_BUFFERS_IN_FLIGHT) { 316b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Rejecting buffer request in excess of internal limit"); 317b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 318b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 319b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 320b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Is an increase required? 321b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mFramesAllowed < bufferCount) { 322b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // An increase is required 323b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned needed = bufferCount - mFramesAllowed; 324b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGI("Allocating %d buffers for camera frames", needed); 325b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 326b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned added = increaseAvailableFrames_Locked(needed); 327b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (added != needed) { 328b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we didn't add all the frames we needed, then roll back to the previous state 329b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Rolling back to previous frame queue size"); 330b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph decreaseAvailableFrames_Locked(added); 331b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return false; 332b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 333b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else if (mFramesAllowed > bufferCount) { 334b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // A decrease is required 335b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned framesToRelease = mFramesAllowed - bufferCount; 336b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGI("Returning %d camera frame buffers", framesToRelease); 337b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 338b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned released = decreaseAvailableFrames_Locked(framesToRelease); 339b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (released != framesToRelease) { 340b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // This shouldn't happen with a properly behaving client because the client 341b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // should only make this call after returning sufficient outstanding buffers 342b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // to allow a clean resize. 343b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Buffer queue shrink failed -- too many buffers currently in use?"); 344b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 345b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 346b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 347b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return true; 348b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 349b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 350b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 351b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphunsigned EvsV4lCamera::increaseAvailableFrames_Locked(unsigned numToAdd) { 352b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Acquire the graphics buffer allocator 353b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GraphicBufferAllocator &alloc(GraphicBufferAllocator::get()); 354b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 355b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned added = 0; 356b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 357b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 358b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph while (added < numToAdd) { 359b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned pixelsPerLine; 360b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buffer_handle_t memHandle = nullptr; 361b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph status_t result = alloc.allocate(mVideo.getWidth(), mVideo.getHeight(), 362b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFormat, 1, 363b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mUsage, 364b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph &memHandle, &pixelsPerLine, 0, "EvsV4lCamera"); 365b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (result != NO_ERROR) { 366b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Error %d allocating %d x %d graphics buffer", 367b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph result, 368b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mVideo.getWidth(), 369b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mVideo.getHeight()); 370b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 371b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 372b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!memHandle) { 373b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("We didn't get a buffer handle back from the allocator"); 374b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 375b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 376b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mStride) { 377b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mStride != pixelsPerLine) { 378b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("We did not expect to get buffers with different strides!"); 379b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 380b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 381b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Gralloc defines stride in terms of pixels per line 382b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mStride = pixelsPerLine; 383b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 384b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 385b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Find a place to store the new buffer 386b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph bool stored = false; 387b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph for (auto&& rec : mBuffers) { 388b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (rec.handle == nullptr) { 389b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Use this existing entry 390b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph rec.handle = memHandle; 391b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph rec.inUse = false; 392b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph stored = true; 393b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 394b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 395b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 396b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!stored) { 397b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Add a BufferRecord wrapping this handle to our set of available buffers 398b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mBuffers.emplace_back(memHandle); 399b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 400b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 401b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesAllowed++; 402b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph added++; 403b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 404b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 405b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return added; 406b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 407b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 408b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 409b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphunsigned EvsV4lCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) { 410b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Acquire the graphics buffer allocator 411b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GraphicBufferAllocator &alloc(GraphicBufferAllocator::get()); 412b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 413b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph unsigned removed = 0; 414b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 415b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph for (auto&& rec : mBuffers) { 416b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Is this record not in use, but holding a buffer that we can free? 417b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if ((rec.inUse == false) && (rec.handle != nullptr)) { 418b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Release buffer and update the record so we can recognize it as "empty" 419b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph alloc.free(rec.handle); 420b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph rec.handle = nullptr; 421b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 422b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesAllowed--; 423b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph removed++; 424b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 425b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (removed == numToRemove) { 426b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 427b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 428b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 429b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 430b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 431b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph return removed; 432b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 433b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 434b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 435b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph// This is the async callback from the video camera that tells us a frame is ready 436b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolphvoid EvsV4lCamera::forwardFrame(imageBuffer* /*pV4lBuff*/, void* pData) { 437b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph bool readyForFrame = false; 438b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph size_t idx = 0; 439b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 440b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Lock scope for updating shared state 441b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph { 442b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::lock_guard<std::mutex> lock(mAccessLock); 443b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 444b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Are we allowed to issue another buffer? 445b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mFramesInUse >= mFramesAllowed) { 446b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Can't do anything right now -- skip this frame 447b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGW("Skipped a frame because too many are in flight\n"); 448b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 449b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Identify an available buffer to fill 450b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph for (idx = 0; idx < mBuffers.size(); idx++) { 451b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!mBuffers[idx].inUse) { 452b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (mBuffers[idx].handle != nullptr) { 453b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Found an available record, so stop looking 454b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph break; 455b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 456b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 457b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 458b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (idx >= mBuffers.size()) { 459b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed 460b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Failed to find an available buffer slot\n"); 461b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 462b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // We're going to make the frame busy 463b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mBuffers[idx].inUse = true; 464b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesInUse++; 465b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph readyForFrame = true; 466b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 467b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 468b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 469b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 470b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!readyForFrame) { 471b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // We need to return the vide buffer so it can capture a new frame 472b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mVideo.markFrameConsumed(); 473b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 474b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Assemble the buffer description we'll transmit below 475b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph BufferDesc buff = {}; 476b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.width = mVideo.getWidth(); 477b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.height = mVideo.getHeight(); 478b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.stride = mStride; 479b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.format = mFormat; 480b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.usage = mUsage; 481b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.bufferId = idx; 482b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph buff.memHandle = mBuffers[idx].handle; 483b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 484b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Lock our output buffer for writing 485b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph void *targetPixels = nullptr; 486b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 487b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mapper.lock(buff.memHandle, 488b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER, 489b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph android::Rect(buff.width, buff.height), 490b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph (void **) &targetPixels); 491b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 492b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // If we failed to lock the pixel buffer, we're about to crash, but log it first 493b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (!targetPixels) { 494b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Camera failed to gain access to image buffer for writing"); 495b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 496b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 497b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Transfer the video image into the output buffer, making any needed 498b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // format conversion along the way 499b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFillBufferFromVideo(buff, (uint8_t*)targetPixels, pData, mVideo.getStride()); 500b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 501b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Unlock the output buffer 502b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mapper.unlock(buff.memHandle); 503b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 504b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 505b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Give the video frame back to the underlying device for reuse 506b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Note that we do this before making the client callback to give the underlying 507b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // camera more time to capture the next frame. 508b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mVideo.markFrameConsumed(); 509b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 510b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Issue the (asynchronous) callback to the client -- can't be holding the lock 511b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph auto result = mStream->deliverFrame(buff); 512b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph if (result.isOk()) { 513b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGD("Delivered %p as id %d", buff.memHandle.getNativeHandle(), buff.bufferId); 514b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } else { 515b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // This can happen if the client dies and is likely unrecoverable. 516b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // To avoid consuming resources generating failing calls, we stop sending 517b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // frames. Note, however, that the stream remains in the "STREAMING" state 518b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // until cleaned up on the main thread. 519b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph ALOGE("Frame delivery call failed in the transport layer."); 520b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 521b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph // Since we didn't actually deliver it, mark the frame as available 522b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph std::lock_guard<std::mutex> lock(mAccessLock); 523b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mBuffers[idx].inUse = false; 524b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph mFramesInUse--; 525b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 526b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph } 527b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} 528b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph 529b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} // namespace implementation 530b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} // namespace V1_0 531b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} // namespace evs 532b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} // namespace automotive 533b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} // namespace hardware 534b342cb163393317d8af77339ff8ff5e921bd4a8fScott Randolph} // namespace android 535