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 // 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 "device3/Camera3IOStreamBase.h" 27 #include "device3/StatusTracker.h" 28 29 namespace android { 30 31 namespace camera3 { 32 33 Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type, 34 uint32_t width, uint32_t height, size_t maxSize, int format) : 35 Camera3Stream(id, type, 36 width, height, maxSize, format), 37 mTotalBufferCount(0), 38 mDequeuedBufferCount(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 51 Camera3IOStreamBase::~Camera3IOStreamBase() { 52 disconnectLocked(); 53 } 54 55 bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const { 56 nsecs_t signalTime = mCombinedFence->getSignalTime(); 57 ALOGV("%s: Stream %d: Has %d outstanding buffers," 58 " buffer signal time is %lld", 59 __FUNCTION__, mId, mDequeuedBufferCount, signalTime); 60 if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { 61 return true; 62 } 63 return false; 64 } 65 66 void 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: %d\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: %lld ns\n", 77 mFrameCount, mLastTimestamp); 78 lines.appendFormat(" Total buffers: %d, currently dequeued: %d\n", 79 mTotalBufferCount, mDequeuedBufferCount); 80 write(fd, lines.string(), lines.size()); 81 } 82 83 status_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 104 size_t Camera3IOStreamBase::getBufferCountLocked() { 105 return mTotalBufferCount; 106 } 107 108 status_t Camera3IOStreamBase::disconnectLocked() { 109 switch (mState) { 110 case STATE_IN_RECONFIG: 111 case STATE_CONFIGURED: 112 // OK 113 break; 114 default: 115 // No connection, nothing to do 116 ALOGV("%s: Stream %d: Already disconnected", 117 __FUNCTION__, mId); 118 return -ENOTCONN; 119 } 120 121 if (mDequeuedBufferCount > 0) { 122 ALOGE("%s: Can't disconnect with %d buffers still dequeued!", 123 __FUNCTION__, mDequeuedBufferCount); 124 return INVALID_OPERATION; 125 } 126 127 return OK; 128 } 129 130 void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer, 131 buffer_handle_t *handle, 132 int acquireFence, 133 int releaseFence, 134 camera3_buffer_status_t status) { 135 /** 136 * Note that all fences are now owned by HAL. 137 */ 138 139 // Handing out a raw pointer to this object. Increment internal refcount. 140 incStrong(this); 141 buffer.stream = this; 142 buffer.buffer = handle; 143 buffer.acquire_fence = acquireFence; 144 buffer.release_fence = releaseFence; 145 buffer.status = status; 146 147 // Inform tracker about becoming busy 148 if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG && 149 mState != STATE_IN_RECONFIG) { 150 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 151 if (statusTracker != 0) { 152 statusTracker->markComponentActive(mStatusId); 153 } 154 } 155 mDequeuedBufferCount++; 156 } 157 158 status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const { 159 // Allow dequeue during IN_[RE]CONFIG for registration 160 if (mState != STATE_CONFIGURED && 161 mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) { 162 ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d", 163 __FUNCTION__, mId, mState); 164 return INVALID_OPERATION; 165 } 166 167 // Only limit dequeue amount when fully configured 168 if (mState == STATE_CONFIGURED && 169 mDequeuedBufferCount == camera3_stream::max_buffers) { 170 ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous" 171 " buffers (%d)", __FUNCTION__, mId, 172 camera3_stream::max_buffers); 173 return INVALID_OPERATION; 174 } 175 176 return OK; 177 } 178 179 status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const { 180 // Allow buffers to be returned in the error state, to allow for disconnect 181 // and in the in-config states for registration 182 if (mState == STATE_CONSTRUCTED) { 183 ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d", 184 __FUNCTION__, mId, mState); 185 return INVALID_OPERATION; 186 } 187 if (mDequeuedBufferCount == 0) { 188 ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__, 189 mId); 190 return INVALID_OPERATION; 191 } 192 193 return OK; 194 } 195 196 status_t Camera3IOStreamBase::returnAnyBufferLocked( 197 const camera3_stream_buffer &buffer, 198 nsecs_t timestamp, 199 bool output) { 200 status_t res; 201 202 // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be 203 // decrementing the internal refcount next. In case this is the last ref, we 204 // might get destructed on the decStrong(), so keep an sp around until the 205 // end of the call - otherwise have to sprinkle the decStrong on all exit 206 // points. 207 sp<Camera3IOStreamBase> keepAlive(this); 208 decStrong(this); 209 210 if ((res = returnBufferPreconditionCheckLocked()) != OK) { 211 return res; 212 } 213 214 sp<Fence> releaseFence; 215 res = returnBufferCheckedLocked(buffer, timestamp, output, 216 &releaseFence); 217 // Res may be an error, but we still want to decrement our owned count 218 // to enable clean shutdown. So we'll just return the error but otherwise 219 // carry on 220 221 if (releaseFence != 0) { 222 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence); 223 } 224 225 mDequeuedBufferCount--; 226 if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG && 227 mState != STATE_IN_RECONFIG) { 228 ALOGV("%s: Stream %d: All buffers returned; now idle", __FUNCTION__, 229 mId); 230 sp<StatusTracker> statusTracker = mStatusTracker.promote(); 231 if (statusTracker != 0) { 232 statusTracker->markComponentIdle(mStatusId, mCombinedFence); 233 } 234 } 235 236 mBufferReturnedSignal.signal(); 237 238 if (output) { 239 mLastTimestamp = timestamp; 240 } 241 242 return res; 243 } 244 245 246 247 }; // namespace camera3 248 249 }; // namespace android 250