1 /* 2 * Copyright (C) 2016 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 #include "Camera3SharedOutputStream.h" 18 19 namespace android { 20 21 namespace camera3 { 22 23 Camera3SharedOutputStream::Camera3SharedOutputStream(int id, 24 const std::vector<sp<Surface>>& surfaces, 25 uint32_t width, uint32_t height, int format, 26 uint64_t consumerUsage, android_dataspace dataSpace, 27 camera3_stream_rotation_t rotation, 28 nsecs_t timestampOffset, int setId) : 29 Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height, 30 format, dataSpace, rotation, consumerUsage, 31 timestampOffset, setId), 32 mSurfaces(surfaces) { 33 } 34 35 Camera3SharedOutputStream::~Camera3SharedOutputStream() { 36 disconnectLocked(); 37 } 38 39 status_t Camera3SharedOutputStream::connectStreamSplitterLocked() { 40 status_t res = OK; 41 42 mStreamSplitter = new Camera3StreamSplitter(); 43 44 uint64_t usage; 45 getEndpointUsage(&usage); 46 47 res = mStreamSplitter->connect(mSurfaces, usage, camera3_stream::max_buffers, &mConsumer); 48 if (res != OK) { 49 ALOGE("%s: Failed to connect to stream splitter: %s(%d)", 50 __FUNCTION__, strerror(-res), res); 51 return res; 52 } 53 54 return res; 55 } 56 57 status_t Camera3SharedOutputStream::notifyBufferReleased(ANativeWindowBuffer *anwBuffer) { 58 Mutex::Autolock l(mLock); 59 status_t res = OK; 60 const sp<GraphicBuffer> buffer(static_cast<GraphicBuffer*>(anwBuffer)); 61 62 if (mStreamSplitter != nullptr) { 63 res = mStreamSplitter->notifyBufferReleased(buffer); 64 } 65 66 return res; 67 } 68 69 bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const { 70 Mutex::Autolock l(mLock); 71 return (surface_id >= mSurfaces.size()); 72 } 73 74 status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) { 75 Mutex::Autolock l(mLock); 76 if (surfaces.size() == 0) { 77 ALOGE("%s: it's illegal to set zero consumer surfaces!", __FUNCTION__); 78 return INVALID_OPERATION; 79 } 80 81 status_t ret = OK; 82 for (auto& surface : surfaces) { 83 if (surface == nullptr) { 84 ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__); 85 return INVALID_OPERATION; 86 } 87 88 mSurfaces.push_back(surface); 89 90 // Only call addOutput if the splitter has been connected. 91 if (mStreamSplitter != nullptr) { 92 ret = mStreamSplitter->addOutput(surface); 93 if (ret != OK) { 94 ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret); 95 return ret; 96 97 } 98 } 99 } 100 return ret; 101 } 102 103 status_t Camera3SharedOutputStream::getBufferLocked(camera3_stream_buffer *buffer, 104 const std::vector<size_t>& surface_ids) { 105 ANativeWindowBuffer* anb; 106 int fenceFd = -1; 107 108 status_t res; 109 res = getBufferLockedCommon(&anb, &fenceFd); 110 if (res != OK) { 111 return res; 112 } 113 114 // Attach the buffer to the splitter output queues. This could block if 115 // the output queue doesn't have any empty slot. So unlock during the course 116 // of attachBufferToOutputs. 117 sp<Camera3StreamSplitter> splitter = mStreamSplitter; 118 mLock.unlock(); 119 res = splitter->attachBufferToOutputs(anb, surface_ids); 120 mLock.lock(); 121 if (res != OK) { 122 ALOGE("%s: Stream %d: Cannot attach stream splitter buffer to outputs: %s (%d)", 123 __FUNCTION__, mId, strerror(-res), res); 124 // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING, 125 // let prepareNextBuffer handle the error.) 126 if (res == NO_INIT && mState == STATE_CONFIGURED) { 127 mState = STATE_ABANDONED; 128 } 129 130 return res; 131 } 132 133 /** 134 * FenceFD now owned by HAL except in case of error, 135 * in which case we reassign it to acquire_fence 136 */ 137 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd, 138 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true); 139 140 return OK; 141 } 142 143 status_t Camera3SharedOutputStream::queueBufferToConsumer(sp<ANativeWindow>& consumer, 144 ANativeWindowBuffer* buffer, int anwReleaseFence) { 145 status_t res = consumer->queueBuffer(consumer.get(), buffer, anwReleaseFence); 146 147 // After queuing buffer to the internal consumer queue, check whether the buffer is 148 // successfully queued to the output queues. 149 if (res == OK) { 150 res = mStreamSplitter->getOnFrameAvailableResult(); 151 if (res != OK) { 152 ALOGE("%s: getOnFrameAvailable returns %d", __FUNCTION__, res); 153 } 154 } else { 155 ALOGE("%s: queueBufer failed %d", __FUNCTION__, res); 156 } 157 158 return res; 159 } 160 161 status_t Camera3SharedOutputStream::configureQueueLocked() { 162 status_t res; 163 164 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { 165 return res; 166 } 167 168 res = connectStreamSplitterLocked(); 169 if (res != OK) { 170 ALOGE("Cannot connect to stream splitter: %s(%d)", strerror(-res), res); 171 return res; 172 } 173 174 res = configureConsumerQueueLocked(); 175 if (res != OK) { 176 ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res); 177 return res; 178 } 179 180 return OK; 181 } 182 183 status_t Camera3SharedOutputStream::disconnectLocked() { 184 status_t res; 185 res = Camera3OutputStream::disconnectLocked(); 186 187 if (mStreamSplitter != nullptr) { 188 mStreamSplitter->disconnect(); 189 } 190 191 return res; 192 } 193 194 status_t Camera3SharedOutputStream::getEndpointUsage(uint64_t *usage) const { 195 196 status_t res = OK; 197 uint64_t u = 0; 198 199 if (mConsumer == nullptr) { 200 // Called before shared buffer queue is constructed. 201 *usage = getPresetConsumerUsage(); 202 203 for (auto surface : mSurfaces) { 204 if (surface != nullptr) { 205 res = getEndpointUsageForSurface(&u, surface); 206 *usage |= u; 207 } 208 } 209 } else { 210 // Called after shared buffer queue is constructed. 211 res = getEndpointUsageForSurface(&u, mConsumer); 212 *usage |= u; 213 } 214 215 return res; 216 } 217 218 } // namespace camera3 219 220 } // namespace android 221