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