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