Camera3InputStream.cpp revision 8aa0f0619ea867e8fb240cf27913d4f8ae767385
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 <utils/Log.h> 22#include <utils/Trace.h> 23#include "Camera3InputStream.h" 24 25namespace android { 26 27namespace camera3 { 28 29Camera3InputStream::Camera3InputStream(int id, 30 uint32_t width, uint32_t height, int format) : 31 Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, 32 /*maxSize*/0, format) { 33 34 if (format == HAL_PIXEL_FORMAT_BLOB) { 35 ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__); 36 mState = STATE_ERROR; 37 } 38} 39 40Camera3InputStream::~Camera3InputStream() { 41 disconnectLocked(); 42} 43 44status_t Camera3InputStream::getInputBufferLocked( 45 camera3_stream_buffer *buffer) { 46 ATRACE_CALL(); 47 status_t res; 48 49 // FIXME: will not work in (re-)registration 50 if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) { 51 ALOGE("%s: Stream %d: Buffer registration for input streams" 52 " not implemented (state %d)", 53 __FUNCTION__, mId, mState); 54 return INVALID_OPERATION; 55 } 56 57 if ((res = getBufferPreconditionCheckLocked()) != OK) { 58 return res; 59 } 60 61 ANativeWindowBuffer* anb; 62 int fenceFd; 63 64 assert(mConsumer != 0); 65 66 BufferItem bufferItem; 67 res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false); 68 69 if (res != OK) { 70 ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)", 71 __FUNCTION__, mId, strerror(-res), res); 72 return res; 73 } 74 75 anb = bufferItem.mGraphicBuffer->getNativeBuffer(); 76 assert(anb != NULL); 77 fenceFd = bufferItem.mFence->dup(); 78 79 /** 80 * FenceFD now owned by HAL except in case of error, 81 * in which case we reassign it to acquire_fence 82 */ 83 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 84 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK); 85 mBuffersInFlight.push_back(bufferItem); 86 87 return OK; 88} 89 90status_t Camera3InputStream::returnBufferCheckedLocked( 91 const camera3_stream_buffer &buffer, 92 nsecs_t timestamp, 93 bool output, 94 /*out*/ 95 sp<Fence> *releaseFenceOut) { 96 97 (void)timestamp; 98 (void)output; 99 ALOG_ASSERT(!output, "Expected output to be false"); 100 101 status_t res; 102 103 bool bufferFound = false; 104 BufferItem bufferItem; 105 { 106 // Find the buffer we are returning 107 Vector<BufferItem>::iterator it, end; 108 for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end(); 109 it != end; 110 ++it) { 111 112 const BufferItem& tmp = *it; 113 ANativeWindowBuffer *anb = tmp.mGraphicBuffer->getNativeBuffer(); 114 if (anb != NULL && &(anb->handle) == buffer.buffer) { 115 bufferFound = true; 116 bufferItem = tmp; 117 mBuffersInFlight.erase(it); 118 } 119 } 120 } 121 if (!bufferFound) { 122 ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL", 123 __FUNCTION__, mId); 124 return INVALID_OPERATION; 125 } 126 127 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { 128 if (buffer.release_fence != -1) { 129 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when " 130 "there is an error", __FUNCTION__, mId, buffer.release_fence); 131 close(buffer.release_fence); 132 } 133 134 /** 135 * Reassign release fence as the acquire fence incase of error 136 */ 137 const_cast<camera3_stream_buffer*>(&buffer)->release_fence = 138 buffer.acquire_fence; 139 } 140 141 /** 142 * Unconditionally return buffer to the buffer queue. 143 * - Fwk takes over the release_fence ownership 144 */ 145 sp<Fence> releaseFence = new Fence(buffer.release_fence); 146 res = mConsumer->releaseBuffer(bufferItem, releaseFence); 147 if (res != OK) { 148 ALOGE("%s: Stream %d: Error releasing buffer back to buffer queue:" 149 " %s (%d)", __FUNCTION__, mId, strerror(-res), res); 150 } 151 152 *releaseFenceOut = releaseFence; 153 154 return res; 155} 156 157status_t Camera3InputStream::returnInputBufferLocked( 158 const camera3_stream_buffer &buffer) { 159 ATRACE_CALL(); 160 161 return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false); 162} 163 164status_t Camera3InputStream::disconnectLocked() { 165 166 status_t res; 167 168 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) { 169 return res; 170 } 171 172 assert(mBuffersInFlight.size() == 0); 173 174 /** 175 * no-op since we can't disconnect the producer from the consumer-side 176 */ 177 178 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG 179 : STATE_CONSTRUCTED; 180 return OK; 181} 182 183void Camera3InputStream::dump(int fd, const Vector<String16> &args) const { 184 (void) args; 185 String8 lines; 186 lines.appendFormat(" Stream[%d]: Input\n", mId); 187 write(fd, lines.string(), lines.size()); 188 189 Camera3IOStreamBase::dump(fd, args); 190} 191 192status_t Camera3InputStream::configureQueueLocked() { 193 status_t res; 194 195 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 196 return res; 197 } 198 199 assert(mMaxSize == 0); 200 assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); 201 202 mDequeuedBufferCount = 0; 203 mFrameCount = 0; 204 205 if (mConsumer.get() == 0) { 206 sp<IGraphicBufferProducer> producer; 207 sp<IGraphicBufferConsumer> consumer; 208 BufferQueue::createBufferQueue(&producer, &consumer); 209 210 int minUndequeuedBuffers = 0; 211 res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers); 212 if (res != OK || minUndequeuedBuffers < 0) { 213 ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)", 214 __FUNCTION__, mId, res, minUndequeuedBuffers); 215 return res; 216 } 217 size_t minBufs = static_cast<size_t>(minUndequeuedBuffers); 218 /* 219 * We promise never to 'acquire' more than camera3_stream::max_buffers 220 * at any one time. 221 * 222 * Boost the number up to meet the minimum required buffer count. 223 * 224 * (Note that this sets consumer-side buffer count only, 225 * and not the sum of producer+consumer side as in other camera streams). 226 */ 227 mTotalBufferCount = camera3_stream::max_buffers > minBufs ? 228 camera3_stream::max_buffers : minBufs; 229 // TODO: somehow set the total buffer count when producer connects? 230 231 mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage, 232 mTotalBufferCount); 233 mConsumer->setName(String8::format("Camera3-InputStream-%d", mId)); 234 } 235 236 res = mConsumer->setDefaultBufferSize(camera3_stream::width, 237 camera3_stream::height); 238 if (res != OK) { 239 ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d", 240 __FUNCTION__, mId, camera3_stream::width, camera3_stream::height); 241 return res; 242 } 243 res = mConsumer->setDefaultBufferFormat(camera3_stream::format); 244 if (res != OK) { 245 ALOGE("%s: Stream %d: Could not set buffer format %d", 246 __FUNCTION__, mId, camera3_stream::format); 247 return res; 248 } 249 250 return OK; 251} 252 253status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) { 254 // Per HAL3 spec, input streams have 0 for their initial usage field. 255 *usage = 0; 256 return OK; 257} 258 259}; // namespace camera3 260 261}; // namespace android 262