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 21#include <gui/BufferItem.h> 22#include <utils/Log.h> 23#include <utils/Trace.h> 24#include "Camera3InputStream.h" 25 26namespace android { 27 28namespace camera3 { 29 30Camera3InputStream::Camera3InputStream(int id, 31 uint32_t width, uint32_t height, int format) : 32 Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0, 33 format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0) { 34 35 if (format == HAL_PIXEL_FORMAT_BLOB) { 36 ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); 37 mState = STATE_ERROR; 38 } 39} 40 41Camera3InputStream::~Camera3InputStream() { 42 disconnectLocked(); 43} 44 45status_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 58 if ((res = getBufferPreconditionCheckLocked()) != OK) { 59 return res; 60 } 61 62 ANativeWindowBuffer* anb; 63 int fenceFd; 64 65 assert(mConsumer != 0); 66 67 BufferItem bufferItem; 68 69 res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false); 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(); 79 80 /** 81 * FenceFD now owned by HAL except in case of error, 82 * in which case we reassign it to acquire_fence 83 */ 84 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 85 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false); 86 mBuffersInFlight.push_back(bufferItem); 87 88 mFrameCount++; 89 mLastTimestamp = bufferItem.mTimestamp; 90 91 return OK; 92} 93 94status_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 105 status_t res; 106 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); 122 break; 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); 155 } 156 157 *releaseFenceOut = releaseFence; 158 159 return res; 160} 161 162status_t Camera3InputStream::returnInputBufferLocked( 163 const camera3_stream_buffer &buffer) { 164 ATRACE_CALL(); 165 166 return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false); 167} 168 169status_t Camera3InputStream::getInputBufferProducerLocked( 170 sp<IGraphicBufferProducer> *producer) { 171 ATRACE_CALL(); 172 173 if (producer == NULL) { 174 return BAD_VALUE; 175 } else if (mProducer == NULL) { 176 ALOGE("%s: No input stream is configured", __FUNCTION__); 177 return INVALID_OPERATION; 178 } 179 180 *producer = mProducer; 181 return OK; 182} 183 184status_t Camera3InputStream::disconnectLocked() { 185 186 status_t res; 187 188 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { 189 return res; 190 } 191 192 assert(mBuffersInFlight.size() == 0); 193 194 mConsumer->abandon(); 195 196 /** 197 * no-op since we can't disconnect the producer from the consumer-side 198 */ 199 200 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG 201 : STATE_CONSTRUCTED; 202 return OK; 203} 204 205void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { 206 (void) args; 207 String8 lines; 208 lines.appendFormat(" Stream[%d]: Input\n", mId); 209 write(fd, lines.string(), lines.size()); 210 211 Camera3IOStreamBase::dump(fd, args); 212} 213 214status_t Camera3InputStream::configureQueueLocked() { 215 status_t res; 216 217 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 218 return res; 219 } 220 221 assert(mMaxSize == 0); 222 assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); 223 224 mHandoutTotalBufferCount = 0; 225 mFrameCount = 0; 226 mLastTimestamp = 0; 227 228 if (mConsumer.get() == 0) { 229 sp<IGraphicBufferProducer> producer; 230 sp<IGraphicBufferConsumer> consumer; 231 BufferQueue::createBufferQueue(&producer, &consumer); 232 233 int minUndequeuedBuffers = 0; 234 res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers); 235 if (res != OK || minUndequeuedBuffers < 0) { 236 ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)", 237 __FUNCTION__, mId, res, minUndequeuedBuffers); 238 return res; 239 } 240 size_t minBufs = static_cast<size_t>(minUndequeuedBuffers); 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 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 261 mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage, 262 mTotalBufferCount); 263 mConsumer->setName(String8::format("Camera3-InputStream-%d", mId)); 264 265 mProducer = producer; 266 267 mConsumer->setBufferFreedListener(this); 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; 285} 286 287status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) const { 288 // Per HAL3 spec, input streams have 0 for their initial usage field. 289 *usage = 0; 290 return OK; 291} 292 293void 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 304}; // namespace camera3 305 306}; // namespace android 307