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