StreamingProcessor.cpp revision 22d58d37db6b5f48a10b3a19f69ffda09943c125
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    ALOGV("%s: Camera %d: type = %d", __FUNCTION__, client->getCameraId(), type);
355
356    Mutex::Autolock m(mMutex);
357
358    CameraMetadata &request = (type == PREVIEW) ?
359            mPreviewRequest : mRecordingRequest;
360
361    res = request.update(
362        ANDROID_REQUEST_OUTPUT_STREAMS,
363        outputStreams);
364    if (res != OK) {
365        ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
366                __FUNCTION__, client->getCameraId(), strerror(-res), res);
367        return res;
368    }
369
370    res = request.sort();
371    if (res != OK) {
372        ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
373                __FUNCTION__, client->getCameraId(), strerror(-res), res);
374        return res;
375    }
376
377    res = client->getCameraDevice()->setStreamingRequest(request);
378    if (res != OK) {
379        ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
380                "%s (%d)",
381                __FUNCTION__, client->getCameraId(), strerror(-res), res);
382        return res;
383    }
384
385    return OK;
386}
387
388status_t StreamingProcessor::stopStream() {
389    ATRACE_CALL();
390    status_t res;
391
392    sp<Camera2Client> client = mClient.promote();
393    if (client == 0) return INVALID_OPERATION;
394    sp<Camera2Device> device = client->getCameraDevice();
395
396    res = device->clearStreamingRequest();
397    if (res != OK) {
398        ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
399                __FUNCTION__, client->getCameraId(), strerror(-res), res);
400        return res;
401    }
402    res = device->waitUntilDrained();
403    if (res != OK) {
404        ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
405                __FUNCTION__, client->getCameraId(), strerror(-res), res);
406        return res;
407    }
408    return OK;
409}
410
411void StreamingProcessor::onFrameAvailable() {
412    ATRACE_CALL();
413    status_t res;
414    sp<Camera2Heap> recordingHeap;
415    size_t heapIdx = 0;
416    nsecs_t timestamp;
417
418    sp<Camera2Client> client = mClient.promote();
419    if (client == 0) return;
420
421    {
422        Mutex::Autolock m(mMutex);
423        BufferItemConsumer::BufferItem imgBuffer;
424        res = mRecordingConsumer->acquireBuffer(&imgBuffer);
425        if (res != OK) {
426            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
427                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
428            return;
429        }
430        timestamp = imgBuffer.mTimestamp;
431
432        mRecordingFrameCount++;
433        ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);
434
435        {
436            SharedParameters::Lock l(client->getParameters());
437            // TODO: Signal errors here upstream
438            if (l.mParameters.state != Parameters::RECORD &&
439                    l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
440                ALOGV("%s: Camera %d: Discarding recording image buffers "
441                        "received after recording done", __FUNCTION__,
442                        client->getCameraId());
443                mRecordingConsumer->releaseBuffer(imgBuffer);
444                return;
445            }
446        }
447
448        if (mRecordingHeap == 0) {
449            const size_t bufferSize = 4 + sizeof(buffer_handle_t);
450            ALOGV("%s: Camera %d: Creating recording heap with %d buffers of "
451                    "size %d bytes", __FUNCTION__, client->getCameraId(),
452                    mRecordingHeapCount, bufferSize);
453
454            mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount,
455                    "Camera2Client::RecordingHeap");
456            if (mRecordingHeap->mHeap->getSize() == 0) {
457                ALOGE("%s: Camera %d: Unable to allocate memory for recording",
458                        __FUNCTION__, client->getCameraId());
459                mRecordingConsumer->releaseBuffer(imgBuffer);
460                return;
461            }
462            for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
463                if (mRecordingBuffers[i].mBuf !=
464                        BufferItemConsumer::INVALID_BUFFER_SLOT) {
465                    ALOGE("%s: Camera %d: Non-empty recording buffers list!",
466                            __FUNCTION__, client->getCameraId());
467                }
468            }
469            mRecordingBuffers.clear();
470            mRecordingBuffers.setCapacity(mRecordingHeapCount);
471            mRecordingBuffers.insertAt(0, mRecordingHeapCount);
472
473            mRecordingHeapHead = 0;
474            mRecordingHeapFree = mRecordingHeapCount;
475        }
476
477        if ( mRecordingHeapFree == 0) {
478            ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
479                    __FUNCTION__, client->getCameraId());
480            mRecordingConsumer->releaseBuffer(imgBuffer);
481            return;
482        }
483
484        heapIdx = mRecordingHeapHead;
485        mRecordingHeapHead = (mRecordingHeapHead + 1) % mRecordingHeapCount;
486        mRecordingHeapFree--;
487
488        ALOGV("%s: Camera %d: Timestamp %lld",
489                __FUNCTION__, client->getCameraId(), timestamp);
490
491        ssize_t offset;
492        size_t size;
493        sp<IMemoryHeap> heap =
494                mRecordingHeap->mBuffers[heapIdx]->getMemory(&offset,
495                        &size);
496
497        uint8_t *data = (uint8_t*)heap->getBase() + offset;
498        uint32_t type = kMetadataBufferTypeGrallocSource;
499        *((uint32_t*)data) = type;
500        *((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle;
501        ALOGV("%s: Camera %d: Sending out buffer_handle_t %p",
502                __FUNCTION__, client->getCameraId(),
503                imgBuffer.mGraphicBuffer->handle);
504        mRecordingBuffers.replaceAt(imgBuffer, heapIdx);
505        recordingHeap = mRecordingHeap;
506    }
507
508    // Call outside locked parameters to allow re-entrancy from notification
509    Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
510    if (l.mCameraClient != 0) {
511        l.mCameraClient->dataCallbackTimestamp(timestamp,
512                CAMERA_MSG_VIDEO_FRAME,
513                recordingHeap->mBuffers[heapIdx]);
514    }
515}
516
517void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
518    ATRACE_CALL();
519    status_t res;
520
521    sp<Camera2Client> client = mClient.promote();
522    if (client == 0) return;
523
524    Mutex::Autolock m(mMutex);
525    // Make sure this is for the current heap
526    ssize_t offset;
527    size_t size;
528    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
529    if (heap->getHeapID() != mRecordingHeap->mHeap->getHeapID()) {
530        ALOGW("%s: Camera %d: Mismatched heap ID, ignoring release "
531                "(got %x, expected %x)", __FUNCTION__, client->getCameraId(),
532                heap->getHeapID(), mRecordingHeap->mHeap->getHeapID());
533        return;
534    }
535    uint8_t *data = (uint8_t*)heap->getBase() + offset;
536    uint32_t type = *(uint32_t*)data;
537    if (type != kMetadataBufferTypeGrallocSource) {
538        ALOGE("%s: Camera %d: Recording frame type invalid (got %x, expected %x)",
539                __FUNCTION__, client->getCameraId(), type,
540                kMetadataBufferTypeGrallocSource);
541        return;
542    }
543
544    // Release the buffer back to the recording queue
545
546    buffer_handle_t imgHandle = *(buffer_handle_t*)(data + 4);
547
548    size_t itemIndex;
549    for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
550        const BufferItemConsumer::BufferItem item =
551                mRecordingBuffers[itemIndex];
552        if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT &&
553                item.mGraphicBuffer->handle == imgHandle) {
554            break;
555        }
556    }
557    if (itemIndex == mRecordingBuffers.size()) {
558        ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of "
559                "outstanding buffers", __FUNCTION__, client->getCameraId(),
560                imgHandle);
561        return;
562    }
563
564    ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__,
565            client->getCameraId(), imgHandle);
566
567    res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
568    if (res != OK) {
569        ALOGE("%s: Camera %d: Unable to free recording frame "
570                "(buffer_handle_t: %p): %s (%d)", __FUNCTION__,
571                client->getCameraId(), imgHandle, strerror(-res), res);
572        return;
573    }
574    mRecordingBuffers.replaceAt(itemIndex);
575
576    mRecordingHeapFree++;
577}
578
579
580status_t StreamingProcessor::dump(int fd, const Vector<String16>& args) {
581    String8 result;
582
583    result.append("  Current requests:\n");
584    if (mPreviewRequest.entryCount() != 0) {
585        result.append("    Preview request:\n");
586        write(fd, result.string(), result.size());
587        mPreviewRequest.dump(fd, 2, 6);
588    } else {
589        result.append("    Preview request: undefined\n");
590        write(fd, result.string(), result.size());
591    }
592
593    if (mRecordingRequest.entryCount() != 0) {
594        result = "    Recording request:\n";
595        write(fd, result.string(), result.size());
596        mRecordingRequest.dump(fd, 2, 6);
597    } else {
598        result = "    Recording request: undefined\n";
599        write(fd, result.string(), result.size());
600    }
601
602    return OK;
603}
604
605}; // namespace camera2
606}; // namespace android
607