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-OutputStream"
     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 "Camera3OutputStream.h"
     24 
     25 #ifndef container_of
     26 #define container_of(ptr, type, member) \
     27     (type *)((char*)(ptr) - offsetof(type, member))
     28 #endif
     29 
     30 namespace android {
     31 
     32 namespace camera3 {
     33 
     34 Camera3OutputStream::Camera3OutputStream(int id,
     35         sp<ANativeWindow> consumer,
     36         uint32_t width, uint32_t height, int format) :
     37         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
     38                             /*maxSize*/0, format),
     39         mConsumer(consumer),
     40         mTransform(0) {
     41 
     42     if (mConsumer == NULL) {
     43         ALOGE("%s: Consumer is NULL!", __FUNCTION__);
     44         mState = STATE_ERROR;
     45     }
     46 }
     47 
     48 Camera3OutputStream::Camera3OutputStream(int id,
     49         sp<ANativeWindow> consumer,
     50         uint32_t width, uint32_t height, size_t maxSize, int format) :
     51         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
     52                             format),
     53         mConsumer(consumer),
     54         mTransform(0) {
     55 
     56     if (format != HAL_PIXEL_FORMAT_BLOB) {
     57         ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__,
     58                 format);
     59         mState = STATE_ERROR;
     60     }
     61 
     62     if (mConsumer == NULL) {
     63         ALOGE("%s: Consumer is NULL!", __FUNCTION__);
     64         mState = STATE_ERROR;
     65     }
     66 }
     67 
     68 Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
     69                                          uint32_t width, uint32_t height,
     70                                          int format) :
     71         Camera3IOStreamBase(id, type, width, height,
     72                             /*maxSize*/0,
     73                             format),
     74         mTransform(0) {
     75 
     76     // Subclasses expected to initialize mConsumer themselves
     77 }
     78 
     79 
     80 Camera3OutputStream::~Camera3OutputStream() {
     81     disconnectLocked();
     82 }
     83 
     84 status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) {
     85     ATRACE_CALL();
     86     status_t res;
     87 
     88     if ((res = getBufferPreconditionCheckLocked()) != OK) {
     89         return res;
     90     }
     91 
     92     ANativeWindowBuffer* anb;
     93     int fenceFd;
     94 
     95     /**
     96      * Release the lock briefly to avoid deadlock for below scenario:
     97      * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
     98      * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock.
     99      * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable().
    100      * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock
    101      * StreamingProcessor lock.
    102      * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock
    103      * and try to lock bufferQueue lock.
    104      * Then there is circular locking dependency.
    105      */
    106     sp<ANativeWindow> currentConsumer = mConsumer;
    107     mLock.unlock();
    108 
    109     res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd);
    110     mLock.lock();
    111     if (res != OK) {
    112         ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
    113                 __FUNCTION__, mId, strerror(-res), res);
    114         return res;
    115     }
    116 
    117     /**
    118      * FenceFD now owned by HAL except in case of error,
    119      * in which case we reassign it to acquire_fence
    120      */
    121     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
    122                         /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
    123 
    124     return OK;
    125 }
    126 
    127 status_t Camera3OutputStream::returnBufferLocked(
    128         const camera3_stream_buffer &buffer,
    129         nsecs_t timestamp) {
    130     ATRACE_CALL();
    131 
    132     status_t res = returnAnyBufferLocked(buffer, timestamp, /*output*/true);
    133 
    134     if (res != OK) {
    135         return res;
    136     }
    137 
    138     mLastTimestamp = timestamp;
    139 
    140     return OK;
    141 }
    142 
    143 status_t Camera3OutputStream::returnBufferCheckedLocked(
    144             const camera3_stream_buffer &buffer,
    145             nsecs_t timestamp,
    146             bool output,
    147             /*out*/
    148             sp<Fence> *releaseFenceOut) {
    149 
    150     (void)output;
    151     ALOG_ASSERT(output, "Expected output to be true");
    152 
    153     status_t res;
    154     sp<Fence> releaseFence;
    155 
    156     /**
    157      * Fence management - calculate Release Fence
    158      */
    159     if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
    160         if (buffer.release_fence != -1) {
    161             ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
    162                   "there is an error", __FUNCTION__, mId, buffer.release_fence);
    163             close(buffer.release_fence);
    164         }
    165 
    166         /**
    167          * Reassign release fence as the acquire fence in case of error
    168          */
    169         releaseFence = new Fence(buffer.acquire_fence);
    170     } else {
    171         res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
    172         if (res != OK) {
    173             ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
    174                   __FUNCTION__, mId, strerror(-res), res);
    175             return res;
    176         }
    177 
    178         releaseFence = new Fence(buffer.release_fence);
    179     }
    180 
    181     int anwReleaseFence = releaseFence->dup();
    182 
    183     /**
    184      * Release the lock briefly to avoid deadlock with
    185      * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this
    186      * thread will go into StreamingProcessor::onFrameAvailable) during
    187      * queueBuffer
    188      */
    189     sp<ANativeWindow> currentConsumer = mConsumer;
    190     mLock.unlock();
    191 
    192     /**
    193      * Return buffer back to ANativeWindow
    194      */
    195     if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
    196         // Cancel buffer
    197         res = currentConsumer->cancelBuffer(currentConsumer.get(),
    198                 container_of(buffer.buffer, ANativeWindowBuffer, handle),
    199                 anwReleaseFence);
    200         if (res != OK) {
    201             ALOGE("%s: Stream %d: Error cancelling buffer to native window:"
    202                   " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
    203         }
    204     } else {
    205         res = currentConsumer->queueBuffer(currentConsumer.get(),
    206                 container_of(buffer.buffer, ANativeWindowBuffer, handle),
    207                 anwReleaseFence);
    208         if (res != OK) {
    209             ALOGE("%s: Stream %d: Error queueing buffer to native window: "
    210                   "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
    211         }
    212     }
    213     mLock.lock();
    214     if (res != OK) {
    215         close(anwReleaseFence);
    216     }
    217 
    218     *releaseFenceOut = releaseFence;
    219 
    220     return res;
    221 }
    222 
    223 void Camera3OutputStream::dump(int fd, const Vector<String16> &args) const {
    224     (void) args;
    225     String8 lines;
    226     lines.appendFormat("    Stream[%d]: Output\n", mId);
    227     write(fd, lines.string(), lines.size());
    228 
    229     Camera3IOStreamBase::dump(fd, args);
    230 }
    231 
    232 status_t Camera3OutputStream::setTransform(int transform) {
    233     ATRACE_CALL();
    234     Mutex::Autolock l(mLock);
    235     return setTransformLocked(transform);
    236 }
    237 
    238 status_t Camera3OutputStream::setTransformLocked(int transform) {
    239     status_t res = OK;
    240     if (mState == STATE_ERROR) {
    241         ALOGE("%s: Stream in error state", __FUNCTION__);
    242         return INVALID_OPERATION;
    243     }
    244 
    245     mTransform = transform;
    246     if (mState == STATE_CONFIGURED) {
    247         res = native_window_set_buffers_transform(mConsumer.get(),
    248                 transform);
    249         if (res != OK) {
    250             ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
    251                     __FUNCTION__, transform, strerror(-res), res);
    252         }
    253     }
    254     return res;
    255 }
    256 
    257 status_t Camera3OutputStream::configureQueueLocked() {
    258     status_t res;
    259 
    260     if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
    261         return res;
    262     }
    263 
    264     ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL");
    265 
    266     // Configure consumer-side ANativeWindow interface
    267     res = native_window_api_connect(mConsumer.get(),
    268             NATIVE_WINDOW_API_CAMERA);
    269     if (res != OK) {
    270         ALOGE("%s: Unable to connect to native window for stream %d",
    271                 __FUNCTION__, mId);
    272         return res;
    273     }
    274 
    275     res = native_window_set_usage(mConsumer.get(), camera3_stream::usage);
    276     if (res != OK) {
    277         ALOGE("%s: Unable to configure usage %08x for stream %d",
    278                 __FUNCTION__, camera3_stream::usage, mId);
    279         return res;
    280     }
    281 
    282     res = native_window_set_scaling_mode(mConsumer.get(),
    283             NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
    284     if (res != OK) {
    285         ALOGE("%s: Unable to configure stream scaling: %s (%d)",
    286                 __FUNCTION__, strerror(-res), res);
    287         return res;
    288     }
    289 
    290     if (mMaxSize == 0) {
    291         // For buffers of known size
    292         res = native_window_set_buffers_geometry(mConsumer.get(),
    293                 camera3_stream::width, camera3_stream::height,
    294                 camera3_stream::format);
    295     } else {
    296         // For buffers with bounded size
    297         res = native_window_set_buffers_geometry(mConsumer.get(),
    298                 mMaxSize, 1,
    299                 camera3_stream::format);
    300     }
    301     if (res != OK) {
    302         ALOGE("%s: Unable to configure stream buffer geometry"
    303                 " %d x %d, format %x for stream %d",
    304                 __FUNCTION__, camera3_stream::width, camera3_stream::height,
    305                 camera3_stream::format, mId);
    306         return res;
    307     }
    308 
    309     int maxConsumerBuffers;
    310     res = mConsumer->query(mConsumer.get(),
    311             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
    312     if (res != OK) {
    313         ALOGE("%s: Unable to query consumer undequeued"
    314                 " buffer count for stream %d", __FUNCTION__, mId);
    315         return res;
    316     }
    317 
    318     ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__,
    319             maxConsumerBuffers, camera3_stream::max_buffers);
    320     if (camera3_stream::max_buffers == 0) {
    321         ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1",
    322                 __FUNCTION__, camera3_stream::max_buffers);
    323         return INVALID_OPERATION;
    324     }
    325 
    326     mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
    327     mDequeuedBufferCount = 0;
    328     mFrameCount = 0;
    329     mLastTimestamp = 0;
    330 
    331     res = native_window_set_buffer_count(mConsumer.get(),
    332             mTotalBufferCount);
    333     if (res != OK) {
    334         ALOGE("%s: Unable to set buffer count for stream %d",
    335                 __FUNCTION__, mId);
    336         return res;
    337     }
    338 
    339     res = native_window_set_buffers_transform(mConsumer.get(),
    340             mTransform);
    341     if (res != OK) {
    342         ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
    343                 __FUNCTION__, mTransform, strerror(-res), res);
    344     }
    345 
    346     return OK;
    347 }
    348 
    349 status_t Camera3OutputStream::disconnectLocked() {
    350     status_t res;
    351 
    352     if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) {
    353         return res;
    354     }
    355 
    356     res = native_window_api_disconnect(mConsumer.get(),
    357                                        NATIVE_WINDOW_API_CAMERA);
    358 
    359     /**
    360      * This is not an error. if client calling process dies, the window will
    361      * also die and all calls to it will return DEAD_OBJECT, thus it's already
    362      * "disconnected"
    363      */
    364     if (res == DEAD_OBJECT) {
    365         ALOGW("%s: While disconnecting stream %d from native window, the"
    366                 " native window died from under us", __FUNCTION__, mId);
    367     }
    368     else if (res != OK) {
    369         ALOGE("%s: Unable to disconnect stream %d from native window "
    370               "(error %d %s)",
    371               __FUNCTION__, mId, res, strerror(-res));
    372         mState = STATE_ERROR;
    373         return res;
    374     }
    375 
    376     mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG
    377                                            : STATE_CONSTRUCTED;
    378     return OK;
    379 }
    380 
    381 status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) {
    382 
    383     status_t res;
    384     int32_t u = 0;
    385     res = mConsumer->query(mConsumer.get(),
    386             NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
    387     *usage = u;
    388 
    389     return res;
    390 }
    391 
    392 }; // namespace camera3
    393 
    394 }; // namespace android
    395