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
30extern "C" {
31#include "jhead.h"
32}
33
34#define CANCEL_TIMEOUT 3000000 // 3 seconds
35
36namespace android {
37/**
38 * libjpeg encoder class - uses libjpeg to encode yuv
39 */
40
41#define MAX_EXIF_TAGS_SUPPORTED 30
42typedef void (*encoder_libjpeg_callback_t) (void* main_jpeg,
43                                            void* thumb_jpeg,
44                                            CameraFrame::FrameType type,
45                                            void* cookie1,
46                                            void* cookie2,
47                                            void* cookie3,
48                                            bool canceled);
49
50// these have to match strings defined in external/jhead/exif.c
51static const char TAG_MODEL[] = "Model";
52static const char TAG_MAKE[] = "Make";
53static const char TAG_FOCALLENGTH[] = "FocalLength";
54static const char TAG_DATETIME[] = "DateTime";
55static const char TAG_IMAGE_WIDTH[] = "ImageWidth";
56static const char TAG_IMAGE_LENGTH[] = "ImageLength";
57static const char TAG_GPS_LAT[] = "GPSLatitude";
58static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef";
59static const char TAG_GPS_LONG[] = "GPSLongitude";
60static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef";
61static const char TAG_GPS_ALT[] = "GPSAltitude";
62static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef";
63static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum";
64static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod";
65static const char TAG_GPS_VERSION_ID[] = "GPSVersionID";
66static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp";
67static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp";
68static const char TAG_ORIENTATION[] = "Orientation";
69static const char TAG_FLASH[] = "Flash";
70static const char TAG_DIGITALZOOMRATIO[] = "DigitalZoomRatio";
71static const char TAG_EXPOSURETIME[] = "ExposureTime";
72static const char TAG_APERTURE[] = "ApertureValue";
73static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings";
74static const char TAG_WHITEBALANCE[] = "WhiteBalance";
75static const char TAG_LIGHT_SOURCE[] = "LightSource";
76static const char TAG_METERING_MODE[] = "MeteringMode";
77static const char TAG_EXPOSURE_PROGRAM[] = "ExposureProgram";
78static const char TAG_COLOR_SPACE[] = "ColorSpace";
79static const char TAG_CPRS_BITS_PER_PIXEL[] = "CompressedBitsPerPixel";
80static const char TAG_FNUMBER[] = "FNumber";
81static const char TAG_SHUTTERSPEED[] = "ShutterSpeedValue";
82static const char TAG_SENSING_METHOD[] = "SensingMethod";
83static const char TAG_CUSTOM_RENDERED[] = "CustomRendered";
84
85class ExifElementsTable {
86    public:
87        ExifElementsTable() :
88           gps_tag_count(0), exif_tag_count(0), position(0),
89           jpeg_opened(false), has_datetime_tag(false) { }
90        ~ExifElementsTable();
91
92        status_t insertElement(const char* tag, const char* value);
93        void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size);
94        status_t insertExifThumbnailImage(const char*, int);
95        void saveJpeg(unsigned char* picture, size_t jpeg_size);
96        static const char* degreesToExifOrientation(unsigned int);
97        static void stringToRational(const char*, unsigned int*, unsigned int*);
98        static bool isAsciiTag(const char* tag);
99    private:
100        ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED];
101        unsigned int gps_tag_count;
102        unsigned int exif_tag_count;
103        unsigned int position;
104        bool jpeg_opened;
105        bool has_datetime_tag;
106};
107
108class Encoder_libjpeg : public Thread {
109    /* public member types and variables */
110    public:
111        struct params {
112            uint8_t* src;
113            int src_size;
114            uint8_t* dst;
115            int dst_size;
116            int quality;
117            int in_width;
118            int in_height;
119            int out_width;
120            int out_height;
121            int right_crop;
122            int start_offset;
123            const char* format;
124            size_t jpeg_size;
125         };
126    /* public member functions */
127    public:
128        Encoder_libjpeg(params* main_jpeg,
129                        params* tn_jpeg,
130                        encoder_libjpeg_callback_t cb,
131                        CameraFrame::FrameType type,
132                        void* cookie1,
133                        void* cookie2,
134                        void* cookie3)
135            : Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb),
136              mCancelEncoding(false), mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3),
137              mType(type), mThumb(NULL) {
138            this->incStrong(this);
139            mCancelSem.Create(0);
140        }
141
142        ~Encoder_libjpeg() {
143            CAMHAL_LOGVB("~Encoder_libjpeg(%p)", this);
144        }
145
146        virtual bool threadLoop() {
147            size_t size = 0;
148            sp<Encoder_libjpeg> tn = NULL;
149            if (mThumbnailInput) {
150                // start thread to encode thumbnail
151                mThumb = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL);
152                mThumb->run();
153            }
154
155            // encode our main image
156            size = encode(mMainInput);
157
158            // signal cancel semaphore incase somebody is waiting
159            mCancelSem.Signal();
160
161            // check if it is main jpeg thread
162            if(mThumb.get()) {
163                // wait until tn jpeg thread exits.
164                mThumb->join();
165                mThumb.clear();
166                mThumb = NULL;
167            }
168
169            if(mCb) {
170                mCb(mMainInput, mThumbnailInput, mType, mCookie1, mCookie2, mCookie3, mCancelEncoding);
171            }
172
173            // encoder thread runs, self-destructs, and then exits
174            this->decStrong(this);
175            return false;
176        }
177
178        void cancel() {
179           mCancelEncoding = true;
180           if (mThumb.get()) {
181               mThumb->cancel();
182               mCancelSem.WaitTimeout(CANCEL_TIMEOUT);
183           }
184        }
185
186        void getCookies(void **cookie1, void **cookie2, void **cookie3) {
187            if (cookie1) *cookie1 = mCookie1;
188            if (cookie2) *cookie2 = mCookie2;
189            if (cookie3) *cookie3 = mCookie3;
190        }
191
192    private:
193        params* mMainInput;
194        params* mThumbnailInput;
195        encoder_libjpeg_callback_t mCb;
196        bool mCancelEncoding;
197        void* mCookie1;
198        void* mCookie2;
199        void* mCookie3;
200        CameraFrame::FrameType mType;
201        sp<Encoder_libjpeg> mThumb;
202        Semaphore mCancelSem;
203
204        size_t encode(params*);
205};
206
207}
208
209#endif
210