blob: 9bb6cb720a6a9f846b856e0879fa84f11061bdfb
1 | /* |
2 | * Copyright (C) 2012 The Android Open Source Project |
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 | /** |
19 | * This class simulates a hardware JPEG compressor. It receives image buffers |
20 | * in RGBA_8888 format, processes them in a worker thread, and then pushes them |
21 | * out to their destination stream. |
22 | */ |
23 | |
24 | #ifndef HW_EMULATOR_CAMERA2_JPEG_H |
25 | #define HW_EMULATOR_CAMERA2_JPEG_H |
26 | |
27 | #include "utils/Thread.h" |
28 | #include "utils/Mutex.h" |
29 | #include "utils/Timers.h" |
30 | |
31 | #include "Base.h" |
32 | |
33 | #include <stdio.h> |
34 | |
35 | extern "C" { |
36 | #include <jpeglib.h> |
37 | #include <jhead.h> |
38 | } |
39 | |
40 | namespace android { |
41 | #define MAX_EXIF_TAGS_SUPPORTED 30 |
42 | static const char TAG_MODEL[] = "Model"; |
43 | static const char TAG_MAKE[] = "Make"; |
44 | static const char TAG_FOCALLENGTH[] = "FocalLength"; |
45 | static const char TAG_DATETIME[] = "DateTime"; |
46 | static const char TAG_IMAGE_WIDTH[] = "ImageWidth"; |
47 | static const char TAG_IMAGE_LENGTH[] = "ImageLength"; |
48 | static const char TAG_GPS_LAT[] = "GPSLatitude"; |
49 | static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef"; |
50 | static const char TAG_GPS_LONG[] = "GPSLongitude"; |
51 | static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef"; |
52 | static const char TAG_GPS_ALT[] = "GPSAltitude"; |
53 | static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef"; |
54 | static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum"; |
55 | static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod"; |
56 | static const char TAG_GPS_VERSION_ID[] = "GPSVersionID"; |
57 | static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp"; |
58 | static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp"; |
59 | static const char TAG_ORIENTATION[] = "Orientation"; |
60 | |
61 | static const char TAG_EXPOSURETIME[] = "ExposureTime"; |
62 | static const char TAG_APERTURE[] = "ApertureValue"; |
63 | static const char TAG_FLASH[] = "Flash"; |
64 | static const char TAG_WHITEBALANCE[] = "WhiteBalance"; |
65 | static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings"; |
66 | static const char TAG_DATETIME_DIGITIZED[] = "DateTimeDigitized"; |
67 | static const char TAG_SUBSEC_TIME[] = "SubSecTime"; |
68 | static const char TAG_SUBSEC_TIME_ORIG[] = "SubSecTimeOriginal"; |
69 | static const char TAG_SUBSEC_TIME_DIG[] = "SubSecTimeDigitized"; |
70 | |
71 | |
72 | class ExifElementsTable { |
73 | public: |
74 | ExifElementsTable() : |
75 | gps_tag_count(0), exif_tag_count(0), position(0), |
76 | jpeg_opened(false) { } |
77 | ~ExifElementsTable(); |
78 | status_t insertElement(const char* tag, const char* value); |
79 | void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size); |
80 | status_t insertExifThumbnailImage(const char*, int); |
81 | void saveJpeg(unsigned char* picture, size_t jpeg_size); |
82 | static const char* degreesToExifOrientation(const char*); |
83 | static void stringToRational(const char*, unsigned int*, unsigned int*); |
84 | static bool isAsciiTag(const char* tag); |
85 | private: |
86 | ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED]; |
87 | unsigned int gps_tag_count; |
88 | unsigned int exif_tag_count; |
89 | unsigned int position; |
90 | bool jpeg_opened; |
91 | }; |
92 | |
93 | class JpegCompressor: private Thread, public virtual RefBase { |
94 | public: |
95 | |
96 | JpegCompressor(); |
97 | ~JpegCompressor(); |
98 | |
99 | struct JpegListener { |
100 | // Called when JPEG compression has finished, or encountered an error |
101 | virtual void onJpegDone(const StreamBuffer &jpegBuffer, |
102 | bool success) = 0; |
103 | // Called when the input buffer for JPEG is not needed any more, |
104 | // if the buffer came from the framework. |
105 | virtual void onJpegInputDone(const StreamBuffer &inputBuffer) = 0; |
106 | virtual ~JpegListener(); |
107 | }; |
108 | |
109 | // Start compressing COMPRESSED format buffers; JpegCompressor takes |
110 | // ownership of the Buffers vector. |
111 | status_t start(Buffers *buffers, JpegListener *listener); |
112 | |
113 | // Compress and block until buffer is complete. |
114 | status_t compressSynchronous(Buffers *buffers); |
115 | |
116 | status_t cancel(); |
117 | |
118 | bool isBusy(); |
119 | bool isStreamInUse(uint32_t id); |
120 | |
121 | bool waitForDone(nsecs_t timeout); |
122 | ssize_t GetMaxJpegBufferSize(); |
123 | void SetMaxJpegBufferSize(ssize_t size); |
124 | void SetExifInfo(struct ExifInfo info); |
125 | int GenExif(ExifElementsTable* exiftable); |
126 | |
127 | // TODO: Measure this |
128 | static const size_t kMaxJpegSize = 300000; |
129 | ssize_t mMaxbufsize; |
130 | |
131 | private: |
132 | Mutex mBusyMutex; |
133 | bool mIsBusy; |
134 | Condition mDone; |
135 | bool mSynchronous; |
136 | |
137 | Mutex mMutex; |
138 | |
139 | bool mNeedexif; |
140 | bool mNeedThumbnail; |
141 | int mMainJpegSize, mThumbJpegSize; |
142 | uint8_t *mSrcThumbBuffer; |
143 | uint8_t *mDstThumbBuffer; |
144 | Buffers *mBuffers; |
145 | JpegListener *mListener; |
146 | struct ExifInfo mInfo; |
147 | StreamBuffer mJpegBuffer, mAuxBuffer; |
148 | bool mFoundJpeg, mFoundAux; |
149 | |
150 | jpeg_compress_struct mCInfo; |
151 | |
152 | struct JpegError : public jpeg_error_mgr { |
153 | JpegCompressor *parent; |
154 | }; |
155 | j_common_ptr mJpegErrorInfo; |
156 | |
157 | struct JpegDestination : public jpeg_destination_mgr { |
158 | JpegCompressor *parent; |
159 | }; |
160 | |
161 | static void MainJpegErrorHandler(j_common_ptr cinfo); |
162 | static void MainJpegInitDestination(j_compress_ptr cinfo); |
163 | static boolean MainJpegEmptyOutputBuffer(j_compress_ptr cinfo); |
164 | static void MainJpegTermDestination(j_compress_ptr cinfo); |
165 | |
166 | static void ThumbJpegErrorHandler(j_common_ptr cinfo); |
167 | static void ThumbJpegInitDestination(j_compress_ptr cinfo); |
168 | static boolean ThumbJpegEmptyOutputBuffer(j_compress_ptr cinfo); |
169 | static void ThumbJpegTermDestination(j_compress_ptr cinfo); |
170 | |
171 | bool checkError(const char *msg); |
172 | status_t compress(); |
173 | |
174 | status_t thumbcompress(); |
175 | void cleanUp(); |
176 | |
177 | /** |
178 | * Inherited Thread virtual overrides |
179 | */ |
180 | private: |
181 | virtual status_t readyToRun(); |
182 | virtual bool threadLoop(); |
183 | }; |
184 | |
185 | } // namespace android |
186 | |
187 | #endif |
188 |