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-InputStream"
     18 #define ATRACE_TAG ATRACE_TAG_CAMERA
     19 //#define LOG_NDEBUG 0
     20 
     21 #include <utils/Log.h>
     22 #include <utils/Trace.h>
     23 #include "Camera3InputStream.h"
     24 
     25 namespace android {
     26 
     27 namespace camera3 {
     28 
     29 Camera3InputStream::Camera3InputStream(int id,
     30         uint32_t width, uint32_t height, int format) :
     31         Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height,
     32                             /*maxSize*/0, format) {
     33 
     34     if (format == HAL_PIXEL_FORMAT_BLOB) {
     35         ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
     36         mState = STATE_ERROR;
     37     }
     38 }
     39 
     40 Camera3InputStream::~Camera3InputStream() {
     41     disconnectLocked();
     42 }
     43 
     44 status_t Camera3InputStream::getInputBufferLocked(
     45         camera3_stream_buffer *buffer) {
     46     ATRACE_CALL();
     47     status_t res;
     48 
     49     // FIXME: will not work in (re-)registration
     50     if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) {
     51         ALOGE("%s: Stream %d: Buffer registration for input streams"
     52               " not implemented (state %d)",
     53               __FUNCTION__, mId, mState);
     54         return INVALID_OPERATION;
     55     }
     56 
     57     if ((res = getBufferPreconditionCheckLocked()) != OK) {
     58         return res;
     59     }
     60 
     61     ANativeWindowBuffer* anb;
     62     int fenceFd;
     63 
     64     assert(mConsumer != 0);
     65 
     66     BufferItem bufferItem;
     67     res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false);
     68 
     69     if (res != OK) {
     70         ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)",
     71                 __FUNCTION__, mId, strerror(-res), res);
     72         return res;
     73     }
     74 
     75     anb = bufferItem.mGraphicBuffer->getNativeBuffer();
     76     assert(anb != NULL);
     77     fenceFd = bufferItem.mFence->dup();
     78 
     79     /**
     80      * FenceFD now owned by HAL except in case of error,
     81      * in which case we reassign it to acquire_fence
     82      */
     83     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
     84                         /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
     85     mBuffersInFlight.push_back(bufferItem);
     86 
     87     return OK;
     88 }
     89 
     90 status_t Camera3InputStream::returnBufferCheckedLocked(
     91             const camera3_stream_buffer &buffer,
     92             nsecs_t timestamp,
     93             bool output,
     94             /*out*/
     95             sp<Fence> *releaseFenceOut) {
     96 
     97     (void)timestamp;
     98     (void)output;
     99     ALOG_ASSERT(!output, "Expected output to be false");
    100 
    101     status_t res;
    102 
    103     bool bufferFound = false;
    104     BufferItem bufferItem;
    105     {
    106         // Find the buffer we are returning
    107         Vector<BufferItem>::iterator it, end;
    108         for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end();
    109              it != end;
    110              ++it) {
    111 
    112             const BufferItem& tmp = *it;
    113             ANativeWindowBuffer *anb = tmp.mGraphicBuffer->getNativeBuffer();
    114             if (anb != NULL && &(anb->handle) == buffer.buffer) {
    115                 bufferFound = true;
    116                 bufferItem = tmp;
    117                 mBuffersInFlight.erase(it);
    118             }
    119         }
    120     }
    121     if (!bufferFound) {
    122         ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL",
    123               __FUNCTION__, mId);
    124         return INVALID_OPERATION;
    125     }
    126 
    127     if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
    128         if (buffer.release_fence != -1) {
    129             ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
    130                   "there is an error", __FUNCTION__, mId, buffer.release_fence);
    131             close(buffer.release_fence);
    132         }
    133 
    134         /**
    135          * Reassign release fence as the acquire fence incase of error
    136          */
    137         const_cast<camera3_stream_buffer*>(&buffer)->release_fence =
    138                 buffer.acquire_fence;
    139     }
    140 
    141     /**
    142      * Unconditionally return buffer to the buffer queue.
    143      * - Fwk takes over the release_fence ownership
    144      */
    145     sp<Fence> releaseFence = new Fence(buffer.release_fence);
    146     res = mConsumer->releaseBuffer(bufferItem, releaseFence);
    147     if (res != OK) {
    148         ALOGE("%s: Stream %d: Error releasing buffer back to buffer queue:"
    149                 " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
    150     }
    151 
    152     *releaseFenceOut = releaseFence;
    153 
    154     return res;
    155 }
    156 
    157 status_t Camera3InputStream::returnInputBufferLocked(
    158         const camera3_stream_buffer &buffer) {
    159     ATRACE_CALL();
    160 
    161     return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false);
    162 }
    163 
    164 status_t Camera3InputStream::disconnectLocked() {
    165 
    166     status_t res;
    167 
    168     if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) {
    169         return res;
    170     }
    171 
    172     assert(mBuffersInFlight.size() == 0);
    173 
    174     /**
    175      *  no-op since we can't disconnect the producer from the consumer-side
    176      */
    177 
    178     mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG
    179                                            : STATE_CONSTRUCTED;
    180     return OK;
    181 }
    182 
    183 void Camera3InputStream::dump(int fd, const Vector<String16> &args) const {
    184     (void) args;
    185     String8 lines;
    186     lines.appendFormat("    Stream[%d]: Input\n", mId);
    187     write(fd, lines.string(), lines.size());
    188 
    189     Camera3IOStreamBase::dump(fd, args);
    190 }
    191 
    192 status_t Camera3InputStream::configureQueueLocked() {
    193     status_t res;
    194 
    195     if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
    196         return res;
    197     }
    198 
    199     assert(mMaxSize == 0);
    200     assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB);
    201 
    202     mTotalBufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS +
    203                         camera3_stream::max_buffers;
    204     mDequeuedBufferCount = 0;
    205     mFrameCount = 0;
    206 
    207     if (mConsumer.get() == 0) {
    208         sp<BufferQueue> bq = new BufferQueue();
    209         mConsumer = new BufferItemConsumer(bq, camera3_stream::usage,
    210                                            mTotalBufferCount);
    211         mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
    212     }
    213 
    214     res = mConsumer->setDefaultBufferSize(camera3_stream::width,
    215                                           camera3_stream::height);
    216     if (res != OK) {
    217         ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d",
    218               __FUNCTION__, mId, camera3_stream::width, camera3_stream::height);
    219         return res;
    220     }
    221     res = mConsumer->setDefaultBufferFormat(camera3_stream::format);
    222     if (res != OK) {
    223         ALOGE("%s: Stream %d: Could not set buffer format %d",
    224               __FUNCTION__, mId, camera3_stream::format);
    225         return res;
    226     }
    227 
    228     return OK;
    229 }
    230 
    231 status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) {
    232     // Per HAL3 spec, input streams have 0 for their initial usage field.
    233     *usage = 0;
    234     return OK;
    235 }
    236 
    237 }; // namespace camera3
    238 
    239 }; // namespace android
    240