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 res = mConsumer->dequeueBuffer(mConsumer.get(), &anb, &fenceFd); 96 if (res != OK) { 97 ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)", 98 __FUNCTION__, mId, strerror(-res), res); 99 return res; 100 } 101 102 /** 103 * FenceFD now owned by HAL except in case of error, 104 * in which case we reassign it to acquire_fence 105 */ 106 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 107 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK); 108 109 return OK; 110 } 111 112 status_t Camera3OutputStream::returnBufferLocked( 113 const camera3_stream_buffer &buffer, 114 nsecs_t timestamp) { 115 ATRACE_CALL(); 116 117 status_t res = returnAnyBufferLocked(buffer, timestamp, /*output*/true); 118 119 if (res != OK) { 120 return res; 121 } 122 123 mLastTimestamp = timestamp; 124 125 return OK; 126 } 127 128 status_t Camera3OutputStream::returnBufferCheckedLocked( 129 const camera3_stream_buffer &buffer, 130 nsecs_t timestamp, 131 bool output, 132 /*out*/ 133 sp<Fence> *releaseFenceOut) { 134 135 (void)output; 136 ALOG_ASSERT(output, "Expected output to be true"); 137 138 status_t res; 139 sp<Fence> releaseFence; 140 141 /** 142 * Fence management - calculate Release Fence 143 */ 144 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 145 if (buffer.release_fence != -1) { 146 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " 147 "there is an error", __FUNCTION__, mId, buffer.release_fence); 148 close(buffer.release_fence); 149 } 150 151 /** 152 * Reassign release fence as the acquire fence in case of error 153 */ 154 releaseFence = new Fence(buffer.acquire_fence); 155 } else { 156 res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp); 157 if (res != OK) { 158 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)", 159 __FUNCTION__, mId, strerror(-res), res); 160 return res; 161 } 162 163 releaseFence = new Fence(buffer.release_fence); 164 } 165 166 int anwReleaseFence = releaseFence->dup(); 167 168 /** 169 * Release the lock briefly to avoid deadlock with 170 * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this 171 * thread will go into StreamingProcessor::onFrameAvailable) during 172 * queueBuffer 173 */ 174 sp<ANativeWindow> currentConsumer = mConsumer; 175 mLock.unlock(); 176 177 /** 178 * Return buffer back to ANativeWindow 179 */ 180 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 181 // Cancel buffer 182 res = currentConsumer->cancelBuffer(currentConsumer.get(), 183 container_of(buffer.buffer, ANativeWindowBuffer, handle), 184 anwReleaseFence); 185 if (res != OK) { 186 ALOGE("%s: Stream %d: Error cancelling buffer to native window:" 187 " %s (%d)", __FUNCTION__, mId, strerror(-res), res); 188 } 189 } else { 190 res = currentConsumer->queueBuffer(currentConsumer.get(), 191 container_of(buffer.buffer, ANativeWindowBuffer, handle), 192 anwReleaseFence); 193 if (res != OK) { 194 ALOGE("%s: Stream %d: Error queueing buffer to native window: " 195 "%s (%d)", __FUNCTION__, mId, strerror(-res), res); 196 } 197 } 198 mLock.lock(); 199 if (res != OK) { 200 close(anwReleaseFence); 201 return res; 202 } 203 204 *releaseFenceOut = releaseFence; 205 206 return OK; 207 } 208 209 void Camera3OutputStream::dump(int fd, const Vector<String16> &args) const { 210 (void) args; 211 String8 lines; 212 lines.appendFormat(" Stream[%d]: Output\n", mId); 213 write(fd, lines.string(), lines.size()); 214 215 Camera3IOStreamBase::dump(fd, args); 216 } 217 218 status_t Camera3OutputStream::setTransform(int transform) { 219 ATRACE_CALL(); 220 Mutex::Autolock l(mLock); 221 return setTransformLocked(transform); 222 } 223 224 status_t Camera3OutputStream::setTransformLocked(int transform) { 225 status_t res = OK; 226 if (mState == STATE_ERROR) { 227 ALOGE("%s: Stream in error state", __FUNCTION__); 228 return INVALID_OPERATION; 229 } 230 231 mTransform = transform; 232 if (mState == STATE_CONFIGURED) { 233 res = native_window_set_buffers_transform(mConsumer.get(), 234 transform); 235 if (res != OK) { 236 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", 237 __FUNCTION__, transform, strerror(-res), res); 238 } 239 } 240 return res; 241 } 242 243 status_t Camera3OutputStream::configureQueueLocked() { 244 status_t res; 245 246 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 247 return res; 248 } 249 250 ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL"); 251 252 // Configure consumer-side ANativeWindow interface 253 res = native_window_api_connect(mConsumer.get(), 254 NATIVE_WINDOW_API_CAMERA); 255 if (res != OK) { 256 ALOGE("%s: Unable to connect to native window for stream %d", 257 __FUNCTION__, mId); 258 return res; 259 } 260 261 res = native_window_set_usage(mConsumer.get(), camera3_stream::usage); 262 if (res != OK) { 263 ALOGE("%s: Unable to configure usage %08x for stream %d", 264 __FUNCTION__, camera3_stream::usage, mId); 265 return res; 266 } 267 268 res = native_window_set_scaling_mode(mConsumer.get(), 269 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 270 if (res != OK) { 271 ALOGE("%s: Unable to configure stream scaling: %s (%d)", 272 __FUNCTION__, strerror(-res), res); 273 return res; 274 } 275 276 if (mMaxSize == 0) { 277 // For buffers of known size 278 res = native_window_set_buffers_geometry(mConsumer.get(), 279 camera3_stream::width, camera3_stream::height, 280 camera3_stream::format); 281 } else { 282 // For buffers with bounded size 283 res = native_window_set_buffers_geometry(mConsumer.get(), 284 mMaxSize, 1, 285 camera3_stream::format); 286 } 287 if (res != OK) { 288 ALOGE("%s: Unable to configure stream buffer geometry" 289 " %d x %d, format %x for stream %d", 290 __FUNCTION__, camera3_stream::width, camera3_stream::height, 291 camera3_stream::format, mId); 292 return res; 293 } 294 295 int maxConsumerBuffers; 296 res = mConsumer->query(mConsumer.get(), 297 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); 298 if (res != OK) { 299 ALOGE("%s: Unable to query consumer undequeued" 300 " buffer count for stream %d", __FUNCTION__, mId); 301 return res; 302 } 303 304 ALOGV("%s: Consumer wants %d buffers", __FUNCTION__, 305 maxConsumerBuffers); 306 307 mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers; 308 mDequeuedBufferCount = 0; 309 mFrameCount = 0; 310 mLastTimestamp = 0; 311 312 res = native_window_set_buffer_count(mConsumer.get(), 313 mTotalBufferCount); 314 if (res != OK) { 315 ALOGE("%s: Unable to set buffer count for stream %d", 316 __FUNCTION__, mId); 317 return res; 318 } 319 320 res = native_window_set_buffers_transform(mConsumer.get(), 321 mTransform); 322 if (res != OK) { 323 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", 324 __FUNCTION__, mTransform, strerror(-res), res); 325 } 326 327 return OK; 328 } 329 330 status_t Camera3OutputStream::disconnectLocked() { 331 status_t res; 332 333 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { 334 return res; 335 } 336 337 res = native_window_api_disconnect(mConsumer.get(), 338 NATIVE_WINDOW_API_CAMERA); 339 340 /** 341 * This is not an error. if client calling process dies, the window will 342 * also die and all calls to it will return DEAD_OBJECT, thus it's already 343 * "disconnected" 344 */ 345 if (res == DEAD_OBJECT) { 346 ALOGW("%s: While disconnecting stream %d from native window, the" 347 " native window died from under us", __FUNCTION__, mId); 348 } 349 else if (res != OK) { 350 ALOGE("%s: Unable to disconnect stream %d from native window " 351 "(error %d %s)", 352 __FUNCTION__, mId, res, strerror(-res)); 353 mState = STATE_ERROR; 354 return res; 355 } 356 357 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG 358 : STATE_CONSTRUCTED; 359 return OK; 360 } 361 362 }; // namespace camera3 363 364 }; // namespace android 365