xref: /aosp_15_r20/frameworks/av/services/camera/libcameraservice/device3/Camera3InputStream.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2013-2018 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 <camera/StringUtils.h>
22 #include <com_android_graphics_libgui_flags.h>
23 #include <gui/BufferItem.h>
24 #include <utils/Log.h>
25 #include <utils/Trace.h>
26 
27 #include "Camera3InputStream.h"
28 
29 namespace android {
30 
31 namespace camera3 {
32 
33 const std::string Camera3InputStream::FAKE_ID;
34 
Camera3InputStream(int id,uint32_t width,uint32_t height,int format)35 Camera3InputStream::Camera3InputStream(int id,
36         uint32_t width, uint32_t height, int format) :
37         Camera3IOStreamBase(id, CAMERA_STREAM_INPUT, width, height, /*maxSize*/0,
38                             format, HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0,
39                             FAKE_ID,
40                             std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT}) {
41 
42     if (format == HAL_PIXEL_FORMAT_BLOB) {
43         ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
44         mState = STATE_ERROR;
45     }
46 }
47 
~Camera3InputStream()48 Camera3InputStream::~Camera3InputStream() {
49     disconnectLocked();
50 }
51 
getInputBufferLocked(camera_stream_buffer * buffer,Size * size)52 status_t Camera3InputStream::getInputBufferLocked(
53         camera_stream_buffer *buffer, Size *size) {
54     ATRACE_CALL();
55     status_t res;
56 
57     if (size == nullptr) {
58         ALOGE("%s: size must not be null", __FUNCTION__);
59         return BAD_VALUE;
60     }
61     // FIXME: will not work in (re-)registration
62     if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) {
63         ALOGE("%s: Stream %d: Buffer registration for input streams"
64               " not implemented (state %d)",
65               __FUNCTION__, mId, mState);
66         return INVALID_OPERATION;
67     }
68 
69     if ((res = getBufferPreconditionCheckLocked()) != OK) {
70         return res;
71     }
72 
73     ANativeWindowBuffer* anb;
74     int fenceFd;
75 
76     assert(mConsumer != 0);
77 
78     BufferItem bufferItem;
79 
80     res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false);
81     if (res != OK) {
82         // This may or may not be an error condition depending on caller.
83         ALOGV("%s: Stream %d: Can't acquire next output buffer: %s (%d)",
84                 __FUNCTION__, mId, strerror(-res), res);
85         return res;
86     }
87 
88     size->width  = bufferItem.mGraphicBuffer->getWidth();
89     size->height = bufferItem.mGraphicBuffer->getHeight();
90 
91     anb = bufferItem.mGraphicBuffer->getNativeBuffer();
92     assert(anb != NULL);
93     fenceFd = bufferItem.mFence->dup();
94     /**
95      * FenceFD now owned by HAL except in case of error,
96      * in which case we reassign it to acquire_fence
97      */
98     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
99                         /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/false);
100     mBuffersInFlight.push_back(bufferItem);
101 
102     mFrameCount++;
103     mLastTimestamp = bufferItem.mTimestamp;
104 
105     return OK;
106 }
107 
returnBufferCheckedLocked(const camera_stream_buffer & buffer,nsecs_t timestamp,nsecs_t readoutTimestamp,bool output,int32_t,const std::vector<size_t> &,sp<Fence> * releaseFenceOut)108 status_t Camera3InputStream::returnBufferCheckedLocked(
109             const camera_stream_buffer &buffer,
110             [[maybe_unused]] nsecs_t timestamp,
111             [[maybe_unused]] nsecs_t readoutTimestamp,
112             [[maybe_unused]] bool output,
113             int32_t /*transform*/,
114             const std::vector<size_t>&,
115             /*out*/
116             sp<Fence> *releaseFenceOut) {
117 
118     ALOG_ASSERT(!output, "Expected output to be false");
119 
120     status_t res;
121 
122     bool bufferFound = false;
123     BufferItem bufferItem;
124     {
125         // Find the buffer we are returning
126         Vector<BufferItem>::iterator it, end;
127         for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end();
128              it != end;
129              ++it) {
130 
131             const BufferItem& tmp = *it;
132             ANativeWindowBuffer *anb = tmp.mGraphicBuffer->getNativeBuffer();
133             if (anb != NULL && &(anb->handle) == buffer.buffer) {
134                 bufferFound = true;
135                 bufferItem = tmp;
136                 mBuffersInFlight.erase(it);
137                 break;
138             }
139         }
140     }
141     if (!bufferFound) {
142         ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL",
143               __FUNCTION__, mId);
144         return INVALID_OPERATION;
145     }
146 
147     if (buffer.status == CAMERA_BUFFER_STATUS_ERROR) {
148         if (buffer.release_fence != -1) {
149             ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
150                   "there is an error", __FUNCTION__, mId, buffer.release_fence);
151             close(buffer.release_fence);
152         }
153 
154         /**
155          * Reassign release fence as the acquire fence incase of error
156          */
157         const_cast<camera_stream_buffer*>(&buffer)->release_fence =
158                 buffer.acquire_fence;
159     }
160 
161     /**
162      * Unconditionally return buffer to the buffer queue.
163      * - Fwk takes over the release_fence ownership
164      */
165     sp<Fence> releaseFence = new Fence(buffer.release_fence);
166     res = mConsumer->releaseBuffer(bufferItem, releaseFence);
167     if (res != OK) {
168         ALOGE("%s: Stream %d: Error releasing buffer back to buffer queue:"
169                 " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
170     }
171 
172     *releaseFenceOut = releaseFence;
173 
174     return res;
175 }
176 
returnInputBufferLocked(const camera_stream_buffer & buffer)177 status_t Camera3InputStream::returnInputBufferLocked(
178         const camera_stream_buffer &buffer) {
179     ATRACE_CALL();
180 
181     return returnAnyBufferLocked(buffer, /*timestamp*/0, /*readoutTimestamp*/0,
182                                  /*output*/false, /*transform*/ -1);
183 }
184 
185 #if WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES
getInputSurfaceLocked(sp<Surface> * surface)186 status_t Camera3InputStream::getInputSurfaceLocked(sp<Surface> *surface) {
187     ATRACE_CALL();
188 
189     if (surface == NULL) {
190         return BAD_VALUE;
191     } else if (mSurface == NULL) {
192         ALOGE("%s: No input stream is configured", __FUNCTION__);
193         return INVALID_OPERATION;
194     }
195 
196     *surface = mSurface;
197     return OK;
198 }
199 #else
getInputBufferProducerLocked(sp<IGraphicBufferProducer> * producer)200 status_t Camera3InputStream::getInputBufferProducerLocked(
201             sp<IGraphicBufferProducer> *producer) {
202     ATRACE_CALL();
203 
204     if (producer == NULL) {
205         return BAD_VALUE;
206     } else if (mProducer == NULL) {
207         ALOGE("%s: No input stream is configured", __FUNCTION__);
208         return INVALID_OPERATION;
209     }
210 
211     *producer = mProducer;
212     return OK;
213 }
214 #endif
215 
disconnectLocked()216 status_t Camera3InputStream::disconnectLocked() {
217 
218     status_t res;
219 
220     if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) {
221         return res;
222     }
223 
224     assert(mBuffersInFlight.size() == 0);
225 
226     mConsumer->abandon();
227 
228     /**
229      *  no-op since we can't disconnect the producer from the consumer-side
230      */
231 
232     mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG
233                                            : STATE_CONSTRUCTED;
234     return OK;
235 }
236 
dump(int fd,const Vector<String16> & args)237 void Camera3InputStream::dump(int fd, [[maybe_unused]] const Vector<String16> &args) {
238     std::string lines;
239     lines += fmt::sprintf("    Stream[%d]: Input\n", mId);
240     write(fd, lines.c_str(), lines.size());
241 
242     Camera3IOStreamBase::dump(fd, args);
243 }
244 
configureQueueLocked()245 status_t Camera3InputStream::configureQueueLocked() {
246     status_t res;
247 
248     if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
249         return res;
250     }
251 
252     assert(mMaxSize == 0);
253     assert(camera_stream::format != HAL_PIXEL_FORMAT_BLOB);
254 
255     mHandoutTotalBufferCount = 0;
256     mFrameCount = 0;
257     mLastTimestamp = 0;
258 
259     if (mConsumer.get() == 0) {
260 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
261         sp<BufferItemConsumer> bufferItemConsumer = new BufferItemConsumer(mUsage);
262         sp<IGraphicBufferProducer> producer =
263                 bufferItemConsumer->getSurface()->getIGraphicBufferProducer();
264 #else
265         sp<IGraphicBufferProducer> producer;
266         sp<IGraphicBufferConsumer> consumer;
267         BufferQueue::createBufferQueue(&producer, &consumer);
268 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
269 
270         int minUndequeuedBuffers = 0;
271         res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
272         if (res != OK || minUndequeuedBuffers < 0) {
273             ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)",
274                     __FUNCTION__, mId, res, minUndequeuedBuffers);
275             return res;
276         }
277         size_t minBufs = static_cast<size_t>(minUndequeuedBuffers);
278 
279         if (camera_stream::max_buffers == 0) {
280             ALOGE("%s: %d: HAL sets max_buffer to 0. Must be at least 1.",
281                     __FUNCTION__, __LINE__);
282             return INVALID_OPERATION;
283         }
284 
285         /*
286          * We promise never to 'acquire' more than camera_stream::max_buffers
287          * at any one time.
288          *
289          * Boost the number up to meet the minimum required buffer count.
290          *
291          * (Note that this sets consumer-side buffer count only,
292          * and not the sum of producer+consumer side as in other camera streams).
293          */
294         mTotalBufferCount = camera_stream::max_buffers > minBufs ?
295             camera_stream::max_buffers : minBufs;
296         // TODO: somehow set the total buffer count when producer connects?
297 
298 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
299         mConsumer = bufferItemConsumer;
300         mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
301         mConsumer->setMaxAcquiredBufferCount(mTotalBufferCount);
302 
303 #if WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES
304         mSurface = mConsumer->getSurface();
305 #else
306         mProducer = mConsumer->getSurface()->getIGraphicBufferProducer();
307 #endif // WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES
308 
309 #else
310         mConsumer = new BufferItemConsumer(consumer, mUsage,
311                                            mTotalBufferCount);
312         mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
313 
314         mProducer = producer;
315 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
316 
317         mConsumer->setBufferFreedListener(this);
318     }
319 
320     res = mConsumer->setDefaultBufferSize(camera_stream::width,
321                                           camera_stream::height);
322     if (res != OK) {
323         ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d",
324               __FUNCTION__, mId, camera_stream::width, camera_stream::height);
325         return res;
326     }
327     res = mConsumer->setDefaultBufferFormat(camera_stream::format);
328     if (res != OK) {
329         ALOGE("%s: Stream %d: Could not set buffer format %d",
330               __FUNCTION__, mId, camera_stream::format);
331         return res;
332     }
333 
334     return OK;
335 }
336 
getEndpointUsage(uint64_t * usage)337 status_t Camera3InputStream::getEndpointUsage(uint64_t *usage) {
338     // Per HAL3 spec, input streams have 0 for their initial usage field.
339     *usage = 0;
340     return OK;
341 }
342 
onBufferFreed(const wp<GraphicBuffer> & gb)343 void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) {
344     const sp<GraphicBuffer> buffer = gb.promote();
345     if (buffer != nullptr) {
346         camera_stream_buffer streamBuffer =
347                 {nullptr, &buffer->handle, CAMERA_BUFFER_STATUS_OK, -1, -1};
348         // Check if this buffer is outstanding.
349         if (isOutstandingBuffer(streamBuffer)) {
350             ALOGV("%s: Stream %d: Trying to free a buffer that is still being "
351                     "processed.", __FUNCTION__, mId);
352             return;
353         }
354 
355         sp<Camera3StreamBufferFreedListener> callback = mBufferFreedListener.promote();
356         if (callback != nullptr) {
357             callback->onBufferFreed(mId, buffer->handle);
358         }
359     } else {
360         ALOGE("%s: GraphicBuffer is freed before onBufferFreed callback finishes!", __FUNCTION__);
361     }
362 }
363 
364 }; // namespace camera3
365 
366 }; // namespace android
367