blob: 464af4da0791fcab1326774cfe54b8fe46ae60f3
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 | #include "Base.h" |
31 | #include <hardware/camera3.h> |
32 | #include <utils/List.h> |
33 | #include <stdio.h> |
34 | |
35 | #include <libexif/exif-entry.h> |
36 | #include <libexif/exif-data.h> |
37 | #include <libexif/exif-ifd.h> |
38 | #include <libexif/exif-loader.h> |
39 | #include <libexif/exif-mem.h> |
40 | |
41 | extern "C" { |
42 | #include <jpeglib.h> |
43 | #include <jhead.h> |
44 | } |
45 | |
46 | namespace android { |
47 | #define MAX_EXIF_TAGS_SUPPORTED 30 |
48 | static const char TAG_MODEL[] = "Model"; |
49 | static const char TAG_MAKE[] = "Make"; |
50 | static const char TAG_FOCALLENGTH[] = "FocalLength"; |
51 | static const char TAG_DATETIME[] = "DateTime"; |
52 | static const char TAG_IMAGE_WIDTH[] = "ImageWidth"; |
53 | static const char TAG_IMAGE_LENGTH[] = "ImageLength"; |
54 | static const char TAG_GPS_LAT[] = "GPSLatitude"; |
55 | static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef"; |
56 | static const char TAG_GPS_LONG[] = "GPSLongitude"; |
57 | static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef"; |
58 | static const char TAG_GPS_ALT[] = "GPSAltitude"; |
59 | static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef"; |
60 | static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum"; |
61 | static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod"; |
62 | static const char TAG_GPS_VERSION_ID[] = "GPSVersionID"; |
63 | static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp"; |
64 | static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp"; |
65 | static const char TAG_ORIENTATION[] = "Orientation"; |
66 | |
67 | static const char TAG_EXPOSURETIME[] = "ExposureTime"; |
68 | static const char TAG_APERTURE[] = "ApertureValue"; |
69 | static const char TAG_FLASH[] = "Flash"; |
70 | static const char TAG_WHITEBALANCE[] = "WhiteBalance"; |
71 | static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings"; |
72 | static const char TAG_DATETIME_DIGITIZED[] = "DateTimeDigitized"; |
73 | static const char TAG_SUBSEC_TIME[] = "SubSecTime"; |
74 | static const char TAG_SUBSEC_TIME_ORIG[] = "SubSecTimeOriginal"; |
75 | static const char TAG_SUBSEC_TIME_DIG[] = "SubSecTimeDigitized"; |
76 | |
77 | struct CaptureRequest { |
78 | uint32_t frameNumber; |
79 | camera3_stream_buffer *buf; |
80 | Buffers *sensorBuffers; |
81 | bool mNeedThumbnail; |
82 | }; |
83 | |
84 | typedef struct _exif_buffer { |
85 | unsigned char *data; |
86 | unsigned int size; |
87 | } exif_buffer; |
88 | |
89 | class ExifElementsTable { |
90 | public: |
91 | ExifElementsTable() : |
92 | gps_tag_count(0), exif_tag_count(0), position(0), |
93 | jpeg_opened(false) { } |
94 | ~ExifElementsTable(); |
95 | status_t insertElement(const char* tag, const char* value); |
96 | void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size); |
97 | status_t insertExifThumbnailImage(const char*, int); |
98 | void saveJpeg(unsigned char* picture, size_t jpeg_size); |
99 | static const char* degreesToExifOrientation(const char*); |
100 | static void stringToRational(const char*, unsigned int*, unsigned int*); |
101 | static bool isAsciiTag(const char* tag); |
102 | private: |
103 | ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED]; |
104 | unsigned int gps_tag_count; |
105 | unsigned int exif_tag_count; |
106 | unsigned int position; |
107 | bool jpeg_opened; |
108 | }; |
109 | |
110 | class JpegCompressor: private Thread, public virtual RefBase { |
111 | public: |
112 | |
113 | JpegCompressor(); |
114 | ~JpegCompressor(); |
115 | |
116 | struct JpegListener { |
117 | // Called when JPEG compression has finished, or encountered an error |
118 | virtual void onJpegDone(const StreamBuffer &jpegBuffer, |
119 | bool success, CaptureRequest &r) = 0; |
120 | // Called when the input buffer for JPEG is not needed any more, |
121 | // if the buffer came from the framework. |
122 | virtual void onJpegInputDone(const StreamBuffer &inputBuffer) = 0; |
123 | virtual ~JpegListener(); |
124 | }; |
125 | |
126 | // Start compressing COMPRESSED format buffers; JpegCompressor takes |
127 | // ownership of the Buffers vector. |
128 | status_t start(); |
129 | status_t setlistener(JpegListener *listener); |
130 | void queueRequest(CaptureRequest &r); |
131 | |
132 | // Compress and block until buffer is complete. |
133 | status_t compressSynchronous(Buffers *buffers); |
134 | |
135 | status_t cancel(); |
136 | |
137 | bool isBusy(); |
138 | bool isStreamInUse(uint32_t id); |
139 | |
140 | bool waitForDone(nsecs_t timeout); |
141 | ssize_t GetMaxJpegBufferSize(); |
142 | void SetMaxJpegBufferSize(ssize_t size); |
143 | void SetExifInfo(struct ExifInfo info); |
144 | int GenExif(ExifElementsTable* exiftable); |
145 | status_t Create_Exif_Use_Libjpeg(); |
146 | status_t Create_Exif_Use_Libexif(); |
147 | exif_buffer *get_exif_buffer(); |
148 | void exif_entry_set_string (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, const char *s); |
149 | void exif_entry_set_short (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, ExifShort n); |
150 | void exif_entry_set_long (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, ExifLong n); |
151 | void exif_entry_set_rational (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, ExifRational r); |
152 | void exif_entry_set_undefined (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, exif_buffer * buf); |
153 | ExifEntry *init_tag(ExifData *exif, ExifIfd ifd, ExifTag tag); |
154 | ExifEntry *create_tag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len); |
155 | void exif_entry_set_gps_coord(ExifData * pEdata, ExifTag eEtag, |
156 | ExifRational r1, ExifRational r2, ExifRational r3); |
157 | void exif_entry_set_gps_altitude(ExifData * pEdata, ExifTag eEtag, ExifRational r1); |
158 | void exif_entry_set_gps_coord_ref(ExifData * pEdata, ExifTag eEtag, const char *s); |
159 | void exif_entry_set_gps_altitude_ref(ExifData * pEdata, ExifTag eEtag, ExifByte n); |
160 | |
161 | // TODO: Measure this |
162 | static const size_t kMaxJpegSize = 8000000; |
163 | ssize_t mMaxbufsize; |
164 | |
165 | private: |
166 | Mutex mBusyMutex; |
167 | bool mIsBusy; |
168 | Condition mDone; |
169 | bool mSynchronous; |
170 | |
171 | Mutex mMutex; |
172 | |
173 | List<CaptureRequest*> mInJpegRequestQueue; |
174 | Condition mInJpegRequestSignal; |
175 | camera3_stream_buffer *tempHalbuffers; |
176 | Buffers *tempBuffers; |
177 | CaptureRequest mJpegRequest; |
178 | bool mExitJpegThread; |
179 | bool mNeedexif; |
180 | int mMainJpegSize, mThumbJpegSize; |
181 | uint8_t *mSrcThumbBuffer; |
182 | uint8_t *mDstThumbBuffer; |
183 | Buffers *mBuffers; |
184 | int mPendingrequest; |
185 | JpegListener *mListener; |
186 | struct ExifInfo mInfo; |
187 | StreamBuffer mJpegBuffer, mAuxBuffer; |
188 | bool mFoundJpeg, mFoundAux; |
189 | jpeg_compress_struct mCInfo; |
190 | |
191 | struct JpegError : public jpeg_error_mgr { |
192 | JpegCompressor *parent; |
193 | }; |
194 | j_common_ptr mJpegErrorInfo; |
195 | |
196 | struct JpegDestination : public jpeg_destination_mgr { |
197 | JpegCompressor *parent; |
198 | }; |
199 | |
200 | bool checkError(const char *msg); |
201 | status_t compress(); |
202 | |
203 | status_t thumbcompress(); |
204 | void cleanUp(); |
205 | |
206 | /** |
207 | * Inherited Thread virtual overrides |
208 | */ |
209 | private: |
210 | virtual status_t readyToRun(); |
211 | virtual bool threadLoop(); |
212 | }; |
213 | |
214 | } // namespace android |
215 | |
216 | #endif |
217 |