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