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#undef TRUE
34#undef FALSE
35
36}
37
38#include "CameraHal.h"
39
40#define CANCEL_TIMEOUT 5000000 // 5 seconds
41
42namespace Ti {
43namespace Camera {
44
45/**
46 * libjpeg encoder class - uses libjpeg to encode yuv
47 */
48
49#define MAX_EXIF_TAGS_SUPPORTED 30
50typedef 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
60static const char TAG_MODEL[] = "Model";
61static const char TAG_MAKE[] = "Make";
62static const char TAG_FOCALLENGTH[] = "FocalLength";
63static const char TAG_DATETIME[] = "DateTime";
64static const char TAG_IMAGE_WIDTH[] = "ImageWidth";
65static const char TAG_IMAGE_LENGTH[] = "ImageLength";
66static const char TAG_GPS_LAT[] = "GPSLatitude";
67static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef";
68static const char TAG_GPS_LONG[] = "GPSLongitude";
69static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef";
70static const char TAG_GPS_ALT[] = "GPSAltitude";
71static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef";
72static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum";
73static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod";
74static const char TAG_GPS_VERSION_ID[] = "GPSVersionID";
75static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp";
76static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp";
77static const char TAG_ORIENTATION[] = "Orientation";
78static const char TAG_FLASH[] = "Flash";
79static const char TAG_DIGITALZOOMRATIO[] = "DigitalZoomRatio";
80static const char TAG_EXPOSURETIME[] = "ExposureTime";
81static const char TAG_APERTURE[] = "ApertureValue";
82static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings";
83static const char TAG_WHITEBALANCE[] = "WhiteBalance";
84static const char TAG_LIGHT_SOURCE[] = "LightSource";
85static const char TAG_METERING_MODE[] = "MeteringMode";
86static const char TAG_EXPOSURE_PROGRAM[] = "ExposureProgram";
87static const char TAG_COLOR_SPACE[] = "ColorSpace";
88static const char TAG_CPRS_BITS_PER_PIXEL[] = "CompressedBitsPerPixel";
89static const char TAG_FNUMBER[] = "FNumber";
90static const char TAG_SHUTTERSPEED[] = "ShutterSpeedValue";
91static const char TAG_SENSING_METHOD[] = "SensingMethod";
92static const char TAG_CUSTOM_RENDERED[] = "CustomRendered";
93
94class ExifElementsTable {
95    public:
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
124class 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:
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
158        ~Encoder_libjpeg() {
159            CAMHAL_LOGVB("~Encoder_libjpeg(%p)", this);
160        }
161
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
193        void cancel() {
194           mCancelEncoding = true;
195           if (mThumb.get()) {
196               mThumb->cancel();
197               mCancelSem.WaitTimeout(CANCEL_TIMEOUT);
198           }
199        }
200
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