StreamingProcessor.cpp revision 73bbd1f1c493835f191ea2b0b72439292496b40a
1/*
2 * Copyright (C) 2012 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 "Camera2-StreamingProcessor"
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 <gui/SurfaceTextureClient.h>
24#include <media/hardware/MetadataBufferType.h>
25
26#include "StreamingProcessor.h"
27#include "Camera2Heap.h"
28#include "../Camera2Client.h"
29#include "../Camera2Device.h"
30
31namespace android {
32namespace camera2 {
33
34StreamingProcessor::StreamingProcessor(wp<Camera2Client> client):
35        mClient(client),
36        mPreviewStreamId(NO_STREAM),
37        mRecordingStreamId(NO_STREAM),
38        mRecordingHeapCount(kDefaultRecordingHeapCount)
39{
40
41}
42
43StreamingProcessor::~StreamingProcessor() {
44    deletePreviewStream();
45    deleteRecordingStream();
46}
47
48status_t StreamingProcessor::setPreviewWindow(sp<ANativeWindow> window) {
49    ATRACE_CALL();
50    status_t res;
51
52    res = deletePreviewStream();
53    if (res != OK) return res;
54
55    Mutex::Autolock m(mMutex);
56
57    mPreviewWindow = window;
58
59    return OK;
60}
61
62bool StreamingProcessor::haveValidPreviewWindow() const {
63    Mutex::Autolock m(mMutex);
64    return mPreviewWindow != 0;
65}
66
67status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {
68    ATRACE_CALL();
69    status_t res;
70    sp<Camera2Client> client = mClient.promote();
71    if (client == 0) return INVALID_OPERATION;
72
73    Mutex::Autolock m(mMutex);
74    if (mPreviewRequest.entryCount() == 0) {
75        res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
76                &mPreviewRequest);
77        if (res != OK) {
78            ALOGE("%s: Camera %d: Unable to create default preview request: "
79                    "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
80            return res;
81        }
82    }
83
84    res = params.updateRequest(&mPreviewRequest);
85    if (res != OK) {
86        ALOGE("%s: Camera %d: Unable to update common entries of preview "
87                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
88                strerror(-res), res);
89        return res;
90    }
91
92    res = mPreviewRequest.update(ANDROID_REQUEST_ID,
93            &Camera2Client::kPreviewRequestId, 1);
94
95    return OK;
96}
97
98status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
99    ATRACE_CALL();
100    Mutex::Autolock m(mMutex);
101
102    status_t res;
103    sp<Camera2Client> client = mClient.promote();
104    if (client == 0) return INVALID_OPERATION;
105    sp<Camera2Device> device = client->getCameraDevice();
106
107    if (mPreviewStreamId != NO_STREAM) {
108        // Check if stream parameters have to change
109        uint32_t currentWidth, currentHeight;
110        res = device->getStreamInfo(mPreviewStreamId,
111                &currentWidth, &currentHeight, 0);
112        if (res != OK) {
113            ALOGE("%s: Camera %d: Error querying preview stream info: "
114                    "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
115            return res;
116        }
117        if (currentWidth != (uint32_t)params.previewWidth ||
118                currentHeight != (uint32_t)params.previewHeight) {
119            ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",
120                    __FUNCTION__, client->getCameraId(), currentWidth, currentHeight,
121                    params.previewWidth, params.previewHeight);
122            res = device->waitUntilDrained();
123            if (res != OK) {
124                ALOGE("%s: Camera %d: Error waiting for preview to drain: "
125                        "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
126                return res;
127            }
128            res = device->deleteStream(mPreviewStreamId);
129            if (res != OK) {
130                ALOGE("%s: Camera %d: Unable to delete old output stream "
131                        "for preview: %s (%d)", __FUNCTION__, client->getCameraId(),
132                        strerror(-res), res);
133                return res;
134            }
135            mPreviewStreamId = NO_STREAM;
136        }
137    }
138
139    if (mPreviewStreamId == NO_STREAM) {
140        res = device->createStream(mPreviewWindow,
141                params.previewWidth, params.previewHeight,
142                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0,
143                &mPreviewStreamId);
144        if (res != OK) {
145            ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
146                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
147            return res;
148        }
149    }
150
151    res = device->setStreamTransform(mPreviewStreamId,
152            params.previewTransform);
153    if (res != OK) {
154        ALOGE("%s: Camera %d: Unable to set preview stream transform: "
155                "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
156        return res;
157    }
158
159    return OK;
160}
161
162status_t StreamingProcessor::deletePreviewStream() {
163    ATRACE_CALL();
164    status_t res;
165
166    Mutex::Autolock m(mMutex);
167
168    if (mPreviewStreamId != NO_STREAM) {
169        sp<Camera2Client> client = mClient.promote();
170        if (client == 0) return INVALID_OPERATION;
171        sp<Camera2Device> device = client->getCameraDevice();
172
173        res = device->waitUntilDrained();
174        if (res != OK) {
175            ALOGE("%s: Error waiting for preview to drain: %s (%d)",
176                    __FUNCTION__, strerror(-res), res);
177            return res;
178        }
179        res = device->deleteStream(mPreviewStreamId);
180        if (res != OK) {
181            ALOGE("%s: Unable to delete old preview stream: %s (%d)",
182                    __FUNCTION__, strerror(-res), res);
183            return res;
184        }
185        mPreviewStreamId = NO_STREAM;
186    }
187    return OK;
188}
189
190status_t StreamingProcessor::getPreviewStreamId() const {
191    Mutex::Autolock m(mMutex);
192    return mPreviewStreamId;
193}
194
195status_t StreamingProcessor::setRecordingBufferCount(size_t count) {
196    ATRACE_CALL();
197    // 32 is the current upper limit on the video buffer count for BufferQueue
198    sp<Camera2Client> client = mClient.promote();
199    if (client == 0) return INVALID_OPERATION;
200    if (count > 32) {
201        ALOGE("%s: Camera %d: Error setting %d as video buffer count value",
202                __FUNCTION__, client->getCameraId(), count);
203        return BAD_VALUE;
204    }
205
206    Mutex::Autolock m(mMutex);
207
208    // Need to reallocate memory for heap
209    if (mRecordingHeapCount != count) {
210        if  (mRecordingHeap != 0) {
211            mRecordingHeap.clear();
212            mRecordingHeap = NULL;
213        }
214        mRecordingHeapCount = count;
215    }
216
217    return OK;
218}
219
220status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
221    ATRACE_CALL();
222    status_t res;
223    Mutex::Autolock m(mMutex);
224
225    sp<Camera2Client> client = mClient.promote();
226    if (client == 0) return INVALID_OPERATION;
227
228    if (mRecordingRequest.entryCount() == 0) {
229        res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
230                &mRecordingRequest);
231        if (res != OK) {
232            ALOGE("%s: Camera %d: Unable to create default recording request:"
233                    " %s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
234            return res;
235        }
236    }
237
238    res = params.updateRequest(&mRecordingRequest);
239    if (res != OK) {
240        ALOGE("%s: Camera %d: Unable to update common entries of recording "
241                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
242                strerror(-res), res);
243        return res;
244    }
245
246    return OK;
247}
248
249status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
250    ATRACE_CALL();
251    status_t res;
252    Mutex::Autolock m(mMutex);
253
254    sp<Camera2Client> client = mClient.promote();
255    if (client == 0) return INVALID_OPERATION;
256    sp<Camera2Device> device = client->getCameraDevice();
257
258    if (mRecordingConsumer == 0) {
259        // Create CPU buffer queue endpoint. We need one more buffer here so that we can
260        // always acquire and free a buffer when the heap is full; otherwise the consumer
261        // will have buffers in flight we'll never clear out.
262        mRecordingConsumer = new BufferItemConsumer(
263                GRALLOC_USAGE_HW_VIDEO_ENCODER,
264                mRecordingHeapCount + 1,
265                true);
266        mRecordingConsumer->setFrameAvailableListener(this);
267        mRecordingConsumer->setName(String8("Camera2-RecordingConsumer"));
268        mRecordingWindow = new SurfaceTextureClient(
269            mRecordingConsumer->getProducerInterface());
270        // Allocate memory later, since we don't know buffer size until receipt
271    }
272
273    if (mRecordingStreamId != NO_STREAM) {
274        // Check if stream parameters have to change
275        uint32_t currentWidth, currentHeight;
276        res = device->getStreamInfo(mRecordingStreamId,
277                &currentWidth, &currentHeight, 0);
278        if (res != OK) {
279            ALOGE("%s: Camera %d: Error querying recording output stream info: "
280                    "%s (%d)", __FUNCTION__, client->getCameraId(),
281                    strerror(-res), res);
282            return res;
283        }
284        if (currentWidth != (uint32_t)params.videoWidth ||
285                currentHeight != (uint32_t)params.videoHeight) {
286            // TODO: Should wait to be sure previous recording has finished
287            res = device->deleteStream(mRecordingStreamId);
288            if (res != OK) {
289                ALOGE("%s: Camera %d: Unable to delete old output stream "
290                        "for recording: %s (%d)", __FUNCTION__,
291                        client->getCameraId(), strerror(-res), res);
292                return res;
293            }
294            mRecordingStreamId = NO_STREAM;
295        }
296    }
297
298    if (mRecordingStreamId == NO_STREAM) {
299        mRecordingFrameCount = 0;
300        res = device->createStream(mRecordingWindow,
301                params.videoWidth, params.videoHeight,
302                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mRecordingStreamId);
303        if (res != OK) {
304            ALOGE("%s: Camera %d: Can't create output stream for recording: "
305                    "%s (%d)", __FUNCTION__, client->getCameraId(),
306                    strerror(-res), res);
307            return res;
308        }
309    }
310
311    return OK;
312}
313
314status_t StreamingProcessor::deleteRecordingStream() {
315    ATRACE_CALL();
316    status_t res;
317
318    Mutex::Autolock m(mMutex);
319
320    if (mRecordingStreamId != NO_STREAM) {
321        sp<Camera2Client> client = mClient.promote();
322        if (client == 0) return INVALID_OPERATION;
323        sp<Camera2Device> device = client->getCameraDevice();
324
325        res = device->waitUntilDrained();
326        if (res != OK) {
327            ALOGE("%s: Error waiting for HAL to drain: %s (%d)",
328                    __FUNCTION__, strerror(-res), res);
329            return res;
330        }
331        res = device->deleteStream(mRecordingStreamId);
332        if (res != OK) {
333            ALOGE("%s: Unable to delete recording stream: %s (%d)",
334                    __FUNCTION__, strerror(-res), res);
335            return res;
336        }
337        mRecordingStreamId = NO_STREAM;
338    }
339    return OK;
340}
341
342status_t StreamingProcessor::getRecordingStreamId() const {
343    return mRecordingStreamId;
344}
345
346status_t StreamingProcessor::startStream(StreamType type,
347        const Vector<uint8_t> &outputStreams) {
348    ATRACE_CALL();
349    status_t res;
350
351    sp<Camera2Client> client = mClient.promote();
352    if (client == 0) return INVALID_OPERATION;
353
354    Mutex::Autolock m(mMutex);
355
356    CameraMetadata &request = (type == PREVIEW) ?
357            mPreviewRequest : mRecordingRequest;
358
359    res = request.update(
360        ANDROID_REQUEST_OUTPUT_STREAMS,
361        outputStreams);
362    if (res != OK) {
363        ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
364                __FUNCTION__, client->getCameraId(), strerror(-res), res);
365        return res;
366    }
367
368    res = request.sort();
369    if (res != OK) {
370        ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
371                __FUNCTION__, client->getCameraId(), strerror(-res), res);
372        return res;
373    }
374
375    res = client->getCameraDevice()->setStreamingRequest(request);
376    if (res != OK) {
377        ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
378                "%s (%d)",
379                __FUNCTION__, client->getCameraId(), strerror(-res), res);
380        return res;
381    }
382
383    return OK;
384}
385
386status_t StreamingProcessor::stopStream() {
387    ATRACE_CALL();
388    status_t res;
389
390    sp<Camera2Client> client = mClient.promote();
391    if (client == 0) return INVALID_OPERATION;
392    sp<Camera2Device> device = client->getCameraDevice();
393
394    res = device->clearStreamingRequest();
395    if (res != OK) {
396        ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
397                __FUNCTION__, client->getCameraId(), strerror(-res), res);
398        return res;
399    }
400    res = device->waitUntilDrained();
401    if (res != OK) {
402        ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
403                __FUNCTION__, client->getCameraId(), strerror(-res), res);
404        return res;
405    }
406    return OK;
407}
408
409void StreamingProcessor::onFrameAvailable() {
410    ATRACE_CALL();
411    status_t res;
412    sp<Camera2Heap> recordingHeap;
413    size_t heapIdx = 0;
414    nsecs_t timestamp;
415
416    sp<Camera2Client> client = mClient.promote();
417    if (client == 0) return;
418
419    {
420        Mutex::Autolock m(mMutex);
421        BufferItemConsumer::BufferItem imgBuffer;
422        res = mRecordingConsumer->acquireBuffer(&imgBuffer);
423        if (res != OK) {
424            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
425                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
426            return;
427        }
428        timestamp = imgBuffer.mTimestamp;
429
430        mRecordingFrameCount++;
431        ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);
432
433        {
434            SharedParameters::Lock l(client->getParameters());
435            // TODO: Signal errors here upstream
436            if (l.mParameters.state != Parameters::RECORD &&
437                    l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
438                ALOGV("%s: Camera %d: Discarding recording image buffers "
439                        "received after recording done", __FUNCTION__,
440                        client->getCameraId());
441                mRecordingConsumer->releaseBuffer(imgBuffer);
442                return;
443            }
444        }
445
446        if (mRecordingHeap == 0) {
447            const size_t bufferSize = 4 + sizeof(buffer_handle_t);
448            ALOGV("%s: Camera %d: Creating recording heap with %d buffers of "
449                    "size %d bytes", __FUNCTION__, client->getCameraId(),
450                    mRecordingHeapCount, bufferSize);
451
452            mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount,
453                    "Camera2Client::RecordingHeap");
454            if (mRecordingHeap->mHeap->getSize() == 0) {
455                ALOGE("%s: Camera %d: Unable to allocate memory for recording",
456                        __FUNCTION__, client->getCameraId());
457                mRecordingConsumer->releaseBuffer(imgBuffer);
458                return;
459            }
460            for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
461                if (mRecordingBuffers[i].mBuf !=
462                        BufferItemConsumer::INVALID_BUFFER_SLOT) {
463                    ALOGE("%s: Camera %d: Non-empty recording buffers list!",
464                            __FUNCTION__, client->getCameraId());
465                }
466            }
467            mRecordingBuffers.clear();
468            mRecordingBuffers.setCapacity(mRecordingHeapCount);
469            mRecordingBuffers.insertAt(0, mRecordingHeapCount);
470
471            mRecordingHeapHead = 0;
472            mRecordingHeapFree = mRecordingHeapCount;
473        }
474
475        if ( mRecordingHeapFree == 0) {
476            ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
477                    __FUNCTION__, client->getCameraId());
478            mRecordingConsumer->releaseBuffer(imgBuffer);
479            return;
480        }
481
482        heapIdx = mRecordingHeapHead;
483        mRecordingHeapHead = (mRecordingHeapHead + 1) % mRecordingHeapCount;
484        mRecordingHeapFree--;
485
486        ALOGV("%s: Camera %d: Timestamp %lld",
487                __FUNCTION__, client->getCameraId(), timestamp);
488
489        ssize_t offset;
490        size_t size;
491        sp<IMemoryHeap> heap =
492                mRecordingHeap->mBuffers[heapIdx]->getMemory(&offset,
493                        &size);
494
495        uint8_t *data = (uint8_t*)heap->getBase() + offset;
496        uint32_t type = kMetadataBufferTypeGrallocSource;
497        *((uint32_t*)data) = type;
498        *((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle;
499        ALOGV("%s: Camera %d: Sending out buffer_handle_t %p",
500                __FUNCTION__, client->getCameraId(),
501                imgBuffer.mGraphicBuffer->handle);
502        mRecordingBuffers.replaceAt(imgBuffer, heapIdx);
503        recordingHeap = mRecordingHeap;
504    }
505
506    // Call outside locked parameters to allow re-entrancy from notification
507    Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
508    if (l.mCameraClient != 0) {
509        l.mCameraClient->dataCallbackTimestamp(timestamp,
510                CAMERA_MSG_VIDEO_FRAME,
511                recordingHeap->mBuffers[heapIdx]);
512    }
513}
514
515void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
516    ATRACE_CALL();
517    status_t res;
518
519    sp<Camera2Client> client = mClient.promote();
520    if (client == 0) return;
521
522    Mutex::Autolock m(mMutex);
523    // Make sure this is for the current heap
524    ssize_t offset;
525    size_t size;
526    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
527    if (heap->getHeapID() != mRecordingHeap->mHeap->getHeapID()) {
528        ALOGW("%s: Camera %d: Mismatched heap ID, ignoring release "
529                "(got %x, expected %x)", __FUNCTION__, client->getCameraId(),
530                heap->getHeapID(), mRecordingHeap->mHeap->getHeapID());
531        return;
532    }
533    uint8_t *data = (uint8_t*)heap->getBase() + offset;
534    uint32_t type = *(uint32_t*)data;
535    if (type != kMetadataBufferTypeGrallocSource) {
536        ALOGE("%s: Camera %d: Recording frame type invalid (got %x, expected %x)",
537                __FUNCTION__, client->getCameraId(), type,
538                kMetadataBufferTypeGrallocSource);
539        return;
540    }
541
542    // Release the buffer back to the recording queue
543
544    buffer_handle_t imgHandle = *(buffer_handle_t*)(data + 4);
545
546    size_t itemIndex;
547    for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
548        const BufferItemConsumer::BufferItem item =
549                mRecordingBuffers[itemIndex];
550        if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT &&
551                item.mGraphicBuffer->handle == imgHandle) {
552            break;
553        }
554    }
555    if (itemIndex == mRecordingBuffers.size()) {
556        ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of "
557                "outstanding buffers", __FUNCTION__, client->getCameraId(),
558                imgHandle);
559        return;
560    }
561
562    ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__,
563            client->getCameraId(), imgHandle);
564
565    res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
566    if (res != OK) {
567        ALOGE("%s: Camera %d: Unable to free recording frame "
568                "(buffer_handle_t: %p): %s (%d)", __FUNCTION__,
569                client->getCameraId(), imgHandle, strerror(-res), res);
570        return;
571    }
572    mRecordingBuffers.replaceAt(itemIndex);
573
574    mRecordingHeapFree++;
575}
576
577
578status_t StreamingProcessor::dump(int fd, const Vector<String16>& args) {
579    String8 result;
580
581    result.append("  Current requests:\n");
582    if (mPreviewRequest.entryCount() != 0) {
583        result.append("    Preview request:\n");
584        write(fd, result.string(), result.size());
585        mPreviewRequest.dump(fd, 2, 6);
586    } else {
587        result.append("    Preview request: undefined\n");
588        write(fd, result.string(), result.size());
589    }
590
591    if (mRecordingRequest.entryCount() != 0) {
592        result = "    Recording request:\n";
593        write(fd, result.string(), result.size());
594        mRecordingRequest.dump(fd, 2, 6);
595    } else {
596        result = "    Recording request: undefined\n";
597        write(fd, result.string(), result.size());
598    }
599
600    return OK;
601}
602
603}; // namespace camera2
604}; // namespace android
605