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     Camera3Stream::dump(fd, args);
     90 }
     91 
     92 status_t Camera3IOStreamBase::configureQueueLocked() {
     93     status_t res;
     94 
     95     switch (mState) {
     96         case STATE_IN_RECONFIG:
     97             res = disconnectLocked();
     98             if (res != OK) {
     99                 return res;
    100             }
    101             break;
    102         case STATE_IN_CONFIG:
    103             // OK
    104             break;
    105         default:
    106             ALOGE("%s: Bad state: %d", __FUNCTION__, mState);
    107             return INVALID_OPERATION;
    108     }
    109 
    110     return OK;
    111 }
    112 
    113 size_t Camera3IOStreamBase::getBufferCountLocked() {
    114     return mTotalBufferCount;
    115 }
    116 
    117 size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() {
    118     return mHandoutOutputBufferCount;
    119 }
    120 
    121 size_t Camera3IOStreamBase::getHandoutInputBufferCountLocked() {
    122     return (mHandoutTotalBufferCount - mHandoutOutputBufferCount);
    123 }
    124 
    125 status_t Camera3IOStreamBase::disconnectLocked() {
    126     switch (mState) {
    127         case STATE_IN_RECONFIG:
    128         case STATE_CONFIGURED:
    129         case STATE_ABANDONED:
    130             // OK
    131             break;
    132         default:
    133             // No connection, nothing to do
    134             ALOGV("%s: Stream %d: Already disconnected",
    135                   __FUNCTION__, mId);
    136             return -ENOTCONN;
    137     }
    138 
    139     if (mHandoutTotalBufferCount > 0) {
    140         ALOGE("%s: Can't disconnect with %zu buffers still dequeued!",
    141                 __FUNCTION__, mHandoutTotalBufferCount);
    142         return INVALID_OPERATION;
    143     }
    144 
    145    return OK;
    146 }
    147 
    148 void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
    149                                               buffer_handle_t *handle,
    150                                               int acquireFence,
    151                                               int releaseFence,
    152                                               camera3_buffer_status_t status,
    153                                               bool output) {
    154     /**
    155      * Note that all fences are now owned by HAL.
    156      */
    157 
    158     // Handing out a raw pointer to this object. Increment internal refcount.
    159     incStrong(this);
    160     buffer.stream = this;
    161     buffer.buffer = handle;
    162     buffer.acquire_fence = acquireFence;
    163     buffer.release_fence = releaseFence;
    164     buffer.status = status;
    165 
    166     // Inform tracker about becoming busy
    167     if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
    168             mState != STATE_IN_RECONFIG && mState != STATE_PREPARING) {
    169         /**
    170          * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
    171          * before/after register_stream_buffers during initial configuration
    172          * or re-configuration, or during prepare pre-allocation
    173          */
    174         sp<StatusTracker> statusTracker = mStatusTracker.promote();
    175         if (statusTracker != 0) {
    176             statusTracker->markComponentActive(mStatusId);
    177         }
    178     }
    179     mHandoutTotalBufferCount++;
    180 
    181     if (output) {
    182         mHandoutOutputBufferCount++;
    183     }
    184 }
    185 
    186 status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {
    187     // Allow dequeue during IN_[RE]CONFIG for registration, in
    188     // PREPARING for pre-allocation
    189     if (mState != STATE_CONFIGURED &&
    190             mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG &&
    191             mState != STATE_PREPARING) {
    192         ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d",
    193                 __FUNCTION__, mId, mState);
    194         return INVALID_OPERATION;
    195     }
    196 
    197     return OK;
    198 }
    199 
    200 status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const {
    201     // Allow buffers to be returned in the error state, to allow for disconnect
    202     // and in the in-config states for registration
    203     if (mState == STATE_CONSTRUCTED) {
    204         ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d",
    205                 __FUNCTION__, mId, mState);
    206         return INVALID_OPERATION;
    207     }
    208     if (mHandoutTotalBufferCount == 0) {
    209         ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
    210                 mId);
    211         return INVALID_OPERATION;
    212     }
    213 
    214     return OK;
    215 }
    216 
    217 status_t Camera3IOStreamBase::returnAnyBufferLocked(
    218         const camera3_stream_buffer &buffer,
    219         nsecs_t timestamp,
    220         bool output) {
    221     status_t res;
    222 
    223     // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be
    224     // decrementing the internal refcount next. In case this is the last ref, we
    225     // might get destructed on the decStrong(), so keep an sp around until the
    226     // end of the call - otherwise have to sprinkle the decStrong on all exit
    227     // points.
    228     sp<Camera3IOStreamBase> keepAlive(this);
    229     decStrong(this);
    230 
    231     if ((res = returnBufferPreconditionCheckLocked()) != OK) {
    232         return res;
    233     }
    234 
    235     sp<Fence> releaseFence;
    236     res = returnBufferCheckedLocked(buffer, timestamp, output,
    237                                     &releaseFence);
    238     // Res may be an error, but we still want to decrement our owned count
    239     // to enable clean shutdown. So we'll just return the error but otherwise
    240     // carry on
    241 
    242     if (releaseFence != 0) {
    243         mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
    244     }
    245 
    246     if (output) {
    247         mHandoutOutputBufferCount--;
    248     }
    249 
    250     mHandoutTotalBufferCount--;
    251     if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
    252             mState != STATE_IN_RECONFIG && mState != STATE_PREPARING) {
    253         /**
    254          * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
    255          * before/after register_stream_buffers during initial configuration
    256          * or re-configuration, or during prepare pre-allocation
    257          */
    258         ALOGV("%s: Stream %d: All buffers returned; now idle", __FUNCTION__,
    259                 mId);
    260         sp<StatusTracker> statusTracker = mStatusTracker.promote();
    261         if (statusTracker != 0) {
    262             statusTracker->markComponentIdle(mStatusId, mCombinedFence);
    263         }
    264     }
    265 
    266     mBufferReturnedSignal.signal();
    267 
    268     if (output) {
    269         mLastTimestamp = timestamp;
    270     }
    271 
    272     return res;
    273 }
    274 
    275 
    276 
    277 }; // namespace camera3
    278 
    279 }; // namespace android
    280