1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @file Encoder_libjpeg.h 19 * 20 * This defines API for camerahal to encode YUV using libjpeg 21 * 22 */ 23 24 #ifndef ANDROID_CAMERA_HARDWARE_ENCODER_LIBJPEG_H 25 #define ANDROID_CAMERA_HARDWARE_ENCODER_LIBJPEG_H 26 27 #include <utils/threads.h> 28 #include <utils/RefBase.h> 29 30 extern "C" { 31 #include "jhead.h" 32 33 #undef TRUE 34 #undef FALSE 35 36 } 37 38 #include "CameraHal.h" 39 40 #define CANCEL_TIMEOUT 5000000 // 5 seconds 41 42 namespace Ti { 43 namespace Camera { 44 45 /** 46 * libjpeg encoder class - uses libjpeg to encode yuv 47 */ 48 49 #define MAX_EXIF_TAGS_SUPPORTED 30 50 typedef void (*encoder_libjpeg_callback_t) (void* main_jpeg, 51 void* thumb_jpeg, 52 CameraFrame::FrameType type, 53 void* cookie1, 54 void* cookie2, 55 void* cookie3, 56 void* cookie4, 57 bool canceled); 58 59 // these have to match strings defined in external/jhead/exif.c 60 static const char TAG_MODEL[] = "Model"; 61 static const char TAG_MAKE[] = "Make"; 62 static const char TAG_FOCALLENGTH[] = "FocalLength"; 63 static const char TAG_DATETIME[] = "DateTime"; 64 static const char TAG_IMAGE_WIDTH[] = "ImageWidth"; 65 static const char TAG_IMAGE_LENGTH[] = "ImageLength"; 66 static const char TAG_GPS_LAT[] = "GPSLatitude"; 67 static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef"; 68 static const char TAG_GPS_LONG[] = "GPSLongitude"; 69 static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef"; 70 static const char TAG_GPS_ALT[] = "GPSAltitude"; 71 static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef"; 72 static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum"; 73 static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod"; 74 static const char TAG_GPS_VERSION_ID[] = "GPSVersionID"; 75 static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp"; 76 static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp"; 77 static const char TAG_ORIENTATION[] = "Orientation"; 78 static const char TAG_FLASH[] = "Flash"; 79 static const char TAG_DIGITALZOOMRATIO[] = "DigitalZoomRatio"; 80 static const char TAG_EXPOSURETIME[] = "ExposureTime"; 81 static const char TAG_APERTURE[] = "ApertureValue"; 82 static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings"; 83 static const char TAG_WHITEBALANCE[] = "WhiteBalance"; 84 static const char TAG_LIGHT_SOURCE[] = "LightSource"; 85 static const char TAG_METERING_MODE[] = "MeteringMode"; 86 static const char TAG_EXPOSURE_PROGRAM[] = "ExposureProgram"; 87 static const char TAG_COLOR_SPACE[] = "ColorSpace"; 88 static const char TAG_CPRS_BITS_PER_PIXEL[] = "CompressedBitsPerPixel"; 89 static const char TAG_FNUMBER[] = "FNumber"; 90 static const char TAG_SHUTTERSPEED[] = "ShutterSpeedValue"; 91 static const char TAG_SENSING_METHOD[] = "SensingMethod"; 92 static const char TAG_CUSTOM_RENDERED[] = "CustomRendered"; 93 94 class ExifElementsTable { 95 public: ExifElementsTable()96 ExifElementsTable() : 97 gps_tag_count(0), exif_tag_count(0), position(0), 98 jpeg_opened(false) 99 { 100 #ifdef ANDROID_API_JB_OR_LATER 101 has_datetime_tag = false; 102 #endif 103 } 104 ~ExifElementsTable(); 105 106 status_t insertElement(const char* tag, const char* value); 107 void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size); 108 status_t insertExifThumbnailImage(const char*, int); 109 void saveJpeg(unsigned char* picture, size_t jpeg_size); 110 static const char* degreesToExifOrientation(unsigned int); 111 static void stringToRational(const char*, unsigned int*, unsigned int*); 112 static bool isAsciiTag(const char* tag); 113 private: 114 ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED]; 115 unsigned int gps_tag_count; 116 unsigned int exif_tag_count; 117 unsigned int position; 118 bool jpeg_opened; 119 #ifdef ANDROID_API_JB_OR_LATER 120 bool has_datetime_tag; 121 #endif 122 }; 123 124 class Encoder_libjpeg : public android::Thread { 125 /* public member types and variables */ 126 public: 127 struct params { 128 uint8_t* src; 129 int src_size; 130 uint8_t* dst; 131 int dst_size; 132 int quality; 133 int in_width; 134 int in_height; 135 int out_width; 136 int out_height; 137 int right_crop; 138 int start_offset; 139 const char* format; 140 size_t jpeg_size; 141 }; 142 /* public member functions */ 143 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)144 Encoder_libjpeg(params* main_jpeg, 145 params* tn_jpeg, 146 encoder_libjpeg_callback_t cb, 147 CameraFrame::FrameType type, 148 void* cookie1, 149 void* cookie2, 150 void* cookie3, void *cookie4) 151 : android::Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb), 152 mCancelEncoding(false), mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3), mCookie4(cookie4), 153 mType(type), mThumb(NULL) { 154 this->incStrong(this); 155 mCancelSem.Create(0); 156 } 157 ~Encoder_libjpeg()158 ~Encoder_libjpeg() { 159 CAMHAL_LOGVB("~Encoder_libjpeg(%p)", this); 160 } 161 threadLoop()162 virtual bool threadLoop() { 163 size_t size = 0; 164 if (mThumbnailInput) { 165 // start thread to encode thumbnail 166 mThumb = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL, NULL); 167 mThumb->run(); 168 } 169 170 // encode our main image 171 size = encode(mMainInput); 172 173 // signal cancel semaphore incase somebody is waiting 174 mCancelSem.Signal(); 175 176 // check if it is main jpeg thread 177 if(mThumb.get()) { 178 // wait until tn jpeg thread exits. 179 mThumb->join(); 180 mThumb.clear(); 181 mThumb = NULL; 182 } 183 184 if(mCb) { 185 mCb(mMainInput, mThumbnailInput, mType, mCookie1, mCookie2, mCookie3, mCookie4, mCancelEncoding); 186 } 187 188 // encoder thread runs, self-destructs, and then exits 189 this->decStrong(this); 190 return false; 191 } 192 cancel()193 void cancel() { 194 mCancelEncoding = true; 195 if (mThumb.get()) { 196 mThumb->cancel(); 197 mCancelSem.WaitTimeout(CANCEL_TIMEOUT); 198 } 199 } 200 getCookies(void ** cookie1,void ** cookie2,void ** cookie3)201 void getCookies(void **cookie1, void **cookie2, void **cookie3) { 202 if (cookie1) *cookie1 = mCookie1; 203 if (cookie2) *cookie2 = mCookie2; 204 if (cookie3) *cookie3 = mCookie3; 205 } 206 207 private: 208 params* mMainInput; 209 params* mThumbnailInput; 210 encoder_libjpeg_callback_t mCb; 211 bool mCancelEncoding; 212 void* mCookie1; 213 void* mCookie2; 214 void* mCookie3; 215 void* mCookie4; 216 CameraFrame::FrameType mType; 217 android::sp<Encoder_libjpeg> mThumb; 218 Utils::Semaphore mCancelSem; 219 220 size_t encode(params*); 221 }; 222 223 } // namespace Camera 224 } // namespace Ti 225 226 #endif 227