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