• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-IOStreamBase"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20 
21 #include <inttypes.h>
22 
23 #include <utils/Log.h>
24 #include <utils/Trace.h>
25 #include "device3/Camera3IOStreamBase.h"
26 #include "device3/StatusTracker.h"
27 
28 namespace android {
29 
30 namespace camera3 {
31 
Camera3IOStreamBase(int id,camera_stream_type_t type,uint32_t width,uint32_t height,size_t maxSize,int format,android_dataspace dataSpace,camera_stream_rotation_t rotation,const String8 & physicalCameraId,const std::unordered_set<int32_t> & sensorPixelModesUsed,int setId,bool isMultiResolution,int64_t dynamicRangeProfile,int64_t streamUseCase,bool deviceTimeBaseIsRealtime,int timestampBase)32 Camera3IOStreamBase::Camera3IOStreamBase(int id, camera_stream_type_t type,
33         uint32_t width, uint32_t height, size_t maxSize, int format,
34         android_dataspace dataSpace, camera_stream_rotation_t rotation,
35         const String8& physicalCameraId,
36         const std::unordered_set<int32_t> &sensorPixelModesUsed,
37         int setId, bool isMultiResolution, int64_t dynamicRangeProfile, int64_t streamUseCase,
38         bool deviceTimeBaseIsRealtime, int timestampBase) :
39         Camera3Stream(id, type,
40                 width, height, maxSize, format, dataSpace, rotation,
41                 physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
42                 dynamicRangeProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase),
43         mTotalBufferCount(0),
44         mMaxCachedBufferCount(0),
45         mHandoutTotalBufferCount(0),
46         mHandoutOutputBufferCount(0),
47         mCachedOutputBufferCount(0),
48         mFrameCount(0),
49         mLastTimestamp(0) {
50 
51     mCombinedFence = new Fence();
52 
53     if (maxSize > 0 &&
54             (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
55         ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__,
56                 format);
57         mState = STATE_ERROR;
58     }
59 }
60 
~Camera3IOStreamBase()61 Camera3IOStreamBase::~Camera3IOStreamBase() {
62     disconnectLocked();
63 }
64 
hasOutstandingBuffersLocked() const65 bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const {
66     nsecs_t signalTime = mCombinedFence->getSignalTime();
67     ALOGV("%s: Stream %d: Has %zu outstanding buffers,"
68             " buffer signal time is %" PRId64,
69             __FUNCTION__, mId, mHandoutTotalBufferCount, signalTime);
70     if (mHandoutTotalBufferCount > 0 || signalTime == INT64_MAX) {
71         return true;
72     }
73     return false;
74 }
75 
dump(int fd,const Vector<String16> & args) const76 void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const {
77     (void) args;
78     String8 lines;
79 
80     uint64_t consumerUsage = 0;
81     status_t res = getEndpointUsage(&consumerUsage);
82     if (res != OK) consumerUsage = 0;
83 
84     lines.appendFormat("      State: %d\n", mState);
85     lines.appendFormat("      Dims: %d x %d, format 0x%x, dataspace 0x%x\n",
86             camera_stream::width, camera_stream::height,
87             camera_stream::format, camera_stream::data_space);
88     lines.appendFormat("      Max size: %zu\n", mMaxSize);
89     lines.appendFormat("      Combined usage: 0x%" PRIx64 ", max HAL buffers: %d\n",
90             mUsage | consumerUsage, camera_stream::max_buffers);
91     if (strlen(camera_stream::physical_camera_id) > 0) {
92         lines.appendFormat("      Physical camera id: %s\n", camera_stream::physical_camera_id);
93     }
94     lines.appendFormat("      Dynamic Range Profile: 0x%" PRIx64 "\n",
95             camera_stream::dynamic_range_profile);
96     lines.appendFormat("      Stream use case: %" PRId64 "\n", camera_stream::use_case);
97     lines.appendFormat("      Timestamp base: %d\n", getTimestampBase());
98     lines.appendFormat("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
99             mFrameCount, mLastTimestamp);
100     lines.appendFormat("      Total buffers: %zu, currently dequeued: %zu, currently cached: %zu\n",
101             mTotalBufferCount, mHandoutTotalBufferCount, mCachedOutputBufferCount);
102     write(fd, lines.string(), lines.size());
103 
104     Camera3Stream::dump(fd, args);
105 }
106 
configureQueueLocked()107 status_t Camera3IOStreamBase::configureQueueLocked() {
108     status_t res;
109 
110     switch (mState) {
111         case STATE_IN_RECONFIG:
112             res = disconnectLocked();
113             if (res != OK) {
114                 return res;
115             }
116             break;
117         case STATE_IN_CONFIG:
118             // OK
119             break;
120         default:
121             ALOGE("%s: Bad state: %d", __FUNCTION__, mState);
122             return INVALID_OPERATION;
123     }
124 
125     return OK;
126 }
127 
getBufferCountLocked()128 size_t Camera3IOStreamBase::getBufferCountLocked() {
129     return mTotalBufferCount;
130 }
131 
getHandoutOutputBufferCountLocked() const132 size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() const {
133     return mHandoutOutputBufferCount;
134 }
135 
getHandoutInputBufferCountLocked()136 size_t Camera3IOStreamBase::getHandoutInputBufferCountLocked() {
137     return (mHandoutTotalBufferCount - mHandoutOutputBufferCount);
138 }
139 
getCachedOutputBufferCountLocked() const140 size_t Camera3IOStreamBase::getCachedOutputBufferCountLocked() const {
141     return mCachedOutputBufferCount;
142 }
143 
getMaxCachedOutputBuffersLocked() const144 size_t Camera3IOStreamBase::getMaxCachedOutputBuffersLocked() const {
145     return mMaxCachedBufferCount;
146 }
147 
disconnectLocked()148 status_t Camera3IOStreamBase::disconnectLocked() {
149     switch (mState) {
150         case STATE_IN_RECONFIG:
151         case STATE_CONFIGURED:
152         case STATE_ABANDONED:
153             // OK
154             break;
155         default:
156             // No connection, nothing to do
157             ALOGV("%s: Stream %d: Already disconnected",
158                   __FUNCTION__, mId);
159             return -ENOTCONN;
160     }
161 
162     if (mHandoutTotalBufferCount > 0) {
163         ALOGE("%s: Can't disconnect with %zu buffers still dequeued!",
164                 __FUNCTION__, mHandoutTotalBufferCount);
165         return INVALID_OPERATION;
166     }
167 
168    return OK;
169 }
170 
handoutBufferLocked(camera_stream_buffer & buffer,buffer_handle_t * handle,int acquireFence,int releaseFence,camera_buffer_status_t status,bool output)171 void Camera3IOStreamBase::handoutBufferLocked(camera_stream_buffer &buffer,
172                                               buffer_handle_t *handle,
173                                               int acquireFence,
174                                               int releaseFence,
175                                               camera_buffer_status_t status,
176                                               bool output) {
177     /**
178      * Note that all fences are now owned by HAL.
179      */
180 
181     // Handing out a raw pointer to this object. Increment internal refcount.
182     incStrong(this);
183     buffer.stream = this;
184     buffer.buffer = handle;
185     buffer.acquire_fence = acquireFence;
186     buffer.release_fence = releaseFence;
187     buffer.status = status;
188 
189     // Inform tracker about becoming busy
190     if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
191             mState != STATE_IN_RECONFIG && mState != STATE_PREPARING) {
192         /**
193          * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
194          * before/after register_stream_buffers during initial configuration
195          * or re-configuration, or during prepare pre-allocation
196          */
197         sp<StatusTracker> statusTracker = mStatusTracker.promote();
198         if (statusTracker != 0) {
199             statusTracker->markComponentActive(mStatusId);
200         }
201     }
202     mHandoutTotalBufferCount++;
203 
204     if (output) {
205         mHandoutOutputBufferCount++;
206     }
207 }
208 
getBufferPreconditionCheckLocked() const209 status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {
210     // Allow dequeue during IN_[RE]CONFIG for registration, in
211     // PREPARING for pre-allocation
212     if (mState != STATE_CONFIGURED &&
213             mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG &&
214             mState != STATE_PREPARING) {
215         ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d",
216                 __FUNCTION__, mId, mState);
217         return INVALID_OPERATION;
218     }
219 
220     return OK;
221 }
222 
returnBufferPreconditionCheckLocked() const223 status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const {
224     // Allow buffers to be returned in the error state, to allow for disconnect
225     // and in the in-config states for registration
226     if (mState == STATE_CONSTRUCTED) {
227         ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d",
228                 __FUNCTION__, mId, mState);
229         return INVALID_OPERATION;
230     }
231     if (mHandoutTotalBufferCount == 0) {
232         ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
233                 mId);
234         return INVALID_OPERATION;
235     }
236 
237     return OK;
238 }
239 
returnAnyBufferLocked(const camera_stream_buffer & buffer,nsecs_t timestamp,nsecs_t readoutTimestamp,bool output,int32_t transform,const std::vector<size_t> & surface_ids)240 status_t Camera3IOStreamBase::returnAnyBufferLocked(
241         const camera_stream_buffer &buffer,
242         nsecs_t timestamp,
243         nsecs_t readoutTimestamp,
244         bool output,
245         int32_t transform,
246         const std::vector<size_t>& surface_ids) {
247     status_t res;
248 
249     // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be
250     // decrementing the internal refcount next. In case this is the last ref, we
251     // might get destructed on the decStrong(), so keep an sp around until the
252     // end of the call - otherwise have to sprinkle the decStrong on all exit
253     // points.
254     sp<Camera3IOStreamBase> keepAlive(this);
255     decStrong(this);
256 
257     if ((res = returnBufferPreconditionCheckLocked()) != OK) {
258         return res;
259     }
260 
261     sp<Fence> releaseFence;
262     res = returnBufferCheckedLocked(buffer, timestamp, readoutTimestamp,
263                                     output, transform, surface_ids,
264                                     &releaseFence);
265     // Res may be an error, but we still want to decrement our owned count
266     // to enable clean shutdown. So we'll just return the error but otherwise
267     // carry on
268 
269     if (releaseFence != 0) {
270         mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
271     }
272 
273     if (output) {
274         mHandoutOutputBufferCount--;
275     }
276 
277     mHandoutTotalBufferCount--;
278     if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
279             mState != STATE_IN_RECONFIG && mState != STATE_PREPARING) {
280         /**
281          * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
282          * before/after register_stream_buffers during initial configuration
283          * or re-configuration, or during prepare pre-allocation
284          */
285         ALOGV("%s: Stream %d: All buffers returned; now idle", __FUNCTION__,
286                 mId);
287         sp<StatusTracker> statusTracker = mStatusTracker.promote();
288         if (statusTracker != 0) {
289             statusTracker->markComponentIdle(mStatusId, mCombinedFence);
290         }
291     }
292 
293     if (output) {
294         mLastTimestamp = timestamp;
295     }
296 
297     return res;
298 }
299 
300 
301 
302 }; // namespace camera3
303 
304 }; // namespace android
305