1/* 2 * Copyright (C) 2013-2018 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 "Camera3-InputStream" 18#define ATRACE_TAG ATRACE_TAG_CAMERA 19//#define LOG_NDEBUG 0 20 21#include <gui/BufferItem.h> 22#include <utils/Log.h> 23#include <utils/Trace.h> 24#include "Camera3InputStream.h" 25 26namespace android { 27 28namespace camera3 { 29 30const String8 Camera3InputStream::DUMMY_ID; 31 32Camera3InputStream::Camera3InputStream(int id, 33 uint32_t width, uint32_t height, int format) : 34 Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0, 35 format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, 36 DUMMY_ID) { 37 38 if (format == HAL_PIXEL_FORMAT_BLOB) { 39 ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); 40 mState = STATE_ERROR; 41 } 42} 43 44Camera3InputStream::~Camera3InputStream() { 45 disconnectLocked(); 46} 47 48status_t Camera3InputStream::getInputBufferLocked( 49 camera3_stream_buffer *buffer) { 50 ATRACE_CALL(); 51 status_t res; 52 53 // FIXME: will not work in (re-)registration 54 if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) { 55 ALOGE("%s: Stream %d: Buffer registration for input streams" 56 " not implemented (state %d)", 57 __FUNCTION__, mId, mState); 58 return INVALID_OPERATION; 59 } 60 61 if ((res = getBufferPreconditionCheckLocked()) != OK) { 62 return res; 63 } 64 65 ANativeWindowBuffer* anb; 66 int fenceFd; 67 68 assert(mConsumer != 0); 69 70 BufferItem bufferItem; 71 72 res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false); 73 if (res != OK) { 74 ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)", 75 __FUNCTION__, mId, strerror(-res), res); 76 return res; 77 } 78 79 anb = bufferItem.mGraphicBuffer->getNativeBuffer(); 80 assert(anb != NULL); 81 fenceFd = bufferItem.mFence->dup(); 82 83 /** 84 * FenceFD now owned by HAL except in case of error, 85 * in which case we reassign it to acquire_fence 86 */ 87 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 88 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false); 89 mBuffersInFlight.push_back(bufferItem); 90 91 mFrameCount++; 92 mLastTimestamp = bufferItem.mTimestamp; 93 94 return OK; 95} 96 97status_t Camera3InputStream::returnBufferCheckedLocked( 98 const camera3_stream_buffer &buffer, 99 nsecs_t timestamp, 100 bool output, 101 /*out*/ 102 sp<Fence> *releaseFenceOut) { 103 104 (void)timestamp; 105 (void)output; 106 ALOG_ASSERT(!output, "Expected output to be false"); 107 108 status_t res; 109 110 bool bufferFound = false; 111 BufferItem bufferItem; 112 { 113 // Find the buffer we are returning 114 Vector<BufferItem>::iterator it, end; 115 for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end(); 116 it != end; 117 ++it) { 118 119 const BufferItem& tmp = *it; 120 ANativeWindowBuffer *anb = tmp.mGraphicBuffer->getNativeBuffer(); 121 if (anb != NULL && &(anb->handle) == buffer.buffer) { 122 bufferFound = true; 123 bufferItem = tmp; 124 mBuffersInFlight.erase(it); 125 break; 126 } 127 } 128 } 129 if (!bufferFound) { 130 ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL", 131 __FUNCTION__, mId); 132 return INVALID_OPERATION; 133 } 134 135 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 136 if (buffer.release_fence != -1) { 137 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " 138 "there is an error", __FUNCTION__, mId, buffer.release_fence); 139 close(buffer.release_fence); 140 } 141 142 /** 143 * Reassign release fence as the acquire fence incase of error 144 */ 145 const_cast<camera3_stream_buffer*>(&buffer)->release_fence = 146 buffer.acquire_fence; 147 } 148 149 /** 150 * Unconditionally return buffer to the buffer queue. 151 * - Fwk takes over the release_fence ownership 152 */ 153 sp<Fence> releaseFence = new Fence(buffer.release_fence); 154 res = mConsumer->releaseBuffer(bufferItem, releaseFence); 155 if (res != OK) { 156 ALOGE("%s: Stream %d: Error releasing buffer back to buffer queue:" 157 " %s (%d)", __FUNCTION__, mId, strerror(-res), res); 158 } 159 160 *releaseFenceOut = releaseFence; 161 162 return res; 163} 164 165status_t Camera3InputStream::returnInputBufferLocked( 166 const camera3_stream_buffer &buffer) { 167 ATRACE_CALL(); 168 169 return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false); 170} 171 172status_t Camera3InputStream::getInputBufferProducerLocked( 173 sp<IGraphicBufferProducer> *producer) { 174 ATRACE_CALL(); 175 176 if (producer == NULL) { 177 return BAD_VALUE; 178 } else if (mProducer == NULL) { 179 ALOGE("%s: No input stream is configured", __FUNCTION__); 180 return INVALID_OPERATION; 181 } 182 183 *producer = mProducer; 184 return OK; 185} 186 187status_t Camera3InputStream::disconnectLocked() { 188 189 status_t res; 190 191 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { 192 return res; 193 } 194 195 assert(mBuffersInFlight.size() == 0); 196 197 mConsumer->abandon(); 198 199 /** 200 * no-op since we can't disconnect the producer from the consumer-side 201 */ 202 203 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG 204 : STATE_CONSTRUCTED; 205 return OK; 206} 207 208void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { 209 (void) args; 210 String8 lines; 211 lines.appendFormat(" Stream[%d]: Input\n", mId); 212 write(fd, lines.string(), lines.size()); 213 214 Camera3IOStreamBase::dump(fd, args); 215} 216 217status_t Camera3InputStream::configureQueueLocked() { 218 status_t res; 219 220 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 221 return res; 222 } 223 224 assert(mMaxSize == 0); 225 assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); 226 227 mHandoutTotalBufferCount = 0; 228 mFrameCount = 0; 229 mLastTimestamp = 0; 230 231 if (mConsumer.get() == 0) { 232 sp<IGraphicBufferProducer> producer; 233 sp<IGraphicBufferConsumer> consumer; 234 BufferQueue::createBufferQueue(&producer, &consumer); 235 236 int minUndequeuedBuffers = 0; 237 res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers); 238 if (res != OK || minUndequeuedBuffers < 0) { 239 ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)", 240 __FUNCTION__, mId, res, minUndequeuedBuffers); 241 return res; 242 } 243 size_t minBufs = static_cast<size_t>(minUndequeuedBuffers); 244 245 if (camera3_stream::max_buffers == 0) { 246 ALOGE("%s: %d: HAL sets max_buffer to 0. Must be at least 1.", 247 __FUNCTION__, __LINE__); 248 return INVALID_OPERATION; 249 } 250 251 /* 252 * We promise never to 'acquire' more than camera3_stream::max_buffers 253 * at any one time. 254 * 255 * Boost the number up to meet the minimum required buffer count. 256 * 257 * (Note that this sets consumer-side buffer count only, 258 * and not the sum of producer+consumer side as in other camera streams). 259 */ 260 mTotalBufferCount = camera3_stream::max_buffers > minBufs ? 261 camera3_stream::max_buffers : minBufs; 262 // TODO: somehow set the total buffer count when producer connects? 263 264 mConsumer = new BufferItemConsumer(consumer, mUsage, 265 mTotalBufferCount); 266 mConsumer->setName(String8::format("Camera3-InputStream-%d", mId)); 267 268 mProducer = producer; 269 270 mConsumer->setBufferFreedListener(this); 271 } 272 273 res = mConsumer->setDefaultBufferSize(camera3_stream::width, 274 camera3_stream::height); 275 if (res != OK) { 276 ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d", 277 __FUNCTION__, mId, camera3_stream::width, camera3_stream::height); 278 return res; 279 } 280 res = mConsumer->setDefaultBufferFormat(camera3_stream::format); 281 if (res != OK) { 282 ALOGE("%s: Stream %d: Could not set buffer format %d", 283 __FUNCTION__, mId, camera3_stream::format); 284 return res; 285 } 286 287 return OK; 288} 289 290status_t Camera3InputStream::getEndpointUsage(uint64_t *usage) const { 291 // Per HAL3 spec, input streams have 0 for their initial usage field. 292 *usage = 0; 293 return OK; 294} 295 296void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) { 297 const sp<GraphicBuffer> buffer = gb.promote(); 298 if (buffer != nullptr) { 299 camera3_stream_buffer streamBuffer = 300 {nullptr, &buffer->handle, 0, -1, -1}; 301 // Check if this buffer is outstanding. 302 if (isOutstandingBuffer(streamBuffer)) { 303 ALOGV("%s: Stream %d: Trying to free a buffer that is still being " 304 "processed.", __FUNCTION__, mId); 305 return; 306 } 307 308 sp<Camera3StreamBufferFreedListener> callback = mBufferFreedListener.promote(); 309 if (callback != nullptr) { 310 callback->onBufferFreed(mId, buffer->handle); 311 } 312 } else { 313 ALOGE("%s: GraphicBuffer is freed before onBufferFreed callback finishes!", __FUNCTION__); 314 } 315} 316 317}; // namespace camera3 318 319}; // namespace android 320