1c3dbf1a40df85b75e5805382838a90416f69730fJames Painter/* 2c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * Copyright (C) 2012 The Android Open Source Project 3c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * 4c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * Licensed under the Apache License, Version 2.0 (the "License"); 5c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * you may not use this file except in compliance with the License. 6c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * You may obtain a copy of the License at 7c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * 8c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * http://www.apache.org/licenses/LICENSE-2.0 9c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * 10c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * Unless required by applicable law or agreed to in writing, software 11c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * distributed under the License is distributed on an "AS IS" BASIS, 12c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * See the License for the specific language governing permissions and 14c3dbf1a40df85b75e5805382838a90416f69730fJames Painter * limitations under the License. 15c3dbf1a40df85b75e5805382838a90416f69730fJames Painter */ 16c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 17852c381dbd1a9f86e6759201b50ac8847a1c3e3cEino-Ville Talvala//#define LOG_NDEBUG 0 18852c381dbd1a9f86e6759201b50ac8847a1c3e3cEino-Ville Talvala#define LOG_TAG "Camera2-JpegCompressor" 19c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 20c3dbf1a40df85b75e5805382838a90416f69730fJames Painter#include <utils/Log.h> 21c3dbf1a40df85b75e5805382838a90416f69730fJames Painter#include <ui/GraphicBufferMapper.h> 22c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 23c3dbf1a40df85b75e5805382838a90416f69730fJames Painter#include "JpegCompressor.h" 24c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 25c3dbf1a40df85b75e5805382838a90416f69730fJames Painternamespace android { 26c3dbf1a40df85b75e5805382838a90416f69730fJames Painternamespace camera2 { 27c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 28c3dbf1a40df85b75e5805382838a90416f69730fJames PainterJpegCompressor::JpegCompressor(): 29c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Thread(false), 30c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mIsBusy(false), 31c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCaptureTime(0) { 32c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 33c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 34c3dbf1a40df85b75e5805382838a90416f69730fJames PainterJpegCompressor::~JpegCompressor() { 35c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 36c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Mutex::Autolock lock(mMutex); 37c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 38c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 39c3dbf1a40df85b75e5805382838a90416f69730fJames Painterstatus_t JpegCompressor::start(Vector<CpuConsumer::LockedBuffer*> buffers, 40c3dbf1a40df85b75e5805382838a90416f69730fJames Painter nsecs_t captureTime) { 41c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 42c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Mutex::Autolock busyLock(mBusyMutex); 43c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 44c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (mIsBusy) { 45c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGE("%s: Already processing a buffer!", __FUNCTION__); 46c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return INVALID_OPERATION; 47c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 48c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 49c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mIsBusy = true; 50c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 51c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mBuffers = buffers; 52c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCaptureTime = captureTime; 53c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 54c3dbf1a40df85b75e5805382838a90416f69730fJames Painter status_t res; 55c3dbf1a40df85b75e5805382838a90416f69730fJames Painter res = run("JpegCompressor"); 56c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (res != OK) { 57c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGE("%s: Unable to start up compression thread: %s (%d)", 58c3dbf1a40df85b75e5805382838a90416f69730fJames Painter __FUNCTION__, strerror(-res), res); 59c3dbf1a40df85b75e5805382838a90416f69730fJames Painter //delete mBuffers; // necessary? 60c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 61c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return res; 62c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 63c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 64c3dbf1a40df85b75e5805382838a90416f69730fJames Painterstatus_t JpegCompressor::cancel() { 65c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 66c3dbf1a40df85b75e5805382838a90416f69730fJames Painter requestExitAndWait(); 67c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return OK; 68c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 69c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 70c3dbf1a40df85b75e5805382838a90416f69730fJames Painterstatus_t JpegCompressor::readyToRun() { 71c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 72c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return OK; 73c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 74c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 75c3dbf1a40df85b75e5805382838a90416f69730fJames Painterbool JpegCompressor::threadLoop() { 76c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 77c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 78c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mAuxBuffer = mBuffers[0]; // input 79c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mJpegBuffer = mBuffers[1]; // output 80c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 81c3dbf1a40df85b75e5805382838a90416f69730fJames Painter // Set up error management 82c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mJpegErrorInfo = NULL; 83c3dbf1a40df85b75e5805382838a90416f69730fJames Painter JpegError error; 84c3dbf1a40df85b75e5805382838a90416f69730fJames Painter error.parent = this; 85c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 86c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.err = jpeg_std_error(&error); 87c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.err->error_exit = jpegErrorHandler; 88c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 89c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpeg_create_compress(&mCInfo); 90c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (checkError("Error initializing compression")) return false; 91c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 92c3dbf1a40df85b75e5805382838a90416f69730fJames Painter // Route compressed data straight to output stream buffer 93c3dbf1a40df85b75e5805382838a90416f69730fJames Painter JpegDestination jpegDestMgr; 94c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpegDestMgr.parent = this; 95c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpegDestMgr.init_destination = jpegInitDestination; 96c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpegDestMgr.empty_output_buffer = jpegEmptyOutputBuffer; 97c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpegDestMgr.term_destination = jpegTermDestination; 98c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 99c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.dest = &jpegDestMgr; 100c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 101c3dbf1a40df85b75e5805382838a90416f69730fJames Painter // Set up compression parameters 102c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.image_width = mAuxBuffer->width; 103c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.image_height = mAuxBuffer->height; 104c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.input_components = 1; // 3; 105c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mCInfo.in_color_space = JCS_GRAYSCALE; // JCS_RGB 106c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 107c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s: image_width = %d, image_height = %d", __FUNCTION__, mCInfo.image_width, mCInfo.image_height); 108c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 109c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpeg_set_defaults(&mCInfo); 110c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (checkError("Error configuring defaults")) return false; 111c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 112c3dbf1a40df85b75e5805382838a90416f69730fJames Painter // Do compression 113c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpeg_start_compress(&mCInfo, TRUE); 114c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (checkError("Error starting compression")) return false; 115c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 116c3dbf1a40df85b75e5805382838a90416f69730fJames Painter size_t rowStride = mAuxBuffer->stride;// * 3; 117c3dbf1a40df85b75e5805382838a90416f69730fJames Painter const size_t kChunkSize = 32; 118c3dbf1a40df85b75e5805382838a90416f69730fJames Painter while (mCInfo.next_scanline < mCInfo.image_height) { 119c3dbf1a40df85b75e5805382838a90416f69730fJames Painter JSAMPROW chunk[kChunkSize]; 120c3dbf1a40df85b75e5805382838a90416f69730fJames Painter for (size_t i = 0 ; i < kChunkSize; i++) { 121c3dbf1a40df85b75e5805382838a90416f69730fJames Painter chunk[i] = (JSAMPROW) 122c3dbf1a40df85b75e5805382838a90416f69730fJames Painter (mAuxBuffer->data + (i + mCInfo.next_scanline) * rowStride); 123c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 124c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpeg_write_scanlines(&mCInfo, chunk, kChunkSize); 125c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (checkError("Error while compressing")) return false; 126c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (exitPending()) { 127c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s: Cancel called, exiting early", __FUNCTION__); 128c3dbf1a40df85b75e5805382838a90416f69730fJames Painter cleanUp(); 129c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return false; 130c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 131c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 132c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 133c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpeg_finish_compress(&mCInfo); 134c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (checkError("Error while finishing compression")) return false; 135c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 136c3dbf1a40df85b75e5805382838a90416f69730fJames Painter cleanUp(); 137c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return false; 138c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 139c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 140c3dbf1a40df85b75e5805382838a90416f69730fJames Painterbool JpegCompressor::isBusy() { 141c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 142c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Mutex::Autolock busyLock(mBusyMutex); 143c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return mIsBusy; 144c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 145c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 146c3dbf1a40df85b75e5805382838a90416f69730fJames Painter// old function -- TODO: update for new buffer type 147ebe3f69ef09777001b14a1cb9a2a21090655a14bIgor Murashkinbool JpegCompressor::isStreamInUse(uint32_t /*id*/) { 148c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 149c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Mutex::Autolock lock(mBusyMutex); 150c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 151c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (mBuffers.size() && mIsBusy) { 152c3dbf1a40df85b75e5805382838a90416f69730fJames Painter for (size_t i = 0; i < mBuffers.size(); i++) { 153c3dbf1a40df85b75e5805382838a90416f69730fJames Painter// if ( mBuffers[i].streamId == (int)id ) return true; 154c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 155c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 156c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return false; 157c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 158c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 159c3dbf1a40df85b75e5805382838a90416f69730fJames Painterbool JpegCompressor::waitForDone(nsecs_t timeout) { 160c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 161c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Mutex::Autolock lock(mBusyMutex); 162c3dbf1a40df85b75e5805382838a90416f69730fJames Painter status_t res = OK; 163c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (mIsBusy) { 164c3dbf1a40df85b75e5805382838a90416f69730fJames Painter res = mDone.waitRelative(mBusyMutex, timeout); 165c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 166c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return (res == OK); 167c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 168c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 169c3dbf1a40df85b75e5805382838a90416f69730fJames Painterbool JpegCompressor::checkError(const char *msg) { 170c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 171c3dbf1a40df85b75e5805382838a90416f69730fJames Painter if (mJpegErrorInfo) { 172c3dbf1a40df85b75e5805382838a90416f69730fJames Painter char errBuffer[JMSG_LENGTH_MAX]; 173c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mJpegErrorInfo->err->format_message(mJpegErrorInfo, errBuffer); 174c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGE("%s: %s: %s", 175c3dbf1a40df85b75e5805382838a90416f69730fJames Painter __FUNCTION__, msg, errBuffer); 176c3dbf1a40df85b75e5805382838a90416f69730fJames Painter cleanUp(); 177c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mJpegErrorInfo = NULL; 178c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return true; 179c3dbf1a40df85b75e5805382838a90416f69730fJames Painter } 180c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return false; 181c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 182c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 183c3dbf1a40df85b75e5805382838a90416f69730fJames Paintervoid JpegCompressor::cleanUp() { 184c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 185c3dbf1a40df85b75e5805382838a90416f69730fJames Painter jpeg_destroy_compress(&mCInfo); 186c3dbf1a40df85b75e5805382838a90416f69730fJames Painter Mutex::Autolock lock(mBusyMutex); 187c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mIsBusy = false; 188c3dbf1a40df85b75e5805382838a90416f69730fJames Painter mDone.signal(); 189c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 190c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 191c3dbf1a40df85b75e5805382838a90416f69730fJames Paintervoid JpegCompressor::jpegErrorHandler(j_common_ptr cinfo) { 192c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 193c3dbf1a40df85b75e5805382838a90416f69730fJames Painter JpegError *error = static_cast<JpegError*>(cinfo->err); 194c3dbf1a40df85b75e5805382838a90416f69730fJames Painter error->parent->mJpegErrorInfo = cinfo; 195c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 196c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 197c3dbf1a40df85b75e5805382838a90416f69730fJames Paintervoid JpegCompressor::jpegInitDestination(j_compress_ptr cinfo) { 198c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 199c3dbf1a40df85b75e5805382838a90416f69730fJames Painter JpegDestination *dest= static_cast<JpegDestination*>(cinfo->dest); 200c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s: Setting destination to %p, size %d", 201c3dbf1a40df85b75e5805382838a90416f69730fJames Painter __FUNCTION__, dest->parent->mJpegBuffer->data, kMaxJpegSize); 202c3dbf1a40df85b75e5805382838a90416f69730fJames Painter dest->next_output_byte = (JOCTET*)(dest->parent->mJpegBuffer->data); 203c3dbf1a40df85b75e5805382838a90416f69730fJames Painter dest->free_in_buffer = kMaxJpegSize; 204c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 205c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 206ebe3f69ef09777001b14a1cb9a2a21090655a14bIgor Murashkinboolean JpegCompressor::jpegEmptyOutputBuffer(j_compress_ptr /*cinfo*/) { 207c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 208c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGE("%s: JPEG destination buffer overflow!", 209c3dbf1a40df85b75e5805382838a90416f69730fJames Painter __FUNCTION__); 210c3dbf1a40df85b75e5805382838a90416f69730fJames Painter return true; 211c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 212c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 213ebe3f69ef09777001b14a1cb9a2a21090655a14bIgor Murashkinvoid JpegCompressor::jpegTermDestination(j_compress_ptr /*cinfo*/) { 214c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s", __FUNCTION__); 215c3dbf1a40df85b75e5805382838a90416f69730fJames Painter ALOGV("%s: Done writing JPEG data. %d bytes left in buffer", 216c3dbf1a40df85b75e5805382838a90416f69730fJames Painter __FUNCTION__, cinfo->dest->free_in_buffer); 217c3dbf1a40df85b75e5805382838a90416f69730fJames Painter} 218c3dbf1a40df85b75e5805382838a90416f69730fJames Painter 219c3dbf1a40df85b75e5805382838a90416f69730fJames Painter}; // namespace camera2 220c3dbf1a40df85b75e5805382838a90416f69730fJames Painter}; // namespace android 221