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