StreamingProcessor.cpp revision 04273cb14d2326e85bb047ea6ef75294c8b3d561
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        ALOGV("%s: for cameraId %d on streamId %d",
174            __FUNCTION__, client->getCameraId(), mPreviewStreamId);
175
176        res = device->waitUntilDrained();
177        if (res != OK) {
178            ALOGE("%s: Error waiting for preview to drain: %s (%d)",
179                    __FUNCTION__, strerror(-res), res);
180            return res;
181        }
182        res = device->deleteStream(mPreviewStreamId);
183        if (res != OK) {
184            ALOGE("%s: Unable to delete old preview stream: %s (%d)",
185                    __FUNCTION__, strerror(-res), res);
186            return res;
187        }
188        mPreviewStreamId = NO_STREAM;
189    }
190    return OK;
191}
192
193status_t StreamingProcessor::getPreviewStreamId() const {
194    Mutex::Autolock m(mMutex);
195    return mPreviewStreamId;
196}
197
198status_t StreamingProcessor::setRecordingBufferCount(size_t count) {
199    ATRACE_CALL();
200    // 32 is the current upper limit on the video buffer count for BufferQueue
201    sp<Camera2Client> client = mClient.promote();
202    if (client == 0) return INVALID_OPERATION;
203    if (count > 32) {
204        ALOGE("%s: Camera %d: Error setting %d as video buffer count value",
205                __FUNCTION__, client->getCameraId(), count);
206        return BAD_VALUE;
207    }
208
209    Mutex::Autolock m(mMutex);
210
211    // Need to reallocate memory for heap
212    if (mRecordingHeapCount != count) {
213        if  (mRecordingHeap != 0) {
214            mRecordingHeap.clear();
215            mRecordingHeap = NULL;
216        }
217        mRecordingHeapCount = count;
218    }
219
220    return OK;
221}
222
223status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
224    ATRACE_CALL();
225    status_t res;
226    Mutex::Autolock m(mMutex);
227
228    sp<Camera2Client> client = mClient.promote();
229    if (client == 0) return INVALID_OPERATION;
230
231    if (mRecordingRequest.entryCount() == 0) {
232        res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
233                &mRecordingRequest);
234        if (res != OK) {
235            ALOGE("%s: Camera %d: Unable to create default recording request:"
236                    " %s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
237            return res;
238        }
239    }
240
241    res = params.updateRequest(&mRecordingRequest);
242    if (res != OK) {
243        ALOGE("%s: Camera %d: Unable to update common entries of recording "
244                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
245                strerror(-res), res);
246        return res;
247    }
248
249    return OK;
250}
251
252status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
253    ATRACE_CALL();
254    status_t res;
255    Mutex::Autolock m(mMutex);
256
257    sp<Camera2Client> client = mClient.promote();
258    if (client == 0) return INVALID_OPERATION;
259    sp<Camera2Device> device = client->getCameraDevice();
260
261    if (mRecordingConsumer == 0) {
262        // Create CPU buffer queue endpoint. We need one more buffer here so that we can
263        // always acquire and free a buffer when the heap is full; otherwise the consumer
264        // will have buffers in flight we'll never clear out.
265        mRecordingConsumer = new BufferItemConsumer(
266                GRALLOC_USAGE_HW_VIDEO_ENCODER,
267                mRecordingHeapCount + 1,
268                true);
269        mRecordingConsumer->setFrameAvailableListener(this);
270        mRecordingConsumer->setName(String8("Camera2-RecordingConsumer"));
271        mRecordingWindow = new SurfaceTextureClient(
272            mRecordingConsumer->getProducerInterface());
273        // Allocate memory later, since we don't know buffer size until receipt
274    }
275
276    if (mRecordingStreamId != NO_STREAM) {
277        // Check if stream parameters have to change
278        uint32_t currentWidth, currentHeight;
279        res = device->getStreamInfo(mRecordingStreamId,
280                &currentWidth, &currentHeight, 0);
281        if (res != OK) {
282            ALOGE("%s: Camera %d: Error querying recording output stream info: "
283                    "%s (%d)", __FUNCTION__, client->getCameraId(),
284                    strerror(-res), res);
285            return res;
286        }
287        if (currentWidth != (uint32_t)params.videoWidth ||
288                currentHeight != (uint32_t)params.videoHeight) {
289            // TODO: Should wait to be sure previous recording has finished
290            res = device->deleteStream(mRecordingStreamId);
291            if (res != OK) {
292                ALOGE("%s: Camera %d: Unable to delete old output stream "
293                        "for recording: %s (%d)", __FUNCTION__,
294                        client->getCameraId(), strerror(-res), res);
295                return res;
296            }
297            mRecordingStreamId = NO_STREAM;
298        }
299    }
300
301    if (mRecordingStreamId == NO_STREAM) {
302        mRecordingFrameCount = 0;
303        res = device->createStream(mRecordingWindow,
304                params.videoWidth, params.videoHeight,
305                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mRecordingStreamId);
306        if (res != OK) {
307            ALOGE("%s: Camera %d: Can't create output stream for recording: "
308                    "%s (%d)", __FUNCTION__, client->getCameraId(),
309                    strerror(-res), res);
310            return res;
311        }
312    }
313
314    return OK;
315}
316
317status_t StreamingProcessor::deleteRecordingStream() {
318    ATRACE_CALL();
319    status_t res;
320
321    Mutex::Autolock m(mMutex);
322
323    if (mRecordingStreamId != NO_STREAM) {
324        sp<Camera2Client> client = mClient.promote();
325        if (client == 0) return INVALID_OPERATION;
326        sp<Camera2Device> device = client->getCameraDevice();
327
328        res = device->waitUntilDrained();
329        if (res != OK) {
330            ALOGE("%s: Error waiting for HAL to drain: %s (%d)",
331                    __FUNCTION__, strerror(-res), res);
332            return res;
333        }
334        res = device->deleteStream(mRecordingStreamId);
335        if (res != OK) {
336            ALOGE("%s: Unable to delete recording stream: %s (%d)",
337                    __FUNCTION__, strerror(-res), res);
338            return res;
339        }
340        mRecordingStreamId = NO_STREAM;
341    }
342    return OK;
343}
344
345status_t StreamingProcessor::getRecordingStreamId() const {
346    return mRecordingStreamId;
347}
348
349status_t StreamingProcessor::startStream(StreamType type,
350        const Vector<uint8_t> &outputStreams) {
351    ATRACE_CALL();
352    status_t res;
353
354    sp<Camera2Client> client = mClient.promote();
355    if (client == 0) return INVALID_OPERATION;
356
357    ALOGV("%s: Camera %d: type = %d", __FUNCTION__, client->getCameraId(), type);
358
359    Mutex::Autolock m(mMutex);
360
361    CameraMetadata &request = (type == PREVIEW) ?
362            mPreviewRequest : mRecordingRequest;
363
364    res = request.update(
365        ANDROID_REQUEST_OUTPUT_STREAMS,
366        outputStreams);
367    if (res != OK) {
368        ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
369                __FUNCTION__, client->getCameraId(), strerror(-res), res);
370        return res;
371    }
372
373    res = request.sort();
374    if (res != OK) {
375        ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
376                __FUNCTION__, client->getCameraId(), strerror(-res), res);
377        return res;
378    }
379
380    res = client->getCameraDevice()->setStreamingRequest(request);
381    if (res != OK) {
382        ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
383                "%s (%d)",
384                __FUNCTION__, client->getCameraId(), strerror(-res), res);
385        return res;
386    }
387
388    return OK;
389}
390
391status_t StreamingProcessor::stopStream() {
392    ATRACE_CALL();
393    status_t res;
394
395    sp<Camera2Client> client = mClient.promote();
396    if (client == 0) return INVALID_OPERATION;
397    sp<Camera2Device> device = client->getCameraDevice();
398
399    res = device->clearStreamingRequest();
400    if (res != OK) {
401        ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
402                __FUNCTION__, client->getCameraId(), strerror(-res), res);
403        return res;
404    }
405    res = device->waitUntilDrained();
406    if (res != OK) {
407        ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
408                __FUNCTION__, client->getCameraId(), strerror(-res), res);
409        return res;
410    }
411    return OK;
412}
413
414void StreamingProcessor::onFrameAvailable() {
415    ATRACE_CALL();
416    status_t res;
417    sp<Camera2Heap> recordingHeap;
418    size_t heapIdx = 0;
419    nsecs_t timestamp;
420
421    sp<Camera2Client> client = mClient.promote();
422    if (client == 0) return;
423
424    {
425        /* acquire SharedParameters before mMutex so we don't dead lock
426            with Camera2Client code calling into StreamingProcessor */
427        SharedParameters::Lock l(client->getParameters());
428        Mutex::Autolock m(mMutex);
429        BufferItemConsumer::BufferItem imgBuffer;
430        res = mRecordingConsumer->acquireBuffer(&imgBuffer);
431        if (res != OK) {
432            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
433                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
434            return;
435        }
436        timestamp = imgBuffer.mTimestamp;
437
438        mRecordingFrameCount++;
439        ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);
440
441        // TODO: Signal errors here upstream
442        if (l.mParameters.state != Parameters::RECORD &&
443                l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
444            ALOGV("%s: Camera %d: Discarding recording image buffers "
445                    "received after recording done", __FUNCTION__,
446                    client->getCameraId());
447            mRecordingConsumer->releaseBuffer(imgBuffer);
448            return;
449        }
450
451        if (mRecordingHeap == 0) {
452            const size_t bufferSize = 4 + sizeof(buffer_handle_t);
453            ALOGV("%s: Camera %d: Creating recording heap with %d buffers of "
454                    "size %d bytes", __FUNCTION__, client->getCameraId(),
455                    mRecordingHeapCount, bufferSize);
456
457            mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount,
458                    "Camera2Client::RecordingHeap");
459            if (mRecordingHeap->mHeap->getSize() == 0) {
460                ALOGE("%s: Camera %d: Unable to allocate memory for recording",
461                        __FUNCTION__, client->getCameraId());
462                mRecordingConsumer->releaseBuffer(imgBuffer);
463                return;
464            }
465            for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
466                if (mRecordingBuffers[i].mBuf !=
467                        BufferItemConsumer::INVALID_BUFFER_SLOT) {
468                    ALOGE("%s: Camera %d: Non-empty recording buffers list!",
469                            __FUNCTION__, client->getCameraId());
470                }
471            }
472            mRecordingBuffers.clear();
473            mRecordingBuffers.setCapacity(mRecordingHeapCount);
474            mRecordingBuffers.insertAt(0, mRecordingHeapCount);
475
476            mRecordingHeapHead = 0;
477            mRecordingHeapFree = mRecordingHeapCount;
478        }
479
480        if ( mRecordingHeapFree == 0) {
481            ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
482                    __FUNCTION__, client->getCameraId());
483            mRecordingConsumer->releaseBuffer(imgBuffer);
484            return;
485        }
486
487        heapIdx = mRecordingHeapHead;
488        mRecordingHeapHead = (mRecordingHeapHead + 1) % mRecordingHeapCount;
489        mRecordingHeapFree--;
490
491        ALOGV("%s: Camera %d: Timestamp %lld",
492                __FUNCTION__, client->getCameraId(), timestamp);
493
494        ssize_t offset;
495        size_t size;
496        sp<IMemoryHeap> heap =
497                mRecordingHeap->mBuffers[heapIdx]->getMemory(&offset,
498                        &size);
499
500        uint8_t *data = (uint8_t*)heap->getBase() + offset;
501        uint32_t type = kMetadataBufferTypeGrallocSource;
502        *((uint32_t*)data) = type;
503        *((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle;
504        ALOGV("%s: Camera %d: Sending out buffer_handle_t %p",
505                __FUNCTION__, client->getCameraId(),
506                imgBuffer.mGraphicBuffer->handle);
507        mRecordingBuffers.replaceAt(imgBuffer, heapIdx);
508        recordingHeap = mRecordingHeap;
509    }
510
511    // Call outside locked parameters to allow re-entrancy from notification
512    Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
513    if (l.mCameraClient != 0) {
514        l.mCameraClient->dataCallbackTimestamp(timestamp,
515                CAMERA_MSG_VIDEO_FRAME,
516                recordingHeap->mBuffers[heapIdx]);
517    }
518}
519
520void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
521    ATRACE_CALL();
522    status_t res;
523
524    sp<Camera2Client> client = mClient.promote();
525    if (client == 0) return;
526
527    Mutex::Autolock m(mMutex);
528    // Make sure this is for the current heap
529    ssize_t offset;
530    size_t size;
531    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
532    if (heap->getHeapID() != mRecordingHeap->mHeap->getHeapID()) {
533        ALOGW("%s: Camera %d: Mismatched heap ID, ignoring release "
534                "(got %x, expected %x)", __FUNCTION__, client->getCameraId(),
535                heap->getHeapID(), mRecordingHeap->mHeap->getHeapID());
536        return;
537    }
538    uint8_t *data = (uint8_t*)heap->getBase() + offset;
539    uint32_t type = *(uint32_t*)data;
540    if (type != kMetadataBufferTypeGrallocSource) {
541        ALOGE("%s: Camera %d: Recording frame type invalid (got %x, expected %x)",
542                __FUNCTION__, client->getCameraId(), type,
543                kMetadataBufferTypeGrallocSource);
544        return;
545    }
546
547    // Release the buffer back to the recording queue
548
549    buffer_handle_t imgHandle = *(buffer_handle_t*)(data + 4);
550
551    size_t itemIndex;
552    for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
553        const BufferItemConsumer::BufferItem item =
554                mRecordingBuffers[itemIndex];
555        if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT &&
556                item.mGraphicBuffer->handle == imgHandle) {
557            break;
558        }
559    }
560    if (itemIndex == mRecordingBuffers.size()) {
561        ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of "
562                "outstanding buffers", __FUNCTION__, client->getCameraId(),
563                imgHandle);
564        return;
565    }
566
567    ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__,
568            client->getCameraId(), imgHandle);
569
570    res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
571    if (res != OK) {
572        ALOGE("%s: Camera %d: Unable to free recording frame "
573                "(buffer_handle_t: %p): %s (%d)", __FUNCTION__,
574                client->getCameraId(), imgHandle, strerror(-res), res);
575        return;
576    }
577    mRecordingBuffers.replaceAt(itemIndex);
578
579    mRecordingHeapFree++;
580}
581
582
583status_t StreamingProcessor::dump(int fd, const Vector<String16>& args) {
584    String8 result;
585
586    result.append("  Current requests:\n");
587    if (mPreviewRequest.entryCount() != 0) {
588        result.append("    Preview request:\n");
589        write(fd, result.string(), result.size());
590        mPreviewRequest.dump(fd, 2, 6);
591    } else {
592        result.append("    Preview request: undefined\n");
593        write(fd, result.string(), result.size());
594    }
595
596    if (mRecordingRequest.entryCount() != 0) {
597        result = "    Recording request:\n";
598        write(fd, result.string(), result.size());
599        mRecordingRequest.dump(fd, 2, 6);
600    } else {
601        result = "    Recording request: undefined\n";
602        write(fd, result.string(), result.size());
603    }
604
605    return OK;
606}
607
608}; // namespace camera2
609}; // namespace android
610