232 lines
7.7 KiB
C++
232 lines
7.7 KiB
C++
/*
|
|
* Copyright (C) Texas Instruments - http://www.ti.com/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @file Encoder_libjpeg.h
|
|
*
|
|
* This defines API for camerahal to encode YUV using libjpeg
|
|
*
|
|
*/
|
|
|
|
#ifndef ANDROID_CAMERA_HARDWARE_ENCODER_LIBJPEG_H
|
|
#define ANDROID_CAMERA_HARDWARE_ENCODER_LIBJPEG_H
|
|
|
|
#include <utils/threads.h>
|
|
#include <utils/RefBase.h>
|
|
|
|
extern "C" {
|
|
#include "jhead.h"
|
|
|
|
#undef TRUE
|
|
#undef FALSE
|
|
|
|
}
|
|
|
|
#include "CameraHal.h"
|
|
|
|
#define CANCEL_TIMEOUT 5000000 // 5 seconds
|
|
|
|
namespace Ti {
|
|
namespace Camera {
|
|
|
|
/**
|
|
* libjpeg encoder class - uses libjpeg to encode yuv
|
|
*/
|
|
|
|
#define MAX_EXIF_TAGS_SUPPORTED 30
|
|
typedef void (*encoder_libjpeg_callback_t) (void* main_jpeg,
|
|
void* thumb_jpeg,
|
|
CameraFrame::FrameType type,
|
|
void* cookie1,
|
|
void* cookie2,
|
|
void* cookie3,
|
|
void* cookie4,
|
|
bool canceled);
|
|
|
|
// these have to match strings defined in external/jhead/exif.c
|
|
static const char TAG_MODEL[] = "Model";
|
|
static const char TAG_MAKE[] = "Make";
|
|
static const char TAG_FOCALLENGTH[] = "FocalLength";
|
|
static const char TAG_DATETIME[] = "DateTime";
|
|
static const char TAG_IMAGE_WIDTH[] = "ImageWidth";
|
|
static const char TAG_IMAGE_LENGTH[] = "ImageLength";
|
|
static const char TAG_EXIF_IMAGE_WIDTH[] = "ExifImageWidth";
|
|
static const char TAG_EXIF_IMAGE_LENGTH[] = "ExifImageLength";
|
|
static const char TAG_GPS_LAT[] = "GPSLatitude";
|
|
static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef";
|
|
static const char TAG_GPS_LONG[] = "GPSLongitude";
|
|
static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef";
|
|
static const char TAG_GPS_ALT[] = "GPSAltitude";
|
|
static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef";
|
|
static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum";
|
|
static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod";
|
|
static const char TAG_GPS_VERSION_ID[] = "GPSVersionID";
|
|
static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp";
|
|
static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp";
|
|
static const char TAG_ORIENTATION[] = "Orientation";
|
|
static const char TAG_FLASH[] = "Flash";
|
|
static const char TAG_DIGITALZOOMRATIO[] = "DigitalZoomRatio";
|
|
static const char TAG_EXPOSURETIME[] = "ExposureTime";
|
|
static const char TAG_APERTURE[] = "ApertureValue";
|
|
static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings";
|
|
static const char TAG_WHITEBALANCE[] = "WhiteBalance";
|
|
static const char TAG_LIGHT_SOURCE[] = "LightSource";
|
|
static const char TAG_METERING_MODE[] = "MeteringMode";
|
|
static const char TAG_EXPOSURE_PROGRAM[] = "ExposureProgram";
|
|
static const char TAG_COLOR_SPACE[] = "ColorSpace";
|
|
static const char TAG_CPRS_BITS_PER_PIXEL[] = "CompressedBitsPerPixel";
|
|
static const char TAG_FNUMBER[] = "FNumber";
|
|
static const char TAG_SHUTTERSPEED[] = "ShutterSpeedValue";
|
|
static const char TAG_SENSING_METHOD[] = "SensingMethod";
|
|
static const char TAG_CUSTOM_RENDERED[] = "CustomRendered";
|
|
|
|
class ExifElementsTable {
|
|
public:
|
|
ExifElementsTable() :
|
|
gps_tag_count(0), exif_tag_count(0), position(0),
|
|
jpeg_opened(false)
|
|
{
|
|
#ifdef ANDROID_API_JB_OR_LATER
|
|
has_datetime_tag = false;
|
|
#endif
|
|
}
|
|
~ExifElementsTable();
|
|
|
|
status_t insertElement(const char* tag, const char* value);
|
|
void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size);
|
|
status_t insertExifThumbnailImage(const char*, int);
|
|
void saveJpeg(unsigned char* picture, size_t jpeg_size);
|
|
static const char* degreesToExifOrientation(unsigned int);
|
|
static void stringToRational(const char*, unsigned int*, unsigned int*);
|
|
static bool isAsciiTag(const char* tag);
|
|
private:
|
|
ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED];
|
|
unsigned int gps_tag_count;
|
|
unsigned int exif_tag_count;
|
|
unsigned int position;
|
|
bool jpeg_opened;
|
|
#ifdef ANDROID_API_JB_OR_LATER
|
|
bool has_datetime_tag;
|
|
#endif
|
|
};
|
|
|
|
class Encoder_libjpeg : public android::Thread {
|
|
/* public member types and variables */
|
|
public:
|
|
struct params {
|
|
uint8_t* src;
|
|
int src_size;
|
|
uint8_t* dst;
|
|
int dst_size;
|
|
int quality;
|
|
int in_width;
|
|
int in_height;
|
|
int out_width;
|
|
int out_height;
|
|
int right_crop;
|
|
int start_offset;
|
|
const char* format;
|
|
size_t jpeg_size;
|
|
};
|
|
/* public member functions */
|
|
public:
|
|
Encoder_libjpeg(params* main_jpeg,
|
|
params* tn_jpeg,
|
|
encoder_libjpeg_callback_t cb,
|
|
CameraFrame::FrameType type,
|
|
void* cookie1,
|
|
void* cookie2,
|
|
void* cookie3, void *cookie4)
|
|
: android::Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb),
|
|
mCancelEncoding(false), mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3), mCookie4(cookie4),
|
|
mType(type), mThumb(NULL) {
|
|
this->incStrong(this);
|
|
mCancelSem.Create(0);
|
|
}
|
|
|
|
~Encoder_libjpeg() {
|
|
CAMHAL_LOGVB("~Encoder_libjpeg(%p)", this);
|
|
}
|
|
|
|
virtual bool threadLoop() {
|
|
size_t size = 0;
|
|
if (mThumbnailInput) {
|
|
// start thread to encode thumbnail
|
|
mThumb = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL, NULL);
|
|
#ifdef ANDROID_API_N_OR_LATER
|
|
mThumb->run("Encoder_libjpeg-Thumb");
|
|
#else
|
|
mThumb->run();
|
|
#endif
|
|
}
|
|
|
|
// encode our main image
|
|
size = encode(mMainInput);
|
|
|
|
// signal cancel semaphore incase somebody is waiting
|
|
mCancelSem.Signal();
|
|
|
|
// check if it is main jpeg thread
|
|
if(mThumb.get()) {
|
|
// wait until tn jpeg thread exits.
|
|
mThumb->join();
|
|
mThumb.clear();
|
|
mThumb = NULL;
|
|
}
|
|
|
|
if(mCb) {
|
|
mCb(mMainInput, mThumbnailInput, mType, mCookie1, mCookie2, mCookie3, mCookie4, mCancelEncoding);
|
|
}
|
|
|
|
// encoder thread runs, self-destructs, and then exits
|
|
this->decStrong(this);
|
|
return false;
|
|
}
|
|
|
|
void cancel() {
|
|
mCancelEncoding = true;
|
|
if (mThumb.get()) {
|
|
mThumb->cancel();
|
|
mCancelSem.WaitTimeout(CANCEL_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
void getCookies(void **cookie1, void **cookie2, void **cookie3) {
|
|
if (cookie1) *cookie1 = mCookie1;
|
|
if (cookie2) *cookie2 = mCookie2;
|
|
if (cookie3) *cookie3 = mCookie3;
|
|
}
|
|
|
|
private:
|
|
params* mMainInput;
|
|
params* mThumbnailInput;
|
|
encoder_libjpeg_callback_t mCb;
|
|
bool mCancelEncoding;
|
|
void* mCookie1;
|
|
void* mCookie2;
|
|
void* mCookie3;
|
|
void* mCookie4;
|
|
CameraFrame::FrameType mType;
|
|
android::sp<Encoder_libjpeg> mThumb;
|
|
Utils::Semaphore mCancelSem;
|
|
|
|
size_t encode(params*);
|
|
};
|
|
|
|
} // namespace Camera
|
|
} // namespace Ti
|
|
|
|
#endif
|