Camera3InputStream.cpp revision 0776a14513300f04dc5c1d2f89c4156576b8b8ed
1/* 2 * Copyright (C) 2013 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// This is needed for stdint.h to define INT64_MAX in C++ 22#define __STDC_LIMIT_MACROS 23 24#include <utils/Log.h> 25#include <utils/Trace.h> 26#include "Camera3InputStream.h" 27 28namespace android { 29 30namespace camera3 { 31 32Camera3InputStream::Camera3InputStream(int id, 33 uint32_t width, uint32_t height, int format) : 34 Camera3Stream(id, CAMERA3_STREAM_INPUT, width, height, 0, format), 35 mTotalBufferCount(0), 36 mDequeuedBufferCount(0), 37 mFrameCount(0), 38 mLastTimestamp(0) { 39 mCombinedFence = new Fence(); 40 41 if (format == HAL_PIXEL_FORMAT_BLOB) { 42 ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); 43 mState = STATE_ERROR; 44 } 45} 46 47Camera3InputStream::~Camera3InputStream() { 48 disconnectLocked(); 49} 50 51status_t Camera3InputStream::getInputBufferLocked( 52 camera3_stream_buffer *buffer) { 53 ATRACE_CALL(); 54 status_t res; 55 56 // FIXME: will not work in (re-)registration 57 if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) { 58 ALOGE("%s: Stream %d: Buffer registration for input streams" 59 " not implemented (state %d)", 60 __FUNCTION__, mId, mState); 61 return INVALID_OPERATION; 62 } 63 64 // Allow acquire during IN_[RE]CONFIG for registration 65 if (mState != STATE_CONFIGURED && 66 mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { 67 ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", 68 __FUNCTION__, mId, mState); 69 return INVALID_OPERATION; 70 } 71 72 // Only limit acquire amount when fully configured 73 if (mState == STATE_CONFIGURED && 74 mDequeuedBufferCount == camera3_stream::max_buffers) { 75 ALOGE("%s: Stream %d: Already acquired maximum number of simultaneous" 76 " buffers (%d)", __FUNCTION__, mId, 77 camera3_stream::max_buffers); 78 return INVALID_OPERATION; 79 } 80 81 ANativeWindowBuffer* anb; 82 int fenceFd; 83 84 assert(mConsumer != 0); 85 86 BufferItem bufferItem; 87 res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false); 88 89 if (res != OK) { 90 ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)", 91 __FUNCTION__, mId, strerror(-res), res); 92 return res; 93 } 94 95 anb = bufferItem.mGraphicBuffer->getNativeBuffer(); 96 assert(anb != NULL); 97 fenceFd = bufferItem.mFence->dup(); 98 /** 99 * FenceFD now owned by HAL except in case of error, 100 * in which case we reassign it to acquire_fence 101 */ 102 103 // Handing out a raw pointer to this object. Increment internal refcount. 104 incStrong(this); 105 buffer->stream = this; 106 buffer->buffer = &(anb->handle); 107 buffer->acquire_fence = fenceFd; 108 buffer->release_fence = -1; 109 buffer->status = CAMERA3_BUFFER_STATUS_OK; 110 111 mDequeuedBufferCount++; 112 113 mBuffersInFlight.push_back(bufferItem); 114 115 return OK; 116} 117 118status_t Camera3InputStream::returnInputBufferLocked( 119 const camera3_stream_buffer &buffer) { 120 ATRACE_CALL(); 121 status_t res; 122 123 // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be 124 // decrementing the internal refcount next. In case this is the last ref, we 125 // might get destructed on the decStrong(), so keep an sp around until the 126 // end of the call - otherwise have to sprinkle the decStrong on all exit 127 // points. 128 sp<Camera3InputStream> keepAlive(this); 129 decStrong(this); 130 131 // Allow buffers to be returned in the error state, to allow for disconnect 132 // and in the in-config states for registration 133 if (mState == STATE_CONSTRUCTED) { 134 ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", 135 __FUNCTION__, mId, mState); 136 return INVALID_OPERATION; 137 } 138 if (mDequeuedBufferCount == 0) { 139 ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, 140 mId); 141 return INVALID_OPERATION; 142 } 143 144 bool bufferFound = false; 145 BufferItem bufferItem; 146 { 147 // Find the buffer we are returning 148 Vector<BufferItem>::iterator it, end; 149 for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end(); 150 it != end; 151 ++it) { 152 153 const BufferItem& tmp = *it; 154 ANativeWindowBuffer *anb = tmp.mGraphicBuffer->getNativeBuffer(); 155 if (anb != NULL && &(anb->handle) == buffer.buffer) { 156 bufferFound = true; 157 bufferItem = tmp; 158 mBuffersInFlight.erase(it); 159 mDequeuedBufferCount--; 160 } 161 } 162 } 163 if (!bufferFound) { 164 ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL", 165 __FUNCTION__, mId); 166 return INVALID_OPERATION; 167 } 168 169 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 170 if (buffer.release_fence != -1) { 171 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " 172 "there is an error", __FUNCTION__, mId, buffer.release_fence); 173 close(buffer.release_fence); 174 } 175 176 /** 177 * Reassign release fence as the acquire fence incase of error 178 */ 179 const_cast<camera3_stream_buffer*>(&buffer)->release_fence = 180 buffer.acquire_fence; 181 } 182 183 /** 184 * Unconditionally return buffer to the buffer queue. 185 * - Fwk takes over the release_fence ownership 186 */ 187 sp<Fence> releaseFence = new Fence(buffer.release_fence); 188 res = mConsumer->releaseBuffer(bufferItem, releaseFence); 189 if (res != OK) { 190 ALOGE("%s: Stream %d: Error releasing buffer back to buffer queue:" 191 " %s (%d)", __FUNCTION__, mId, strerror(-res), res); 192 return res; 193 } 194 195 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); 196 197 mBufferReturnedSignal.signal(); 198 199 return OK; 200 201} 202 203bool Camera3InputStream::hasOutstandingBuffersLocked() const { 204 nsecs_t signalTime = mCombinedFence->getSignalTime(); 205 ALOGV("%s: Stream %d: Has %d outstanding buffers," 206 " buffer signal time is %lld", 207 __FUNCTION__, mId, mDequeuedBufferCount, signalTime); 208 if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { 209 return true; 210 } 211 return false; 212} 213 214status_t Camera3InputStream::waitUntilIdle(nsecs_t timeout) { 215 status_t res; 216 { 217 Mutex::Autolock l(mLock); 218 while (mDequeuedBufferCount > 0) { 219 if (timeout != TIMEOUT_NEVER) { 220 nsecs_t startTime = systemTime(); 221 res = mBufferReturnedSignal.waitRelative(mLock, timeout); 222 if (res == TIMED_OUT) { 223 return res; 224 } else if (res != OK) { 225 ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", 226 __FUNCTION__, strerror(-res), res); 227 return res; 228 } 229 nsecs_t deltaTime = systemTime() - startTime; 230 if (timeout <= deltaTime) { 231 timeout = 0; 232 } else { 233 timeout -= deltaTime; 234 } 235 } else { 236 res = mBufferReturnedSignal.wait(mLock); 237 if (res != OK) { 238 ALOGE("%s: Error waiting for outstanding buffers: %s (%d)", 239 __FUNCTION__, strerror(-res), res); 240 return res; 241 } 242 } 243 } 244 } 245 246 // No lock 247 248 unsigned int timeoutMs; 249 if (timeout == TIMEOUT_NEVER) { 250 timeoutMs = Fence::TIMEOUT_NEVER; 251 } else if (timeout == 0) { 252 timeoutMs = 0; 253 } else { 254 // Round up to wait at least 1 ms 255 timeoutMs = (timeout + 999999) / 1000000; 256 } 257 258 return mCombinedFence->wait(timeoutMs); 259} 260 261size_t Camera3InputStream::getBufferCountLocked() { 262 return mTotalBufferCount; 263} 264 265status_t Camera3InputStream::disconnectLocked() { 266 switch (mState) { 267 case STATE_IN_RECONFIG: 268 case STATE_CONFIGURED: 269 // OK 270 break; 271 default: 272 // No connection, nothing to do 273 return OK; 274 } 275 276 if (mDequeuedBufferCount > 0) { 277 ALOGE("%s: Can't disconnect with %d buffers still acquired!", 278 __FUNCTION__, mDequeuedBufferCount); 279 return INVALID_OPERATION; 280 } 281 282 assert(mBuffersInFlight.size() == 0); 283 284 /** 285 * no-op since we can't disconnect the producer from the consumer-side 286 */ 287 288 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED; 289 return OK; 290} 291 292sp<IGraphicBufferProducer> Camera3InputStream::getProducerInterface() const { 293 return mConsumer->getProducerInterface(); 294} 295 296void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { 297 (void) args; 298 String8 lines; 299 lines.appendFormat(" Stream[%d]: Input\n", mId); 300 lines.appendFormat(" State: %d\n", mState); 301 lines.appendFormat(" Dims: %d x %d, format 0x%x\n", 302 camera3_stream::width, camera3_stream::height, 303 camera3_stream::format); 304 lines.appendFormat(" Max size: %d\n", mMaxSize); 305 lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", 306 camera3_stream::usage, camera3_stream::max_buffers); 307 lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n", 308 mFrameCount, mLastTimestamp); 309 lines.appendFormat(" Total buffers: %d, currently acquired: %d\n", 310 mTotalBufferCount, mDequeuedBufferCount); 311 write(fd, lines.string(), lines.size()); 312} 313 314status_t Camera3InputStream::configureQueueLocked() { 315 status_t res; 316 317 switch (mState) { 318 case STATE_IN_RECONFIG: 319 res = disconnectLocked(); 320 if (res != OK) { 321 return res; 322 } 323 break; 324 case STATE_IN_CONFIG: 325 // OK 326 break; 327 default: 328 ALOGE("%s: Bad state: %d", __FUNCTION__, mState); 329 return INVALID_OPERATION; 330 } 331 332 assert(mMaxSize == 0); 333 assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); 334 335 mTotalBufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS + 336 camera3_stream::max_buffers; 337 mDequeuedBufferCount = 0; 338 mFrameCount = 0; 339 340 if (mConsumer.get() == 0) { 341 mConsumer = new BufferItemConsumer(camera3_stream::usage, 342 mTotalBufferCount, 343 /*synchronousMode*/true); 344 mConsumer->setName(String8::format("Camera3-InputStream-%d", mId)); 345 } 346 347 res = mConsumer->setDefaultBufferSize(camera3_stream::width, 348 camera3_stream::height); 349 if (res != OK) { 350 ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d", 351 __FUNCTION__, mId, camera3_stream::width, camera3_stream::height); 352 return res; 353 } 354 res = mConsumer->setDefaultBufferFormat(camera3_stream::format); 355 if (res != OK) { 356 ALOGE("%s: Stream %d: Could not set buffer format %d", 357 __FUNCTION__, mId, camera3_stream::format); 358 return res; 359 } 360 361 return OK; 362} 363 364}; // namespace camera3 365 366}; // namespace android 367