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-OutputStream" 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 "Camera3OutputStream.h" 24 25 #ifndef container_of 26 #define container_of(ptr, type, member) \ 27 (type *)((char*)(ptr) - offsetof(type, member)) 28 #endif 29 30 namespace android { 31 32 namespace camera3 { 33 34 Camera3OutputStream::Camera3OutputStream(int id, 35 sp<ANativeWindow> consumer, 36 uint32_t width, uint32_t height, int format) : 37 Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, 38 /*maxSize*/0, format), 39 mConsumer(consumer), 40 mTransform(0) { 41 42 if (mConsumer == NULL) { 43 ALOGE("%s: Consumer is NULL!", __FUNCTION__); 44 mState = STATE_ERROR; 45 } 46 } 47 48 Camera3OutputStream::Camera3OutputStream(int id, 49 sp<ANativeWindow> consumer, 50 uint32_t width, uint32_t height, size_t maxSize, int format) : 51 Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize, 52 format), 53 mConsumer(consumer), 54 mTransform(0) { 55 56 if (format != HAL_PIXEL_FORMAT_BLOB) { 57 ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__, 58 format); 59 mState = STATE_ERROR; 60 } 61 62 if (mConsumer == NULL) { 63 ALOGE("%s: Consumer is NULL!", __FUNCTION__); 64 mState = STATE_ERROR; 65 } 66 } 67 68 Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type, 69 uint32_t width, uint32_t height, 70 int format) : 71 Camera3IOStreamBase(id, type, width, height, 72 /*maxSize*/0, 73 format), 74 mTransform(0) { 75 76 // Subclasses expected to initialize mConsumer themselves 77 } 78 79 80 Camera3OutputStream::~Camera3OutputStream() { 81 disconnectLocked(); 82 } 83 84 status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) { 85 ATRACE_CALL(); 86 status_t res; 87 88 if ((res = getBufferPreconditionCheckLocked()) != OK) { 89 return res; 90 } 91 92 ANativeWindowBuffer* anb; 93 int fenceFd; 94 95 /** 96 * Release the lock briefly to avoid deadlock for below scenario: 97 * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring(). 98 * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock. 99 * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable(). 100 * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock 101 * StreamingProcessor lock. 102 * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock 103 * and try to lock bufferQueue lock. 104 * Then there is circular locking dependency. 105 */ 106 sp<ANativeWindow> currentConsumer = mConsumer; 107 mLock.unlock(); 108 109 res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd); 110 mLock.lock(); 111 if (res != OK) { 112 ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)", 113 __FUNCTION__, mId, strerror(-res), res); 114 return res; 115 } 116 117 /** 118 * FenceFD now owned by HAL except in case of error, 119 * in which case we reassign it to acquire_fence 120 */ 121 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 122 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK); 123 124 return OK; 125 } 126 127 status_t Camera3OutputStream::returnBufferLocked( 128 const camera3_stream_buffer &buffer, 129 nsecs_t timestamp) { 130 ATRACE_CALL(); 131 132 status_t res = returnAnyBufferLocked(buffer, timestamp, /*output*/true); 133 134 if (res != OK) { 135 return res; 136 } 137 138 mLastTimestamp = timestamp; 139 140 return OK; 141 } 142 143 status_t Camera3OutputStream::returnBufferCheckedLocked( 144 const camera3_stream_buffer &buffer, 145 nsecs_t timestamp, 146 bool output, 147 /*out*/ 148 sp<Fence> *releaseFenceOut) { 149 150 (void)output; 151 ALOG_ASSERT(output, "Expected output to be true"); 152 153 status_t res; 154 sp<Fence> releaseFence; 155 156 /** 157 * Fence management - calculate Release Fence 158 */ 159 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 160 if (buffer.release_fence != -1) { 161 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " 162 "there is an error", __FUNCTION__, mId, buffer.release_fence); 163 close(buffer.release_fence); 164 } 165 166 /** 167 * Reassign release fence as the acquire fence in case of error 168 */ 169 releaseFence = new Fence(buffer.acquire_fence); 170 } else { 171 res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp); 172 if (res != OK) { 173 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)", 174 __FUNCTION__, mId, strerror(-res), res); 175 return res; 176 } 177 178 releaseFence = new Fence(buffer.release_fence); 179 } 180 181 int anwReleaseFence = releaseFence->dup(); 182 183 /** 184 * Release the lock briefly to avoid deadlock with 185 * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this 186 * thread will go into StreamingProcessor::onFrameAvailable) during 187 * queueBuffer 188 */ 189 sp<ANativeWindow> currentConsumer = mConsumer; 190 mLock.unlock(); 191 192 /** 193 * Return buffer back to ANativeWindow 194 */ 195 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 196 // Cancel buffer 197 res = currentConsumer->cancelBuffer(currentConsumer.get(), 198 container_of(buffer.buffer, ANativeWindowBuffer, handle), 199 anwReleaseFence); 200 if (res != OK) { 201 ALOGE("%s: Stream %d: Error cancelling buffer to native window:" 202 " %s (%d)", __FUNCTION__, mId, strerror(-res), res); 203 } 204 } else { 205 res = currentConsumer->queueBuffer(currentConsumer.get(), 206 container_of(buffer.buffer, ANativeWindowBuffer, handle), 207 anwReleaseFence); 208 if (res != OK) { 209 ALOGE("%s: Stream %d: Error queueing buffer to native window: " 210 "%s (%d)", __FUNCTION__, mId, strerror(-res), res); 211 } 212 } 213 mLock.lock(); 214 if (res != OK) { 215 close(anwReleaseFence); 216 } 217 218 *releaseFenceOut = releaseFence; 219 220 return res; 221 } 222 223 void Camera3OutputStream::dump(int fd, const Vector<String16> &args) const { 224 (void) args; 225 String8 lines; 226 lines.appendFormat(" Stream[%d]: Output\n", mId); 227 write(fd, lines.string(), lines.size()); 228 229 Camera3IOStreamBase::dump(fd, args); 230 } 231 232 status_t Camera3OutputStream::setTransform(int transform) { 233 ATRACE_CALL(); 234 Mutex::Autolock l(mLock); 235 return setTransformLocked(transform); 236 } 237 238 status_t Camera3OutputStream::setTransformLocked(int transform) { 239 status_t res = OK; 240 if (mState == STATE_ERROR) { 241 ALOGE("%s: Stream in error state", __FUNCTION__); 242 return INVALID_OPERATION; 243 } 244 245 mTransform = transform; 246 if (mState == STATE_CONFIGURED) { 247 res = native_window_set_buffers_transform(mConsumer.get(), 248 transform); 249 if (res != OK) { 250 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", 251 __FUNCTION__, transform, strerror(-res), res); 252 } 253 } 254 return res; 255 } 256 257 status_t Camera3OutputStream::configureQueueLocked() { 258 status_t res; 259 260 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 261 return res; 262 } 263 264 ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL"); 265 266 // Configure consumer-side ANativeWindow interface 267 res = native_window_api_connect(mConsumer.get(), 268 NATIVE_WINDOW_API_CAMERA); 269 if (res != OK) { 270 ALOGE("%s: Unable to connect to native window for stream %d", 271 __FUNCTION__, mId); 272 return res; 273 } 274 275 res = native_window_set_usage(mConsumer.get(), camera3_stream::usage); 276 if (res != OK) { 277 ALOGE("%s: Unable to configure usage %08x for stream %d", 278 __FUNCTION__, camera3_stream::usage, mId); 279 return res; 280 } 281 282 res = native_window_set_scaling_mode(mConsumer.get(), 283 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 284 if (res != OK) { 285 ALOGE("%s: Unable to configure stream scaling: %s (%d)", 286 __FUNCTION__, strerror(-res), res); 287 return res; 288 } 289 290 if (mMaxSize == 0) { 291 // For buffers of known size 292 res = native_window_set_buffers_geometry(mConsumer.get(), 293 camera3_stream::width, camera3_stream::height, 294 camera3_stream::format); 295 } else { 296 // For buffers with bounded size 297 res = native_window_set_buffers_geometry(mConsumer.get(), 298 mMaxSize, 1, 299 camera3_stream::format); 300 } 301 if (res != OK) { 302 ALOGE("%s: Unable to configure stream buffer geometry" 303 " %d x %d, format %x for stream %d", 304 __FUNCTION__, camera3_stream::width, camera3_stream::height, 305 camera3_stream::format, mId); 306 return res; 307 } 308 309 int maxConsumerBuffers; 310 res = mConsumer->query(mConsumer.get(), 311 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); 312 if (res != OK) { 313 ALOGE("%s: Unable to query consumer undequeued" 314 " buffer count for stream %d", __FUNCTION__, mId); 315 return res; 316 } 317 318 ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__, 319 maxConsumerBuffers, camera3_stream::max_buffers); 320 if (camera3_stream::max_buffers == 0) { 321 ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1", 322 __FUNCTION__, camera3_stream::max_buffers); 323 return INVALID_OPERATION; 324 } 325 326 mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers; 327 mDequeuedBufferCount = 0; 328 mFrameCount = 0; 329 mLastTimestamp = 0; 330 331 res = native_window_set_buffer_count(mConsumer.get(), 332 mTotalBufferCount); 333 if (res != OK) { 334 ALOGE("%s: Unable to set buffer count for stream %d", 335 __FUNCTION__, mId); 336 return res; 337 } 338 339 res = native_window_set_buffers_transform(mConsumer.get(), 340 mTransform); 341 if (res != OK) { 342 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", 343 __FUNCTION__, mTransform, strerror(-res), res); 344 } 345 346 return OK; 347 } 348 349 status_t Camera3OutputStream::disconnectLocked() { 350 status_t res; 351 352 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { 353 return res; 354 } 355 356 res = native_window_api_disconnect(mConsumer.get(), 357 NATIVE_WINDOW_API_CAMERA); 358 359 /** 360 * This is not an error. if client calling process dies, the window will 361 * also die and all calls to it will return DEAD_OBJECT, thus it's already 362 * "disconnected" 363 */ 364 if (res == DEAD_OBJECT) { 365 ALOGW("%s: While disconnecting stream %d from native window, the" 366 " native window died from under us", __FUNCTION__, mId); 367 } 368 else if (res != OK) { 369 ALOGE("%s: Unable to disconnect stream %d from native window " 370 "(error %d %s)", 371 __FUNCTION__, mId, res, strerror(-res)); 372 mState = STATE_ERROR; 373 return res; 374 } 375 376 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG 377 : STATE_CONSTRUCTED; 378 return OK; 379 } 380 381 status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) { 382 383 status_t res; 384 int32_t u = 0; 385 res = mConsumer->query(mConsumer.get(), 386 NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u); 387 *usage = u; 388 389 return res; 390 } 391 392 }; // namespace camera3 393 394 }; // namespace android 395