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