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