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
Camera3SharedOutputStream(int id,const std::vector<sp<Surface>> & surfaces,uint32_t width,uint32_t height,int format,uint64_t consumerUsage,android_dataspace dataSpace,camera3_stream_rotation_t rotation,nsecs_t timestampOffset,int setId)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
~Camera3SharedOutputStream()35 Camera3SharedOutputStream::~Camera3SharedOutputStream() {
36 disconnectLocked();
37 }
38
connectStreamSplitterLocked()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
notifyBufferReleased(ANativeWindowBuffer * anwBuffer)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
isConsumerConfigurationDeferred(size_t surface_id) const69 bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const {
70 Mutex::Autolock l(mLock);
71 return (surface_id >= mSurfaces.size());
72 }
73
setConsumers(const std::vector<sp<Surface>> & surfaces)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
getBufferLocked(camera3_stream_buffer * buffer,const std::vector<size_t> & surface_ids)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
queueBufferToConsumer(sp<ANativeWindow> & consumer,ANativeWindowBuffer * buffer,int anwReleaseFence)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
configureQueueLocked()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
disconnectLocked()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
getEndpointUsage(uint64_t * usage) const194 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