| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 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-InputStream" | 
|  | 18 | #define ATRACE_TAG ATRACE_TAG_CAMERA | 
|  | 19 | //#define LOG_NDEBUG 0 | 
|  | 20 |  | 
| Dan Stoza | 549e735 | 2015-03-12 15:21:16 -0700 | [diff] [blame] | 21 | #include <gui/BufferItem.h> | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 22 | #include <utils/Log.h> | 
|  | 23 | #include <utils/Trace.h> | 
|  | 24 | #include "Camera3InputStream.h" | 
|  | 25 |  | 
|  | 26 | namespace android { | 
|  | 27 |  | 
|  | 28 | namespace camera3 { | 
|  | 29 |  | 
|  | 30 | Camera3InputStream::Camera3InputStream(int id, | 
|  | 31 | uint32_t width, uint32_t height, int format) : | 
| Yin-Chia Yeh | b97babb | 2015-03-12 13:42:44 -0700 | [diff] [blame] | 32 | Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0, | 
|  | 33 | format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0) { | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 34 |  | 
|  | 35 | if (format == HAL_PIXEL_FORMAT_BLOB) { | 
|  | 36 | ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); | 
|  | 37 | mState = STATE_ERROR; | 
|  | 38 | } | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 39 | } | 
|  | 40 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 41 | Camera3InputStream::~Camera3InputStream() { | 
|  | 42 | disconnectLocked(); | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 43 | } | 
|  | 44 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 45 | status_t Camera3InputStream::getInputBufferLocked( | 
|  | 46 | camera3_stream_buffer *buffer) { | 
|  | 47 | ATRACE_CALL(); | 
|  | 48 | status_t res; | 
|  | 49 |  | 
|  | 50 | // FIXME: will not work in (re-)registration | 
|  | 51 | if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) { | 
|  | 52 | ALOGE("%s: Stream %d: Buffer registration for input streams" | 
|  | 53 | " not implemented (state %d)", | 
|  | 54 | __FUNCTION__, mId, mState); | 
|  | 55 | return INVALID_OPERATION; | 
|  | 56 | } | 
|  | 57 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 58 | if ((res = getBufferPreconditionCheckLocked()) != OK) { | 
|  | 59 | return res; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 60 | } | 
|  | 61 |  | 
|  | 62 | ANativeWindowBuffer* anb; | 
|  | 63 | int fenceFd; | 
|  | 64 |  | 
|  | 65 | assert(mConsumer != 0); | 
|  | 66 |  | 
|  | 67 | BufferItem bufferItem; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 68 |  | 
| Chien-Yu Chen | 618ff8a | 2015-03-13 11:27:17 -0700 | [diff] [blame] | 69 | res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 70 | if (res != OK) { | 
|  | 71 | ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)", | 
|  | 72 | __FUNCTION__, mId, strerror(-res), res); | 
|  | 73 | return res; | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | anb = bufferItem.mGraphicBuffer->getNativeBuffer(); | 
|  | 77 | assert(anb != NULL); | 
|  | 78 | fenceFd = bufferItem.mFence->dup(); | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 79 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 80 | /** | 
|  | 81 | * FenceFD now owned by HAL except in case of error, | 
|  | 82 | * in which case we reassign it to acquire_fence | 
|  | 83 | */ | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 84 | handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, | 
| Zhijun He | 6adc9cc | 2014-04-15 14:09:55 -0700 | [diff] [blame] | 85 | /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 86 | mBuffersInFlight.push_back(bufferItem); | 
|  | 87 |  | 
| Eino-Ville Talvala | c31dc7e | 2017-01-31 17:35:41 -0800 | [diff] [blame] | 88 | mFrameCount++; | 
|  | 89 | mLastTimestamp = bufferItem.mTimestamp; | 
|  | 90 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 91 | return OK; | 
|  | 92 | } | 
|  | 93 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 94 | status_t Camera3InputStream::returnBufferCheckedLocked( | 
|  | 95 | const camera3_stream_buffer &buffer, | 
|  | 96 | nsecs_t timestamp, | 
|  | 97 | bool output, | 
|  | 98 | /*out*/ | 
|  | 99 | sp<Fence> *releaseFenceOut) { | 
|  | 100 |  | 
|  | 101 | (void)timestamp; | 
|  | 102 | (void)output; | 
|  | 103 | ALOG_ASSERT(!output, "Expected output to be false"); | 
|  | 104 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 105 | status_t res; | 
|  | 106 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 107 | bool bufferFound = false; | 
|  | 108 | BufferItem bufferItem; | 
|  | 109 | { | 
|  | 110 | // Find the buffer we are returning | 
|  | 111 | Vector<BufferItem>::iterator it, end; | 
|  | 112 | for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end(); | 
|  | 113 | it != end; | 
|  | 114 | ++it) { | 
|  | 115 |  | 
|  | 116 | const BufferItem& tmp = *it; | 
|  | 117 | ANativeWindowBuffer *anb = tmp.mGraphicBuffer->getNativeBuffer(); | 
|  | 118 | if (anb != NULL && &(anb->handle) == buffer.buffer) { | 
|  | 119 | bufferFound = true; | 
|  | 120 | bufferItem = tmp; | 
|  | 121 | mBuffersInFlight.erase(it); | 
| Eino-Ville Talvala | 05a8cf5 | 2016-03-28 14:08:56 -0700 | [diff] [blame] | 122 | break; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 123 | } | 
|  | 124 | } | 
|  | 125 | } | 
|  | 126 | if (!bufferFound) { | 
|  | 127 | ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL", | 
|  | 128 | __FUNCTION__, mId); | 
|  | 129 | return INVALID_OPERATION; | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { | 
|  | 133 | if (buffer.release_fence != -1) { | 
|  | 134 | ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " | 
|  | 135 | "there is an error", __FUNCTION__, mId, buffer.release_fence); | 
|  | 136 | close(buffer.release_fence); | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | /** | 
|  | 140 | * Reassign release fence as the acquire fence incase of error | 
|  | 141 | */ | 
|  | 142 | const_cast<camera3_stream_buffer*>(&buffer)->release_fence = | 
|  | 143 | buffer.acquire_fence; | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | /** | 
|  | 147 | * Unconditionally return buffer to the buffer queue. | 
|  | 148 | * - Fwk takes over the release_fence ownership | 
|  | 149 | */ | 
|  | 150 | sp<Fence> releaseFence = new Fence(buffer.release_fence); | 
|  | 151 | res = mConsumer->releaseBuffer(bufferItem, releaseFence); | 
|  | 152 | if (res != OK) { | 
|  | 153 | ALOGE("%s: Stream %d: Error releasing buffer back to buffer queue:" | 
|  | 154 | " %s (%d)", __FUNCTION__, mId, strerror(-res), res); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 155 | } | 
|  | 156 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 157 | *releaseFenceOut = releaseFence; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 158 |  | 
| Eino-Ville Talvala | f1e98d8 | 2013-09-06 09:32:43 -0700 | [diff] [blame] | 159 | return res; | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 160 | } | 
|  | 161 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 162 | status_t Camera3InputStream::returnInputBufferLocked( | 
|  | 163 | const camera3_stream_buffer &buffer) { | 
|  | 164 | ATRACE_CALL(); | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 165 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 166 | return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false); | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 167 | } | 
|  | 168 |  | 
| Chien-Yu Chen | 618ff8a | 2015-03-13 11:27:17 -0700 | [diff] [blame] | 169 | status_t Camera3InputStream::getInputBufferProducerLocked( | 
|  | 170 | sp<IGraphicBufferProducer> *producer) { | 
|  | 171 | ATRACE_CALL(); | 
|  | 172 |  | 
|  | 173 | if (producer == NULL) { | 
|  | 174 | return BAD_VALUE; | 
|  | 175 | } else if (mProducer == NULL) { | 
| Zhijun He | 125684a | 2015-12-26 15:07:30 -0800 | [diff] [blame] | 176 | ALOGE("%s: No input stream is configured", __FUNCTION__); | 
| Chien-Yu Chen | 618ff8a | 2015-03-13 11:27:17 -0700 | [diff] [blame] | 177 | return INVALID_OPERATION; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | *producer = mProducer; | 
|  | 181 | return OK; | 
|  | 182 | } | 
|  | 183 |  | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 184 | status_t Camera3InputStream::disconnectLocked() { | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 185 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 186 | status_t res; | 
|  | 187 |  | 
|  | 188 | if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { | 
|  | 189 | return res; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 190 | } | 
|  | 191 |  | 
|  | 192 | assert(mBuffersInFlight.size() == 0); | 
|  | 193 |  | 
| Chien-Yu Chen | ed0412e | 2015-04-27 15:04:22 -0700 | [diff] [blame] | 194 | mConsumer->abandon(); | 
|  | 195 |  | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 196 | /** | 
|  | 197 | *  no-op since we can't disconnect the producer from the consumer-side | 
|  | 198 | */ | 
|  | 199 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 200 | mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG | 
|  | 201 | : STATE_CONSTRUCTED; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 202 | return OK; | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 203 | } | 
|  | 204 |  | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 205 | void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 206 | (void) args; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 207 | String8 lines; | 
|  | 208 | lines.appendFormat("    Stream[%d]: Input\n", mId); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 209 | write(fd, lines.string(), lines.size()); | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 210 |  | 
|  | 211 | Camera3IOStreamBase::dump(fd, args); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 212 | } | 
|  | 213 |  | 
|  | 214 | status_t Camera3InputStream::configureQueueLocked() { | 
|  | 215 | status_t res; | 
|  | 216 |  | 
| Igor Murashkin | ae3d0ba | 2013-05-08 18:03:15 -0700 | [diff] [blame] | 217 | if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { | 
|  | 218 | return res; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 219 | } | 
|  | 220 |  | 
|  | 221 | assert(mMaxSize == 0); | 
|  | 222 | assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); | 
|  | 223 |  | 
| Zhijun He | 6adc9cc | 2014-04-15 14:09:55 -0700 | [diff] [blame] | 224 | mHandoutTotalBufferCount = 0; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 225 | mFrameCount = 0; | 
| Eino-Ville Talvala | c31dc7e | 2017-01-31 17:35:41 -0800 | [diff] [blame] | 226 | mLastTimestamp = 0; | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 227 |  | 
|  | 228 | if (mConsumer.get() == 0) { | 
| Dan Stoza | 8aa0f06 | 2014-03-12 14:31:05 -0700 | [diff] [blame] | 229 | sp<IGraphicBufferProducer> producer; | 
|  | 230 | sp<IGraphicBufferConsumer> consumer; | 
|  | 231 | BufferQueue::createBufferQueue(&producer, &consumer); | 
| Igor Murashkin | 054aab3 | 2013-11-18 11:39:27 -0800 | [diff] [blame] | 232 |  | 
|  | 233 | int minUndequeuedBuffers = 0; | 
| Dan Stoza | 8aa0f06 | 2014-03-12 14:31:05 -0700 | [diff] [blame] | 234 | res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers); | 
| Igor Murashkin | 054aab3 | 2013-11-18 11:39:27 -0800 | [diff] [blame] | 235 | if (res != OK || minUndequeuedBuffers < 0) { | 
|  | 236 | ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)", | 
| Chien-Yu Chen | 618ff8a | 2015-03-13 11:27:17 -0700 | [diff] [blame] | 237 | __FUNCTION__, mId, res, minUndequeuedBuffers); | 
| Igor Murashkin | 054aab3 | 2013-11-18 11:39:27 -0800 | [diff] [blame] | 238 | return res; | 
|  | 239 | } | 
|  | 240 | size_t minBufs = static_cast<size_t>(minUndequeuedBuffers); | 
| Chien-Yu Chen | 618ff8a | 2015-03-13 11:27:17 -0700 | [diff] [blame] | 241 |  | 
|  | 242 | if (camera3_stream::max_buffers == 0) { | 
|  | 243 | ALOGE("%s: %d: HAL sets max_buffer to 0. Must be at least 1.", | 
|  | 244 | __FUNCTION__, __LINE__); | 
|  | 245 | return INVALID_OPERATION; | 
|  | 246 | } | 
|  | 247 |  | 
| Igor Murashkin | 054aab3 | 2013-11-18 11:39:27 -0800 | [diff] [blame] | 248 | /* | 
|  | 249 | * We promise never to 'acquire' more than camera3_stream::max_buffers | 
|  | 250 | * at any one time. | 
|  | 251 | * | 
|  | 252 | * Boost the number up to meet the minimum required buffer count. | 
|  | 253 | * | 
|  | 254 | * (Note that this sets consumer-side buffer count only, | 
|  | 255 | * and not the sum of producer+consumer side as in other camera streams). | 
|  | 256 | */ | 
|  | 257 | mTotalBufferCount = camera3_stream::max_buffers > minBufs ? | 
|  | 258 | camera3_stream::max_buffers : minBufs; | 
|  | 259 | // TODO: somehow set the total buffer count when producer connects? | 
|  | 260 |  | 
| Dan Stoza | 8aa0f06 | 2014-03-12 14:31:05 -0700 | [diff] [blame] | 261 | mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage, | 
| Mathias Agopian | 5e1f08b | 2013-07-16 22:54:39 -0700 | [diff] [blame] | 262 | mTotalBufferCount); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 263 | mConsumer->setName(String8::format("Camera3-InputStream-%d", mId)); | 
| Chien-Yu Chen | 618ff8a | 2015-03-13 11:27:17 -0700 | [diff] [blame] | 264 |  | 
|  | 265 | mProducer = producer; | 
| Yin-Chia Yeh | be83fa7 | 2017-03-30 13:35:36 -0700 | [diff] [blame] | 266 |  | 
|  | 267 | mConsumer->setBufferFreedListener(this); | 
| Igor Murashkin | 0776a14 | 2013-04-15 14:59:22 -0700 | [diff] [blame] | 268 | } | 
|  | 269 |  | 
|  | 270 | res = mConsumer->setDefaultBufferSize(camera3_stream::width, | 
|  | 271 | camera3_stream::height); | 
|  | 272 | if (res != OK) { | 
|  | 273 | ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d", | 
|  | 274 | __FUNCTION__, mId, camera3_stream::width, camera3_stream::height); | 
|  | 275 | return res; | 
|  | 276 | } | 
|  | 277 | res = mConsumer->setDefaultBufferFormat(camera3_stream::format); | 
|  | 278 | if (res != OK) { | 
|  | 279 | ALOGE("%s: Stream %d: Could not set buffer format %d", | 
|  | 280 | __FUNCTION__, mId, camera3_stream::format); | 
|  | 281 | return res; | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | return OK; | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 285 | } | 
|  | 286 |  | 
| Eino-Ville Talvala | 4d44cad | 2015-04-11 13:15:45 -0700 | [diff] [blame] | 287 | status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) const { | 
| Eino-Ville Talvala | b2f5b19 | 2013-07-30 14:36:03 -0700 | [diff] [blame] | 288 | // Per HAL3 spec, input streams have 0 for their initial usage field. | 
|  | 289 | *usage = 0; | 
|  | 290 | return OK; | 
|  | 291 | } | 
|  | 292 |  | 
| Yin-Chia Yeh | be83fa7 | 2017-03-30 13:35:36 -0700 | [diff] [blame] | 293 | void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) { | 
|  | 294 | const sp<GraphicBuffer> buffer = gb.promote(); | 
|  | 295 | if (buffer != nullptr) { | 
|  | 296 | if (mBufferFreedListener != nullptr) { | 
|  | 297 | mBufferFreedListener->onBufferFreed(mId, buffer->handle); | 
|  | 298 | } | 
|  | 299 | } else { | 
|  | 300 | ALOGE("%s: GraphicBuffer is freed before onBufferFreed callback finishes!", __FUNCTION__); | 
|  | 301 | } | 
|  | 302 | } | 
|  | 303 |  | 
| Eino-Ville Talvala | 8be20f5 | 2013-03-06 16:20:06 -0800 | [diff] [blame] | 304 | }; // namespace camera3 | 
|  | 305 |  | 
|  | 306 | }; // namespace android |