Home | History | Annotate | Download | only in camera3
      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-ZslStream"
     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 "Camera3ZslStream.h"
     24 
     25 typedef android::RingBufferConsumer::PinnedBufferItem PinnedBufferItem;
     26 
     27 namespace android {
     28 
     29 namespace camera3 {
     30 
     31 namespace {
     32 struct TimestampFinder : public RingBufferConsumer::RingBufferComparator {
     33     typedef RingBufferConsumer::BufferInfo BufferInfo;
     34 
     35     enum {
     36         SELECT_I1 = -1,
     37         SELECT_I2 = 1,
     38         SELECT_NEITHER = 0,
     39     };
     40 
     41     TimestampFinder(nsecs_t timestamp) : mTimestamp(timestamp) {}
     42     ~TimestampFinder() {}
     43 
     44     template <typename T>
     45     static void swap(T& a, T& b) {
     46         T tmp = a;
     47         a = b;
     48         b = tmp;
     49     }
     50 
     51     /**
     52      * Try to find the best candidate for a ZSL buffer.
     53      * Match priority from best to worst:
     54      *  1) Timestamps match.
     55      *  2) Timestamp is closest to the needle (and lower).
     56      *  3) Timestamp is closest to the needle (and higher).
     57      *
     58      */
     59     virtual int compare(const BufferInfo *i1,
     60                         const BufferInfo *i2) const {
     61         // Try to select non-null object first.
     62         if (i1 == NULL) {
     63             return SELECT_I2;
     64         } else if (i2 == NULL) {
     65             return SELECT_I1;
     66         }
     67 
     68         // Best result: timestamp is identical
     69         if (i1->mTimestamp == mTimestamp) {
     70             return SELECT_I1;
     71         } else if (i2->mTimestamp == mTimestamp) {
     72             return SELECT_I2;
     73         }
     74 
     75         const BufferInfo* infoPtrs[2] = {
     76             i1,
     77             i2
     78         };
     79         int infoSelectors[2] = {
     80             SELECT_I1,
     81             SELECT_I2
     82         };
     83 
     84         // Order i1,i2 so that always i1.timestamp < i2.timestamp
     85         if (i1->mTimestamp > i2->mTimestamp) {
     86             swap(infoPtrs[0], infoPtrs[1]);
     87             swap(infoSelectors[0], infoSelectors[1]);
     88         }
     89 
     90         // Second best: closest (lower) timestamp
     91         if (infoPtrs[1]->mTimestamp < mTimestamp) {
     92             return infoSelectors[1];
     93         } else if (infoPtrs[0]->mTimestamp < mTimestamp) {
     94             return infoSelectors[0];
     95         }
     96 
     97         // Worst: closest (higher) timestamp
     98         return infoSelectors[0];
     99 
    100         /**
    101          * The above cases should cover all the possibilities,
    102          * and we get an 'empty' result only if the ring buffer
    103          * was empty itself
    104          */
    105     }
    106 
    107     const nsecs_t mTimestamp;
    108 }; // struct TimestampFinder
    109 } // namespace anonymous
    110 
    111 Camera3ZslStream::Camera3ZslStream(int id, uint32_t width, uint32_t height,
    112         int depth) :
    113         Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL,
    114                             width, height,
    115                             HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
    116         mDepth(depth),
    117         mProducer(new RingBufferConsumer(GRALLOC_USAGE_HW_CAMERA_ZSL,
    118                                          depth)) {
    119 
    120         mConsumer = new Surface(mProducer->getProducerInterface());
    121 }
    122 
    123 Camera3ZslStream::~Camera3ZslStream() {
    124 }
    125 
    126 status_t Camera3ZslStream::getInputBufferLocked(camera3_stream_buffer *buffer) {
    127     ATRACE_CALL();
    128 
    129     status_t res;
    130 
    131     // TODO: potentially register from inputBufferLocked
    132     // this should be ok, registerBuffersLocked only calls getBuffer for now
    133     // register in output mode instead of input mode for ZSL streams.
    134     if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) {
    135         ALOGE("%s: Stream %d: Buffer registration for input streams"
    136               " not implemented (state %d)",
    137               __FUNCTION__, mId, mState);
    138         return INVALID_OPERATION;
    139     }
    140 
    141     if ((res = getBufferPreconditionCheckLocked()) != OK) {
    142         return res;
    143     }
    144 
    145     ANativeWindowBuffer* anb;
    146     int fenceFd;
    147 
    148     assert(mProducer != 0);
    149 
    150     sp<PinnedBufferItem> bufferItem;
    151     {
    152         List<sp<RingBufferConsumer::PinnedBufferItem> >::iterator it, end;
    153         it = mInputBufferQueue.begin();
    154         end = mInputBufferQueue.end();
    155 
    156         // Need to call enqueueInputBufferByTimestamp as a prerequisite
    157         if (it == end) {
    158             ALOGE("%s: Stream %d: No input buffer was queued",
    159                     __FUNCTION__, mId);
    160             return INVALID_OPERATION;
    161         }
    162         bufferItem = *it;
    163         mInputBufferQueue.erase(it);
    164     }
    165 
    166     anb = bufferItem->getBufferItem().mGraphicBuffer->getNativeBuffer();
    167     assert(anb != NULL);
    168     fenceFd = bufferItem->getBufferItem().mFence->dup();
    169 
    170     /**
    171      * FenceFD now owned by HAL except in case of error,
    172      * in which case we reassign it to acquire_fence
    173      */
    174     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
    175                          /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
    176 
    177     mBuffersInFlight.push_back(bufferItem);
    178 
    179     return OK;
    180 }
    181 
    182 status_t Camera3ZslStream::returnBufferCheckedLocked(
    183             const camera3_stream_buffer &buffer,
    184             nsecs_t timestamp,
    185             bool output,
    186             /*out*/
    187             sp<Fence> *releaseFenceOut) {
    188 
    189     if (output) {
    190         // Output stream path
    191         return Camera3OutputStream::returnBufferCheckedLocked(buffer,
    192                                                               timestamp,
    193                                                               output,
    194                                                               releaseFenceOut);
    195     }
    196 
    197     /**
    198      * Input stream path
    199      */
    200     bool bufferFound = false;
    201     sp<PinnedBufferItem> bufferItem;
    202     {
    203         // Find the buffer we are returning
    204         Vector<sp<PinnedBufferItem> >::iterator it, end;
    205         for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end();
    206              it != end;
    207              ++it) {
    208 
    209             const sp<PinnedBufferItem>& tmp = *it;
    210             ANativeWindowBuffer *anb =
    211                     tmp->getBufferItem().mGraphicBuffer->getNativeBuffer();
    212             if (anb != NULL && &(anb->handle) == buffer.buffer) {
    213                 bufferFound = true;
    214                 bufferItem = tmp;
    215                 mBuffersInFlight.erase(it);
    216                 break;
    217             }
    218         }
    219     }
    220     if (!bufferFound) {
    221         ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL",
    222               __FUNCTION__, mId);
    223         return INVALID_OPERATION;
    224     }
    225 
    226     int releaseFenceFd = buffer.release_fence;
    227 
    228     if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
    229         if (buffer.release_fence != -1) {
    230             ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
    231                   "there is an error", __FUNCTION__, mId, buffer.release_fence);
    232             close(buffer.release_fence);
    233         }
    234 
    235         /**
    236          * Reassign release fence as the acquire fence incase of error
    237          */
    238         releaseFenceFd = buffer.acquire_fence;
    239     }
    240 
    241     /**
    242      * Unconditionally return buffer to the buffer queue.
    243      * - Fwk takes over the release_fence ownership
    244      */
    245     sp<Fence> releaseFence = new Fence(releaseFenceFd);
    246     bufferItem->getBufferItem().mFence = releaseFence;
    247     bufferItem.clear(); // dropping last reference unpins buffer
    248 
    249     *releaseFenceOut = releaseFence;
    250 
    251     return OK;
    252 }
    253 
    254 status_t Camera3ZslStream::returnInputBufferLocked(
    255         const camera3_stream_buffer &buffer) {
    256     ATRACE_CALL();
    257 
    258     status_t res = returnAnyBufferLocked(buffer, /*timestamp*/0,
    259                                          /*output*/false);
    260 
    261     return res;
    262 }
    263 
    264 void Camera3ZslStream::dump(int fd, const Vector<String16> &args) const {
    265     (void) args;
    266 
    267     String8 lines;
    268     lines.appendFormat("    Stream[%d]: ZSL\n", mId);
    269     write(fd, lines.string(), lines.size());
    270 
    271     Camera3IOStreamBase::dump(fd, args);
    272 
    273     lines = String8();
    274     lines.appendFormat("      Input buffers pending: %d, in flight %d\n",
    275             mInputBufferQueue.size(), mBuffersInFlight.size());
    276     write(fd, lines.string(), lines.size());
    277 }
    278 
    279 status_t Camera3ZslStream::enqueueInputBufferByTimestamp(
    280         nsecs_t timestamp,
    281         nsecs_t* actualTimestamp) {
    282 
    283     Mutex::Autolock l(mLock);
    284 
    285     TimestampFinder timestampFinder = TimestampFinder(timestamp);
    286 
    287     sp<RingBufferConsumer::PinnedBufferItem> pinnedBuffer =
    288             mProducer->pinSelectedBuffer(timestampFinder,
    289                                         /*waitForFence*/false);
    290 
    291     if (pinnedBuffer == 0) {
    292         ALOGE("%s: No ZSL buffers were available yet", __FUNCTION__);
    293         return NO_BUFFER_AVAILABLE;
    294     }
    295 
    296     nsecs_t actual = pinnedBuffer->getBufferItem().mTimestamp;
    297 
    298     if (actual != timestamp) {
    299         ALOGW("%s: ZSL buffer candidate search didn't find an exact match --"
    300               " requested timestamp = %lld, actual timestamp = %lld",
    301               __FUNCTION__, timestamp, actual);
    302     }
    303 
    304     mInputBufferQueue.push_back(pinnedBuffer);
    305 
    306     if (actualTimestamp != NULL) {
    307         *actualTimestamp = actual;
    308     }
    309 
    310     return OK;
    311 }
    312 
    313 status_t Camera3ZslStream::clearInputRingBuffer() {
    314     Mutex::Autolock l(mLock);
    315 
    316     mInputBufferQueue.clear();
    317 
    318     return mProducer->clear();
    319 }
    320 
    321 status_t Camera3ZslStream::setTransform(int /*transform*/) {
    322     ALOGV("%s: Not implemented", __FUNCTION__);
    323     return INVALID_OPERATION;
    324 }
    325 
    326 }; // namespace camera3
    327 
    328 }; // namespace android
    329