JpegProcessor.cpp revision a6b4c40e70eafc5aba16163999de6d3e26667b89
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 "Camera2Client::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 ¶ms) { 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 ¤tWidth, ¤tHeight, 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