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