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-ZslStream" 18 #define ATRACE_TAG ATRACE_TAG_CAMERA 19 //#define LOG_NDEBUG 0 20 21 #include <utils/Log.h> 22 #include <utils/Trace.h> 23 #include "Camera3ZslStream.h" 24 25 typedef android::RingBufferConsumer::PinnedBufferItem PinnedBufferItem; 26 27 namespace android { 28 29 namespace camera3 { 30 31 namespace { 32 struct TimestampFinder : public RingBufferConsumer::RingBufferComparator { 33 typedef RingBufferConsumer::BufferInfo BufferInfo; 34 35 enum { 36 SELECT_I1 = -1, 37 SELECT_I2 = 1, 38 SELECT_NEITHER = 0, 39 }; 40 41 TimestampFinder(nsecs_t timestamp) : mTimestamp(timestamp) {} 42 ~TimestampFinder() {} 43 44 template <typename T> 45 static void swap(T& a, T& b) { 46 T tmp = a; 47 a = b; 48 b = tmp; 49 } 50 51 /** 52 * Try to find the best candidate for a ZSL buffer. 53 * Match priority from best to worst: 54 * 1) Timestamps match. 55 * 2) Timestamp is closest to the needle (and lower). 56 * 3) Timestamp is closest to the needle (and higher). 57 * 58 */ 59 virtual int compare(const BufferInfo *i1, 60 const BufferInfo *i2) const { 61 // Try to select non-null object first. 62 if (i1 == NULL) { 63 return SELECT_I2; 64 } else if (i2 == NULL) { 65 return SELECT_I1; 66 } 67 68 // Best result: timestamp is identical 69 if (i1->mTimestamp == mTimestamp) { 70 return SELECT_I1; 71 } else if (i2->mTimestamp == mTimestamp) { 72 return SELECT_I2; 73 } 74 75 const BufferInfo* infoPtrs[2] = { 76 i1, 77 i2 78 }; 79 int infoSelectors[2] = { 80 SELECT_I1, 81 SELECT_I2 82 }; 83 84 // Order i1,i2 so that always i1.timestamp < i2.timestamp 85 if (i1->mTimestamp > i2->mTimestamp) { 86 swap(infoPtrs[0], infoPtrs[1]); 87 swap(infoSelectors[0], infoSelectors[1]); 88 } 89 90 // Second best: closest (lower) timestamp 91 if (infoPtrs[1]->mTimestamp < mTimestamp) { 92 return infoSelectors[1]; 93 } else if (infoPtrs[0]->mTimestamp < mTimestamp) { 94 return infoSelectors[0]; 95 } 96 97 // Worst: closest (higher) timestamp 98 return infoSelectors[0]; 99 100 /** 101 * The above cases should cover all the possibilities, 102 * and we get an 'empty' result only if the ring buffer 103 * was empty itself 104 */ 105 } 106 107 const nsecs_t mTimestamp; 108 }; // struct TimestampFinder 109 } // namespace anonymous 110 111 Camera3ZslStream::Camera3ZslStream(int id, uint32_t width, uint32_t height, 112 int depth) : 113 Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL, 114 width, height, 115 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), 116 mDepth(depth) { 117 118 sp<BufferQueue> bq = new BufferQueue(); 119 mProducer = new RingBufferConsumer(bq, GRALLOC_USAGE_HW_CAMERA_ZSL, depth); 120 mConsumer = new Surface(bq); 121 } 122 123 Camera3ZslStream::~Camera3ZslStream() { 124 } 125 126 status_t Camera3ZslStream::getInputBufferLocked(camera3_stream_buffer *buffer) { 127 ATRACE_CALL(); 128 129 status_t res; 130 131 // TODO: potentially register from inputBufferLocked 132 // this should be ok, registerBuffersLocked only calls getBuffer for now 133 // register in output mode instead of input mode for ZSL streams. 134 if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) { 135 ALOGE("%s: Stream %d: Buffer registration for input streams" 136 " not implemented (state %d)", 137 __FUNCTION__, mId, mState); 138 return INVALID_OPERATION; 139 } 140 141 if ((res = getBufferPreconditionCheckLocked()) != OK) { 142 return res; 143 } 144 145 ANativeWindowBuffer* anb; 146 int fenceFd; 147 148 assert(mProducer != 0); 149 150 sp<PinnedBufferItem> bufferItem; 151 { 152 List<sp<RingBufferConsumer::PinnedBufferItem> >::iterator it, end; 153 it = mInputBufferQueue.begin(); 154 end = mInputBufferQueue.end(); 155 156 // Need to call enqueueInputBufferByTimestamp as a prerequisite 157 if (it == end) { 158 ALOGE("%s: Stream %d: No input buffer was queued", 159 __FUNCTION__, mId); 160 return INVALID_OPERATION; 161 } 162 bufferItem = *it; 163 mInputBufferQueue.erase(it); 164 } 165 166 anb = bufferItem->getBufferItem().mGraphicBuffer->getNativeBuffer(); 167 assert(anb != NULL); 168 fenceFd = bufferItem->getBufferItem().mFence->dup(); 169 170 /** 171 * FenceFD now owned by HAL except in case of error, 172 * in which case we reassign it to acquire_fence 173 */ 174 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 175 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK); 176 177 mBuffersInFlight.push_back(bufferItem); 178 179 return OK; 180 } 181 182 status_t Camera3ZslStream::returnBufferCheckedLocked( 183 const camera3_stream_buffer &buffer, 184 nsecs_t timestamp, 185 bool output, 186 /*out*/ 187 sp<Fence> *releaseFenceOut) { 188 189 if (output) { 190 // Output stream path 191 return Camera3OutputStream::returnBufferCheckedLocked(buffer, 192 timestamp, 193 output, 194 releaseFenceOut); 195 } 196 197 /** 198 * Input stream path 199 */ 200 bool bufferFound = false; 201 sp<PinnedBufferItem> bufferItem; 202 { 203 // Find the buffer we are returning 204 Vector<sp<PinnedBufferItem> >::iterator it, end; 205 for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end(); 206 it != end; 207 ++it) { 208 209 const sp<PinnedBufferItem>& tmp = *it; 210 ANativeWindowBuffer *anb = 211 tmp->getBufferItem().mGraphicBuffer->getNativeBuffer(); 212 if (anb != NULL && &(anb->handle) == buffer.buffer) { 213 bufferFound = true; 214 bufferItem = tmp; 215 mBuffersInFlight.erase(it); 216 break; 217 } 218 } 219 } 220 if (!bufferFound) { 221 ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL", 222 __FUNCTION__, mId); 223 return INVALID_OPERATION; 224 } 225 226 int releaseFenceFd = buffer.release_fence; 227 228 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 229 if (buffer.release_fence != -1) { 230 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " 231 "there is an error", __FUNCTION__, mId, buffer.release_fence); 232 close(buffer.release_fence); 233 } 234 235 /** 236 * Reassign release fence as the acquire fence incase of error 237 */ 238 releaseFenceFd = buffer.acquire_fence; 239 } 240 241 /** 242 * Unconditionally return buffer to the buffer queue. 243 * - Fwk takes over the release_fence ownership 244 */ 245 sp<Fence> releaseFence = new Fence(releaseFenceFd); 246 bufferItem->getBufferItem().mFence = releaseFence; 247 bufferItem.clear(); // dropping last reference unpins buffer 248 249 *releaseFenceOut = releaseFence; 250 251 return OK; 252 } 253 254 status_t Camera3ZslStream::returnInputBufferLocked( 255 const camera3_stream_buffer &buffer) { 256 ATRACE_CALL(); 257 258 status_t res = returnAnyBufferLocked(buffer, /*timestamp*/0, 259 /*output*/false); 260 261 return res; 262 } 263 264 void Camera3ZslStream::dump(int fd, const Vector<String16> &args) const { 265 (void) args; 266 267 String8 lines; 268 lines.appendFormat(" Stream[%d]: ZSL\n", mId); 269 write(fd, lines.string(), lines.size()); 270 271 Camera3IOStreamBase::dump(fd, args); 272 273 lines = String8(); 274 lines.appendFormat(" Input buffers pending: %d, in flight %d\n", 275 mInputBufferQueue.size(), mBuffersInFlight.size()); 276 write(fd, lines.string(), lines.size()); 277 } 278 279 status_t Camera3ZslStream::enqueueInputBufferByTimestamp( 280 nsecs_t timestamp, 281 nsecs_t* actualTimestamp) { 282 283 Mutex::Autolock l(mLock); 284 285 TimestampFinder timestampFinder = TimestampFinder(timestamp); 286 287 sp<RingBufferConsumer::PinnedBufferItem> pinnedBuffer = 288 mProducer->pinSelectedBuffer(timestampFinder, 289 /*waitForFence*/false); 290 291 if (pinnedBuffer == 0) { 292 ALOGE("%s: No ZSL buffers were available yet", __FUNCTION__); 293 return NO_BUFFER_AVAILABLE; 294 } 295 296 nsecs_t actual = pinnedBuffer->getBufferItem().mTimestamp; 297 298 if (actual != timestamp) { 299 ALOGW("%s: ZSL buffer candidate search didn't find an exact match --" 300 " requested timestamp = %lld, actual timestamp = %lld", 301 __FUNCTION__, timestamp, actual); 302 } 303 304 mInputBufferQueue.push_back(pinnedBuffer); 305 306 if (actualTimestamp != NULL) { 307 *actualTimestamp = actual; 308 } 309 310 return OK; 311 } 312 313 status_t Camera3ZslStream::clearInputRingBuffer() { 314 Mutex::Autolock l(mLock); 315 316 mInputBufferQueue.clear(); 317 318 return mProducer->clear(); 319 } 320 321 status_t Camera3ZslStream::setTransform(int /*transform*/) { 322 ALOGV("%s: Not implemented", __FUNCTION__); 323 return INVALID_OPERATION; 324 } 325 326 }; // namespace camera3 327 328 }; // namespace android 329