JpegProcessor.cpp revision da6665cbd06ca58d3357c3002b7366d13e23f152
1b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber/*
2b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber *
4b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * you may not use this file except in compliance with the License.
6b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * You may obtain a copy of the License at
7b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber *
8b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber *
10b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * Unless required by applicable law or agreed to in writing, software
11b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * See the License for the specific language governing permissions and
14b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * limitations under the License.
15b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber */
16b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
17b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#define LOG_TAG "Camera2Client::JpegProcessor"
18b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#define ATRACE_TAG ATRACE_TAG_CAMERA
19b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber//#define LOG_NDEBUG 0
20b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
21b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include <utils/Log.h>
22b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include <utils/Trace.h>
23b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
24b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include "JpegProcessor.h"
25b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include <gui/SurfaceTextureClient.h>
26b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include "../Camera2Device.h"
27b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include "../Camera2Client.h"
28b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
29b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
30b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Hubernamespace android {
31b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Hubernamespace camera2 {
32b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
33b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas HuberJpegProcessor::JpegProcessor(
34b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    wp<Camera2Client> client,
35b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    wp<CaptureSequencer> sequencer):
36b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        Thread(false),
37b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mClient(client),
38b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mSequencer(sequencer),
39b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureAvailable(false),
40b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureStreamId(NO_STREAM) {
41b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber}
42b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
43b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas HuberJpegProcessor::~JpegProcessor() {
44b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    ALOGV("%s: Exit", __FUNCTION__);
45b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber}
46b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
47b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Hubervoid JpegProcessor::onFrameAvailable() {
48b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    Mutex::Autolock l(mInputMutex);
49b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    if (!mCaptureAvailable) {
50b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureAvailable = true;
51b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureAvailableSignal.signal();
52b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    }
53b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber}
54b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
55b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huberstatus_t JpegProcessor::updateStream(const Parameters &params) {
56b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    ATRACE_CALL();
57b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    ALOGV("%s", __FUNCTION__);
58b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    status_t res;
59b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
60b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    Mutex::Autolock l(mInputMutex);
61b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
62b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    sp<Camera2Client> client = mClient.promote();
63b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    if (client == 0) return OK;
64b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    sp<Camera2Device> device = client->getCameraDevice();
65b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
66b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    // Find out buffer size for JPEG
67b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    camera_metadata_ro_entry_t maxJpegSize =
68b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            params.staticInfo(ANDROID_JPEG_MAX_SIZE);
69b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    if (maxJpegSize.count == 0) {
70b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
71b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                __FUNCTION__, client->getCameraId());
72b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        return INVALID_OPERATION;
73b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    }
74b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
75b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    if (mCaptureConsumer == 0) {
76b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        // Create CPU buffer queue endpoint
77b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureConsumer = new CpuConsumer(1);
78b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureConsumer->setFrameAvailableListener(this);
79b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer"));
80b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureWindow = new SurfaceTextureClient(
81b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            mCaptureConsumer->getProducerInterface());
82b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        // Create memory for API consumption
83b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        mCaptureHeap = new Camera2Heap(maxJpegSize.data.i32[0], 1,
84b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                                       "Camera2Client::CaptureHeap");
85b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        if (mCaptureHeap->mHeap->getSize() == 0) {
86b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            ALOGE("%s: Camera %d: Unable to allocate memory for capture",
87b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                    __FUNCTION__, client->getCameraId());
88b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            return NO_MEMORY;
89b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        }
90b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    }
91b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
92b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    if (mCaptureStreamId != NO_STREAM) {
93b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        // Check if stream parameters have to change
94b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        uint32_t currentWidth, currentHeight;
95b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        res = device->getStreamInfo(mCaptureStreamId,
96b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                &currentWidth, &currentHeight, 0);
97b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        if (res != OK) {
98b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            ALOGE("%s: Camera %d: Error querying capture output stream info: "
99b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                    "%s (%d)", __FUNCTION__,
100b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                    client->getCameraId(), strerror(-res), res);
101b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            return res;
102b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        }
103b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        if (currentWidth != (uint32_t)params.pictureWidth ||
104b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                currentHeight != (uint32_t)params.pictureHeight) {
105b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            res = device->deleteStream(mCaptureStreamId);
106b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            if (res != OK) {
107b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                ALOGE("%s: Camera %d: Unable to delete old output stream "
108b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                        "for capture: %s (%d)", __FUNCTION__,
109b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                        client->getCameraId(), strerror(-res), res);
110b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber                return res;
111b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            }
112b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber            mCaptureStreamId = NO_STREAM;
113b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber        }
114b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    }
115b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber
116b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber    if (mCaptureStreamId == NO_STREAM) {
117        // Create stream for HAL production
118        res = device->createStream(mCaptureWindow,
119                params.pictureWidth, params.pictureHeight,
120                HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0],
121                &mCaptureStreamId);
122        if (res != OK) {
123            ALOGE("%s: Camera %d: Can't create output stream for capture: "
124                    "%s (%d)", __FUNCTION__, client->getCameraId(),
125                    strerror(-res), res);
126            return res;
127        }
128
129    }
130    return OK;
131}
132
133status_t JpegProcessor::deleteStream() {
134    ATRACE_CALL();
135    status_t res;
136
137    Mutex::Autolock l(mInputMutex);
138
139    if (mCaptureStreamId != NO_STREAM) {
140        sp<Camera2Client> client = mClient.promote();
141        if (client == 0) return OK;
142        sp<Camera2Device> device = client->getCameraDevice();
143
144        device->deleteStream(mCaptureStreamId);
145        mCaptureStreamId = NO_STREAM;
146    }
147    return OK;
148}
149
150int JpegProcessor::getStreamId() const {
151    Mutex::Autolock l(mInputMutex);
152    return mCaptureStreamId;
153}
154
155void JpegProcessor::dump(int fd, const Vector<String16>& args) const {
156}
157
158bool JpegProcessor::threadLoop() {
159    status_t res;
160
161    {
162        Mutex::Autolock l(mInputMutex);
163        while (!mCaptureAvailable) {
164            res = mCaptureAvailableSignal.waitRelative(mInputMutex,
165                    kWaitDuration);
166            if (res == TIMED_OUT) return true;
167        }
168        mCaptureAvailable = false;
169    }
170
171    do {
172        sp<Camera2Client> client = mClient.promote();
173        if (client == 0) return false;
174        res = processNewCapture(client);
175    } while (res == OK);
176
177    return true;
178}
179
180status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) {
181    ATRACE_CALL();
182    status_t res;
183    sp<Camera2Heap> captureHeap;
184
185    CpuConsumer::LockedBuffer imgBuffer;
186
187    res = mCaptureConsumer->lockNextBuffer(&imgBuffer);
188    if (res != OK) {
189        if (res != BAD_VALUE) {
190            ALOGE("%s: Camera %d: Error receiving still image buffer: "
191                    "%s (%d)", __FUNCTION__,
192                    client->getCameraId(), strerror(-res), res);
193        }
194        return res;
195    }
196
197    ALOGV("%s: Camera %d: Still capture available", __FUNCTION__,
198            client->getCameraId());
199
200    // TODO: Signal errors here upstream
201    {
202        SharedParameters::Lock l(client->getParameters());
203
204        switch (l.mParameters.state) {
205            case Parameters::STILL_CAPTURE:
206            case Parameters::VIDEO_SNAPSHOT:
207                break;
208            default:
209                ALOGE("%s: Camera %d: Still image produced unexpectedly "
210                        "in state %s!",
211                        __FUNCTION__, client->getCameraId(),
212                        Parameters::getStateName(l.mParameters.state));
213                mCaptureConsumer->unlockBuffer(imgBuffer);
214                return BAD_VALUE;
215        }
216    }
217
218    if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
219        ALOGE("%s: Camera %d: Unexpected format for still image: "
220                "%x, expected %x", __FUNCTION__, client->getCameraId(),
221                imgBuffer.format,
222                HAL_PIXEL_FORMAT_BLOB);
223        mCaptureConsumer->unlockBuffer(imgBuffer);
224        return OK;
225    }
226
227    sp<CaptureSequencer> sequencer = mSequencer.promote();
228    if (sequencer != 0) {
229        sequencer->onCaptureAvailable(imgBuffer.timestamp);
230    }
231
232    // TODO: Optimize this to avoid memcopy
233    void* captureMemory = mCaptureHeap->mHeap->getBase();
234    size_t size = mCaptureHeap->mHeap->getSize();
235    memcpy(captureMemory, imgBuffer.data, size);
236
237    mCaptureConsumer->unlockBuffer(imgBuffer);
238
239    captureHeap = mCaptureHeap;
240
241    Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
242    ALOGV("%s: Sending still image to client", __FUNCTION__);
243    if (l.mCameraClient != 0) {
244        l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
245                captureHeap->mBuffers[0], NULL);
246    } else {
247        ALOGV("%s: No client!", __FUNCTION__);
248    }
249    return OK;
250}
251
252}; // namespace camera2
253}; // namespace android
254