Camera3IOStreamBase.cpp revision 6adc9ccb2948d9421a0ed4b74f52b909bcec2037
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-IOStreamBase" 18#define ATRACE_TAG ATRACE_TAG_CAMERA 19//#define LOG_NDEBUG 0 20 21#include <inttypes.h> 22 23#include <utils/Log.h> 24#include <utils/Trace.h> 25#include "device3/Camera3IOStreamBase.h" 26#include "device3/StatusTracker.h" 27 28namespace android { 29 30namespace camera3 { 31 32Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type, 33 uint32_t width, uint32_t height, size_t maxSize, int format) : 34 Camera3Stream(id, type, 35 width, height, maxSize, format), 36 mTotalBufferCount(0), 37 mHandoutTotalBufferCount(0), 38 mHandoutOutputBufferCount(0), 39 mFrameCount(0), 40 mLastTimestamp(0) { 41 42 mCombinedFence = new Fence(); 43 44 if (maxSize > 0 && format != HAL_PIXEL_FORMAT_BLOB) { 45 ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__, 46 format); 47 mState = STATE_ERROR; 48 } 49} 50 51Camera3IOStreamBase::~Camera3IOStreamBase() { 52 disconnectLocked(); 53} 54 55bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const { 56 nsecs_t signalTime = mCombinedFence->getSignalTime(); 57 ALOGV("%s: Stream %d: Has %zu outstanding buffers," 58 " buffer signal time is %" PRId64, 59 __FUNCTION__, mId, mHandoutTotalBufferCount, signalTime); 60 if (mHandoutTotalBufferCount > 0 || signalTime == INT64_MAX) { 61 return true; 62 } 63 return false; 64} 65 66void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const { 67 (void) args; 68 String8 lines; 69 lines.appendFormat(" State: %d\n", mState); 70 lines.appendFormat(" Dims: %d x %d, format 0x%x\n", 71 camera3_stream::width, camera3_stream::height, 72 camera3_stream::format); 73 lines.appendFormat(" Max size: %zu\n", mMaxSize); 74 lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", 75 camera3_stream::usage, camera3_stream::max_buffers); 76 lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n", 77 mFrameCount, mLastTimestamp); 78 lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n", 79 mTotalBufferCount, mHandoutTotalBufferCount); 80 write(fd, lines.string(), lines.size()); 81} 82 83status_t Camera3IOStreamBase::configureQueueLocked() { 84 status_t res; 85 86 switch (mState) { 87 case STATE_IN_RECONFIG: 88 res = disconnectLocked(); 89 if (res != OK) { 90 return res; 91 } 92 break; 93 case STATE_IN_CONFIG: 94 // OK 95 break; 96 default: 97 ALOGE("%s: Bad state: %d", __FUNCTION__, mState); 98 return INVALID_OPERATION; 99 } 100 101 return OK; 102} 103 104size_t Camera3IOStreamBase::getBufferCountLocked() { 105 return mTotalBufferCount; 106} 107 108size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() { 109 return mHandoutOutputBufferCount; 110} 111 112size_t Camera3IOStreamBase::getHandoutInputBufferCountLocked() { 113 return (mHandoutTotalBufferCount - mHandoutOutputBufferCount); 114} 115 116status_t Camera3IOStreamBase::disconnectLocked() { 117 switch (mState) { 118 case STATE_IN_RECONFIG: 119 case STATE_CONFIGURED: 120 // OK 121 break; 122 default: 123 // No connection, nothing to do 124 ALOGV("%s: Stream %d: Already disconnected", 125 __FUNCTION__, mId); 126 return -ENOTCONN; 127 } 128 129 if (mHandoutTotalBufferCount > 0) { 130 ALOGE("%s: Can't disconnect with %zu buffers still dequeued!", 131 __FUNCTION__, mHandoutTotalBufferCount); 132 return INVALID_OPERATION; 133 } 134 135 return OK; 136} 137 138void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer, 139 buffer_handle_t *handle, 140 int acquireFence, 141 int releaseFence, 142 camera3_buffer_status_t status, 143 bool output) { 144 /** 145 * Note that all fences are now owned by HAL. 146 */ 147 148 // Handing out a raw pointer to this object. Increment internal refcount. 149 incStrong(this); 150 buffer.stream = this; 151 buffer.buffer = handle; 152 buffer.acquire_fence = acquireFence; 153 buffer.release_fence = releaseFence; 154 buffer.status = status; 155 156 // Inform tracker about becoming busy 157 if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG && 158 mState != STATE_IN_RECONFIG) { 159 /** 160 * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers 161 * before/after register_stream_buffers during initial configuration 162 * or re-configuration. 163 * 164 * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for <HAL3.2 165 */ 166 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 167 if (statusTracker != 0) { 168 statusTracker->markComponentActive(mStatusId); 169 } 170 } 171 mHandoutTotalBufferCount++; 172 173 if (output) { 174 mHandoutOutputBufferCount++; 175 } 176} 177 178status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const { 179 // Allow dequeue during IN_[RE]CONFIG for registration 180 if (mState != STATE_CONFIGURED && 181 mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { 182 ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", 183 __FUNCTION__, mId, mState); 184 return INVALID_OPERATION; 185 } 186 187 // Only limit dequeue amount when fully configured 188 if (mState == STATE_CONFIGURED && 189 mHandoutTotalBufferCount == camera3_stream::max_buffers) { 190 ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous" 191 " buffers (%d)", __FUNCTION__, mId, 192 camera3_stream::max_buffers); 193 return INVALID_OPERATION; 194 } 195 196 return OK; 197} 198 199status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const { 200 // Allow buffers to be returned in the error state, to allow for disconnect 201 // and in the in-config states for registration 202 if (mState == STATE_CONSTRUCTED) { 203 ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", 204 __FUNCTION__, mId, mState); 205 return INVALID_OPERATION; 206 } 207 if (mHandoutTotalBufferCount == 0) { 208 ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, 209 mId); 210 return INVALID_OPERATION; 211 } 212 213 return OK; 214} 215 216status_t Camera3IOStreamBase::returnAnyBufferLocked( 217 const camera3_stream_buffer &buffer, 218 nsecs_t timestamp, 219 bool output) { 220 status_t res; 221 222 // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be 223 // decrementing the internal refcount next. In case this is the last ref, we 224 // might get destructed on the decStrong(), so keep an sp around until the 225 // end of the call - otherwise have to sprinkle the decStrong on all exit 226 // points. 227 sp<Camera3IOStreamBase> keepAlive(this); 228 decStrong(this); 229 230 if ((res = returnBufferPreconditionCheckLocked()) != OK) { 231 return res; 232 } 233 234 sp<Fence> releaseFence; 235 res = returnBufferCheckedLocked(buffer, timestamp, output, 236 &releaseFence); 237 // Res may be an error, but we still want to decrement our owned count 238 // to enable clean shutdown. So we'll just return the error but otherwise 239 // carry on 240 241 if (releaseFence != 0) { 242 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); 243 } 244 245 if (output) { 246 mHandoutOutputBufferCount--; 247 } 248 249 mHandoutTotalBufferCount--; 250 if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG && 251 mState != STATE_IN_RECONFIG) { 252 /** 253 * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers 254 * before/after register_stream_buffers during initial configuration 255 * or re-configuration. 256 * 257 * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for <HAL3.2 258 */ 259 ALOGV("%s: Stream %d: All buffers returned; now idle", __FUNCTION__, 260 mId); 261 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 262 if (statusTracker != 0) { 263 statusTracker->markComponentIdle(mStatusId, mCombinedFence); 264 } 265 } 266 267 mBufferReturnedSignal.signal(); 268 269 if (output) { 270 mLastTimestamp = timestamp; 271 } 272 273 return res; 274} 275 276 277 278}; // namespace camera3 279 280}; // namespace android 281