JpegProcessor.cpp revision 4bb8118816874c696d9f1adab48490df1da365f7
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-JpegProcessor"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <netinet/in.h>
22
23#include <utils/Log.h>
24#include <utils/Trace.h>
25
26#include "JpegProcessor.h"
27#include <gui/SurfaceTextureClient.h>
28#include "../Camera2Device.h"
29#include "../Camera2Client.h"
30
31
32namespace android {
33namespace camera2 {
34
35JpegProcessor::JpegProcessor(
36    wp<Camera2Client> client,
37    wp<CaptureSequencer> sequencer):
38        Thread(false),
39        mClient(client),
40        mSequencer(sequencer),
41        mCaptureAvailable(false),
42        mCaptureStreamId(NO_STREAM) {
43}
44
45JpegProcessor::~JpegProcessor() {
46    ALOGV("%s: Exit", __FUNCTION__);
47    deleteStream();
48}
49
50void JpegProcessor::onFrameAvailable() {
51    Mutex::Autolock l(mInputMutex);
52    if (!mCaptureAvailable) {
53        mCaptureAvailable = true;
54        mCaptureAvailableSignal.signal();
55    }
56}
57
58status_t JpegProcessor::updateStream(const Parameters &params) {
59    ATRACE_CALL();
60    ALOGV("%s", __FUNCTION__);
61    status_t res;
62
63    Mutex::Autolock l(mInputMutex);
64
65    sp<Camera2Client> client = mClient.promote();
66    if (client == 0) return OK;
67    sp<Camera2Device> device = client->getCameraDevice();
68
69    // Find out buffer size for JPEG
70    camera_metadata_ro_entry_t maxJpegSize =
71            params.staticInfo(ANDROID_JPEG_MAX_SIZE);
72    if (maxJpegSize.count == 0) {
73        ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
74                __FUNCTION__, client->getCameraId());
75        return INVALID_OPERATION;
76    }
77
78    if (mCaptureConsumer == 0) {
79        // Create CPU buffer queue endpoint
80        mCaptureConsumer = new CpuConsumer(1);
81        mCaptureConsumer->setFrameAvailableListener(this);
82        mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer"));
83        mCaptureWindow = new SurfaceTextureClient(
84            mCaptureConsumer->getProducerInterface());
85        // Create memory for API consumption
86        mCaptureHeap = new MemoryHeapBase(maxJpegSize.data.i32[0], 0,
87                                       "Camera2Client::CaptureHeap");
88        if (mCaptureHeap->getSize() == 0) {
89            ALOGE("%s: Camera %d: Unable to allocate memory for capture",
90                    __FUNCTION__, client->getCameraId());
91            return NO_MEMORY;
92        }
93    }
94
95    if (mCaptureStreamId != NO_STREAM) {
96        // Check if stream parameters have to change
97        uint32_t currentWidth, currentHeight;
98        res = device->getStreamInfo(mCaptureStreamId,
99                &currentWidth, &currentHeight, 0);
100        if (res != OK) {
101            ALOGE("%s: Camera %d: Error querying capture output stream info: "
102                    "%s (%d)", __FUNCTION__,
103                    client->getCameraId(), strerror(-res), res);
104            return res;
105        }
106        if (currentWidth != (uint32_t)params.pictureWidth ||
107                currentHeight != (uint32_t)params.pictureHeight) {
108            res = device->deleteStream(mCaptureStreamId);
109            if (res != OK) {
110                ALOGE("%s: Camera %d: Unable to delete old output stream "
111                        "for capture: %s (%d)", __FUNCTION__,
112                        client->getCameraId(), strerror(-res), res);
113                return res;
114            }
115            mCaptureStreamId = NO_STREAM;
116        }
117    }
118
119    if (mCaptureStreamId == NO_STREAM) {
120        // Create stream for HAL production
121        res = device->createStream(mCaptureWindow,
122                params.pictureWidth, params.pictureHeight,
123                HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0],
124                &mCaptureStreamId);
125        if (res != OK) {
126            ALOGE("%s: Camera %d: Can't create output stream for capture: "
127                    "%s (%d)", __FUNCTION__, client->getCameraId(),
128                    strerror(-res), res);
129            return res;
130        }
131
132    }
133    return OK;
134}
135
136status_t JpegProcessor::deleteStream() {
137    ATRACE_CALL();
138    status_t res;
139
140    Mutex::Autolock l(mInputMutex);
141
142    if (mCaptureStreamId != NO_STREAM) {
143        sp<Camera2Client> client = mClient.promote();
144        if (client == 0) return OK;
145        sp<Camera2Device> device = client->getCameraDevice();
146
147        device->deleteStream(mCaptureStreamId);
148
149        mCaptureHeap.clear();
150        mCaptureWindow.clear();
151        mCaptureConsumer.clear();
152
153        mCaptureStreamId = NO_STREAM;
154    }
155    return OK;
156}
157
158int JpegProcessor::getStreamId() const {
159    Mutex::Autolock l(mInputMutex);
160    return mCaptureStreamId;
161}
162
163void JpegProcessor::dump(int fd, const Vector<String16>& args) const {
164}
165
166bool JpegProcessor::threadLoop() {
167    status_t res;
168
169    {
170        Mutex::Autolock l(mInputMutex);
171        while (!mCaptureAvailable) {
172            res = mCaptureAvailableSignal.waitRelative(mInputMutex,
173                    kWaitDuration);
174            if (res == TIMED_OUT) return true;
175        }
176        mCaptureAvailable = false;
177    }
178
179    do {
180        sp<Camera2Client> client = mClient.promote();
181        if (client == 0) return false;
182        res = processNewCapture(client);
183    } while (res == OK);
184
185    return true;
186}
187
188status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) {
189    ATRACE_CALL();
190    status_t res;
191    sp<Camera2Heap> captureHeap;
192
193    CpuConsumer::LockedBuffer imgBuffer;
194
195    res = mCaptureConsumer->lockNextBuffer(&imgBuffer);
196    if (res != OK) {
197        if (res != BAD_VALUE) {
198            ALOGE("%s: Camera %d: Error receiving still image buffer: "
199                    "%s (%d)", __FUNCTION__,
200                    client->getCameraId(), strerror(-res), res);
201        }
202        return res;
203    }
204
205    ALOGV("%s: Camera %d: Still capture available", __FUNCTION__,
206            client->getCameraId());
207
208    // TODO: Signal errors here upstream
209    {
210        SharedParameters::Lock l(client->getParameters());
211
212        switch (l.mParameters.state) {
213            case Parameters::STILL_CAPTURE:
214            case Parameters::VIDEO_SNAPSHOT:
215                break;
216            default:
217                ALOGE("%s: Camera %d: Still image produced unexpectedly "
218                        "in state %s!",
219                        __FUNCTION__, client->getCameraId(),
220                        Parameters::getStateName(l.mParameters.state));
221                mCaptureConsumer->unlockBuffer(imgBuffer);
222                return BAD_VALUE;
223        }
224    }
225
226    if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
227        ALOGE("%s: Camera %d: Unexpected format for still image: "
228                "%x, expected %x", __FUNCTION__, client->getCameraId(),
229                imgBuffer.format,
230                HAL_PIXEL_FORMAT_BLOB);
231        mCaptureConsumer->unlockBuffer(imgBuffer);
232        return OK;
233    }
234
235    // Find size of JPEG image
236    uint8_t *jpegStart; // points to start of buffer in imgBuffer.data
237    size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width, &jpegStart);
238    size_t heapSize = mCaptureHeap->getSize();
239    if (jpegSize == 0) jpegSize = imgBuffer.width;
240    if (jpegSize > heapSize) {
241        ALOGW("%s: JPEG image is larger than expected, truncating "
242                "(got %d, expected at most %d bytes)",
243                __FUNCTION__, jpegSize, heapSize);
244        jpegSize = heapSize;
245    }
246
247    // TODO: Optimize this to avoid memcopy
248    sp<MemoryBase> captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize);
249    void* captureMemory = mCaptureHeap->getBase();
250    memcpy(captureMemory, imgBuffer.data, jpegSize);
251
252    mCaptureConsumer->unlockBuffer(imgBuffer);
253
254    sp<CaptureSequencer> sequencer = mSequencer.promote();
255    if (sequencer != 0) {
256        sequencer->onCaptureAvailable(imgBuffer.timestamp, captureBuffer);
257    }
258
259    return OK;
260}
261
262/*
263 * JPEG FILE FORMAT OVERVIEW.
264 * http://www.jpeg.org/public/jfif.pdf
265 * (JPEG is the image compression algorithm, actual file format is called JFIF)
266 *
267 * "Markers" are 2-byte patterns used to distinguish parts of JFIF files.  The
268 * first byte is always 0xFF, and the second byte is between 0x01 and 0xFE
269 * (inclusive).  Because every marker begins with the same byte, they are
270 * referred to by the second byte's value.
271 *
272 * JFIF files all begin with the Start of Image (SOI) marker, which is 0xD8.
273 * Following it, "segment" sections begin with other markers, followed by a
274 * 2-byte length (in network byte order), then the segment data.
275 *
276 * For our purposes we will ignore the data, and just use the length to skip to
277 * the next segment.  This is necessary because the data inside segments are
278 * allowed to contain the End of Image marker (0xFF 0xD9), preventing us from
279 * naievely scanning until the end.
280 *
281 * After all the segments are processed, the jpeg compressed image stream begins.
282 * This can be considered an opaque format with one requirement: all 0xFF bytes
283 * in this stream must be followed with a 0x00 byte.  This prevents any of the
284 * image data to be interpreted as a segment.  The only exception to this is at
285 * the end of the image stream there is an End of Image (EOI) marker, which is
286 * 0xFF followed by a non-zero (0xD9) byte.
287 */
288
289const uint8_t MARK = 0xFF; // First byte of marker
290const uint8_t SOI = 0xD8; // Start of Image
291const uint8_t EOI = 0xD9; // End of Image
292const size_t MARKER_LENGTH = 2; // length of a marker
293
294#pragma pack(push)
295#pragma pack(1)
296typedef struct segment {
297    uint8_t marker[MARKER_LENGTH];
298    uint16_t length;
299} segment_t;
300#pragma pack(pop)
301
302/* HELPER FUNCTIONS */
303
304// check for Start of Image marker
305bool checkJpegStart(uint8_t* buf) {
306    return buf[0] == MARK && buf[1] == SOI;
307}
308// check for End of Image marker
309bool checkJpegEnd(uint8_t *buf) {
310    return buf[0] == MARK && buf[1] == EOI;
311}
312// check for arbitrary marker, returns marker type (second byte)
313// returns 0 if no marker found. Note: 0x00 is not a valid marker type
314uint8_t checkJpegMarker(uint8_t *buf) {
315    if (buf[0] == MARK && buf[1] > 0 && buf[1] < 0xFF) {
316        return buf[1];
317    }
318    return 0;
319}
320
321// Return the size of the JPEG, 0 indicates failure
322size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer,
323                                   size_t maxSize,
324                                   uint8_t** jpegStart) {
325    uint8_t *start;
326    size_t size;
327
328    // First check for JPEG transport header
329    struct camera2_jpeg_blob *blob = (struct camera2_jpeg_blob*)(jpegBuffer);
330    if (blob->jpeg_blob_id == CAMERA2_JPEG_BLOB_ID) {
331        size = blob->jpeg_size;
332        if (size > 0 && size <= maxSize - sizeof(struct camera2_jpeg_blob)) {
333            // Verify SOI and EOI markers
334            uint8_t *start = blob->jpeg_data;
335            size_t offset = size - MARKER_LENGTH;
336            uint8_t *end = blob->jpeg_data + offset;
337            if (checkJpegStart(start) && checkJpegEnd(end)) {
338                ALOGV("Found JPEG transport header, img size %d", size);
339                *jpegStart = start;
340                return size;
341            } else {
342                ALOGW("Found JPEG transport header with bad Image Start/End");
343            }
344        } else {
345            ALOGW("Found JPEG transport header with bad size %d", size);
346        }
347    }
348
349    // Find Start of Image
350    // This lets us handle malformed transport headers by skipping them
351    bool foundStart = false;
352    for (size = 0; size <= sizeof(struct camera2_jpeg_blob); size++) {
353        if ( checkJpegStart(jpegBuffer + size) ) {
354            foundStart = true;
355            start = jpegBuffer + size;
356            maxSize = maxSize - size; // adjust accordingly
357            break;
358        }
359    }
360    if (!foundStart) {
361        ALOGE("Could not find start of JPEG marker");
362        return 0;
363    }
364    if (size != 0) { // Image starts at offset from beginning
365        // We want the jpeg to start at the first byte; so emit warning
366        ALOGW("JPEG Image starts at offset %d", size);
367    }
368
369    // Read JFIF segment markers, skip over segment data
370    size = 0;
371    while (size <= maxSize - MARKER_LENGTH) {
372        segment_t *segment = (segment_t*)(start + size);
373        uint8_t type = checkJpegMarker(segment->marker);
374        if (type == 0) { // invalid marker, no more segments, begin JPEG data
375            ALOGV("JPEG stream found beginning at offset %d", size);
376            break;
377        }
378        if (type == EOI || size > maxSize - sizeof(segment_t)) {
379            ALOGE("Got premature End before JPEG data, offset %d", size);
380            return 0;
381        }
382        size_t length = ntohs(segment->length);
383        ALOGV("JFIF Segment, type %x length %x", type, length);
384        size += length + MARKER_LENGTH;
385    }
386
387    // Find End of Image
388    // Scan JPEG buffer until End of Image (EOI)
389    bool foundEnd = false;
390    for (size; size <= maxSize; size++) {
391        if ( checkJpegEnd(start + size) ) {
392            foundEnd = true;
393            size += MARKER_LENGTH;
394            break;
395        }
396    }
397    if (!foundEnd) {
398        ALOGE("Could not find end of JPEG marker");
399        return 0;
400    }
401
402    if (size > maxSize) {
403        ALOGW("JPEG size %d too large, reducing to maxSize %d", size, maxSize);
404        size = maxSize;
405    }
406    ALOGV("Final JPEG size %d", size);
407    return size;
408}
409
410}; // namespace camera2
411}; // namespace android
412