| /* |
| * 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" |
| } |
| |
| #define CANCEL_TIMEOUT 3000000 // 3 seconds |
| |
| namespace android { |
| /** |
| * 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, |
| 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_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), has_datetime_tag(false) { } |
| ~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; |
| bool has_datetime_tag; |
| }; |
| |
| class Encoder_libjpeg : public 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) |
| : Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb), |
| mCancelEncoding(false), mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3), |
| 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; |
| sp<Encoder_libjpeg> tn = NULL; |
| if (mThumbnailInput) { |
| // start thread to encode thumbnail |
| mThumb = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL); |
| mThumb->run(); |
| } |
| |
| // 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, 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; |
| CameraFrame::FrameType mType; |
| sp<Encoder_libjpeg> mThumb; |
| Semaphore mCancelSem; |
| |
| size_t encode(params*); |
| }; |
| |
| } |
| |
| #endif |