Camera3OutputStream.cpp revision 15ad2470b2f2ac34473eb568b606ad75e8e63ac6
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
30namespace android {
31
32namespace camera3 {
33
34Camera3OutputStream::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
48Camera3OutputStream::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
68Camera3OutputStream::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
80Camera3OutputStream::~Camera3OutputStream() {
81    disconnectLocked();
82}
83
84status_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
127status_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
143status_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
223void 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
232status_t Camera3OutputStream::setTransform(int transform) {
233    ATRACE_CALL();
234    Mutex::Autolock l(mLock);
235    return setTransformLocked(transform);
236}
237
238status_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
257status_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
349status_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
381status_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