1 /*
2 * Copyright 2017 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 #include "QCamera3HdrPlusListenerThread.h"
18
19
20 using ::android::hardware::camera::common::V1_0::helper::CameraMetadata;
21 using namespace android;
22
23 namespace qcamera {
24
QCamera3HdrPlusListenerThread(HdrPlusClientListener * listener)25 QCamera3HdrPlusListenerThread::QCamera3HdrPlusListenerThread(
26 HdrPlusClientListener *listener) : mListener(listener), mExitRequested(false),
27 mFatalError(false)
28 {
29 }
30
~QCamera3HdrPlusListenerThread()31 QCamera3HdrPlusListenerThread::~QCamera3HdrPlusListenerThread()
32 {
33 requestExit();
34
35 while (mResults.size() > 0) {
36 PendingResult result = mResults.front();
37 mResults.pop();
38
39 if (result.metadata != nullptr) {
40 free_camera_metadata(result.metadata);
41 }
42 }
43 }
44
onOpened(std::unique_ptr<HdrPlusClient> client)45 void QCamera3HdrPlusListenerThread::onOpened(std::unique_ptr<HdrPlusClient> client)
46 {
47 std::unique_lock<std::mutex> l(mCallbackLock);
48 if (mClient != nullptr) {
49 ALOGW("%s: An old client exists and will be destroyed.", __FUNCTION__);
50 }
51 mClient = std::move(client);
52 mPendingCallbacks.push(CALLBACK_TYPE_OPENED);
53 mCallbackCond.notify_one();
54 }
55
onOpenFailed(status_t err)56 void QCamera3HdrPlusListenerThread::onOpenFailed(status_t err)
57 {
58 std::unique_lock<std::mutex> l(mCallbackLock);
59 if (mOpenError != OK) {
60 ALOGW("%s: An old open failure exists and will be ignored: %s (%d)", __FUNCTION__,
61 strerror(-mOpenError), mOpenError);
62 }
63 mOpenError = err;
64 mPendingCallbacks.push(CALLBACK_TYPE_OPENFAILED);
65 mCallbackCond.notify_one();
66 }
67
onFatalError()68 void QCamera3HdrPlusListenerThread::onFatalError()
69 {
70 std::unique_lock<std::mutex> l(mCallbackLock);
71 if (mFatalError) {
72 ALOGW("%s: An old fatal failure exists.", __FUNCTION__);
73 }
74 mFatalError = true;
75 mPendingCallbacks.push(CALLBACK_TYPE_FATAL_ERROR);
76 mCallbackCond.notify_one();
77 }
78
onCaptureResult(pbcamera::CaptureResult * result,const camera_metadata_t & resultMetadata)79 void QCamera3HdrPlusListenerThread::onCaptureResult(pbcamera::CaptureResult *result,
80 const camera_metadata_t &resultMetadata)
81 {
82 std::unique_lock<std::mutex> l(mCallbackLock);
83
84 PendingResult pendingResult = {};
85 pendingResult.result = *result;
86 pendingResult.metadata = clone_camera_metadata(&resultMetadata);
87 pendingResult.isFailed = false;
88 mResults.push(pendingResult);
89
90 mPendingCallbacks.push(CALLBACK_TYPE_CAPTURE_RESULT);
91 mCallbackCond.notify_one();
92 }
93
onFailedCaptureResult(pbcamera::CaptureResult * failedResult)94 void QCamera3HdrPlusListenerThread::onFailedCaptureResult(pbcamera::CaptureResult *failedResult)
95 {
96 std::unique_lock<std::mutex> l(mCallbackLock);
97
98 PendingResult result = {};
99 result.result = *failedResult;
100 result.metadata = nullptr;
101 result.isFailed = true;
102 mResults.push(result);
103
104 mPendingCallbacks.push(CALLBACK_TYPE_CAPTURE_RESULT);
105 mCallbackCond.notify_one();
106 }
107
onShutter(uint32_t requestId,int64_t apSensorTimestampNs)108 void QCamera3HdrPlusListenerThread::onShutter(uint32_t requestId, int64_t apSensorTimestampNs)
109 {
110 std::unique_lock<std::mutex> l(mCallbackLock);
111
112 std::pair<uint32_t, int64_t> shutter(requestId, apSensorTimestampNs);
113 mShutters.push(shutter);
114
115 mPendingCallbacks.push(CALLBACK_TYPE_SHUTTER);
116 mCallbackCond.notify_one();
117 }
118
onNextCaptureReady(uint32_t requestId)119 void QCamera3HdrPlusListenerThread::onNextCaptureReady(uint32_t requestId)
120 {
121 std::unique_lock<std::mutex> l(mCallbackLock);
122 mNextCaptureReadyIds.push(requestId);
123
124 mPendingCallbacks.push(CALLBACK_TYPE_NEXT_CAPTURE_READY);
125 mCallbackCond.notify_one();
126
127 }
128
onPostview(uint32_t requestId,std::unique_ptr<std::vector<uint8_t>> postview,uint32_t width,uint32_t height,uint32_t stride,int32_t format)129 void QCamera3HdrPlusListenerThread::onPostview(uint32_t requestId,
130 std::unique_ptr<std::vector<uint8_t>> postview, uint32_t width, uint32_t height,
131 uint32_t stride, int32_t format)
132 {
133 std::unique_lock<std::mutex> l(mCallbackLock);
134
135 PendingPostview pendingPostview = {};
136 pendingPostview.requestId = requestId;
137 pendingPostview.postview = std::move(postview);
138 pendingPostview.width = width;
139 pendingPostview.height = height;
140 pendingPostview.stride = stride;
141 pendingPostview.format = format;
142 mPostviews.push(std::move(pendingPostview));
143
144 mPendingCallbacks.push(CALLBACK_TYPE_POSTVIEW);
145 mCallbackCond.notify_one();
146
147 }
148
requestExit()149 void QCamera3HdrPlusListenerThread::requestExit()
150 {
151 std::unique_lock<std::mutex> l(mCallbackLock);
152 mExitRequested = true;
153 mCallbackCond.notify_one();
154 }
155
handleFatalError()156 void QCamera3HdrPlusListenerThread::handleFatalError()
157 {
158 bool fatalError;
159 {
160 std::unique_lock<std::mutex> lock(mCallbackLock);
161 if (!mFatalError) {
162 ALOGW("%s: There is no fatal error.", __FUNCTION__);
163 return;
164 }
165
166 fatalError = mFatalError;
167 }
168
169 mListener->onFatalError();
170 }
171
handlePendingClient()172 void QCamera3HdrPlusListenerThread::handlePendingClient()
173 {
174 std::unique_ptr<HdrPlusClient> client;
175 {
176 std::unique_lock<std::mutex> lock(mCallbackLock);
177 if (mClient == nullptr) {
178 ALOGW("%s: There is no pending client.", __FUNCTION__);
179 return;
180 }
181
182 client = std::move(mClient);
183 }
184
185 mListener->onOpened(std::move(client));
186 }
187
handleOpenError()188 void QCamera3HdrPlusListenerThread::handleOpenError()
189 {
190 status_t err = OK;
191 {
192 std::unique_lock<std::mutex> lock(mCallbackLock);
193 if (mOpenError == OK) {
194 ALOGW("%s: There is no pending open failure.", __FUNCTION__);
195 return;
196 }
197
198 err = mOpenError;
199 mOpenError = OK;
200 }
201
202 mListener->onOpenFailed(err);
203 }
204
handleNextCaptureReady()205 void QCamera3HdrPlusListenerThread::handleNextCaptureReady()
206 {
207 uint32_t requestId = 0;
208 {
209 std::unique_lock<std::mutex> l(mCallbackLock);
210 if (mNextCaptureReadyIds.size() == 0) {
211 ALOGW("%s: There is no NextCaptureReady.", __FUNCTION__);
212 return;
213 }
214 requestId = mNextCaptureReadyIds.front();
215 mNextCaptureReadyIds.pop();
216 }
217 mListener->onNextCaptureReady(requestId);
218 }
219
handleCaptureResult()220 void QCamera3HdrPlusListenerThread::handleCaptureResult()
221 {
222 PendingResult result = {};
223 {
224 std::unique_lock<std::mutex> l(mCallbackLock);
225 if (mResults.size() == 0) {
226 ALOGW("%s: There is no capture result.", __FUNCTION__);
227 return;
228 }
229 result = mResults.front();
230 mResults.pop();
231 }
232
233 if (result.isFailed) {
234 mListener->onFailedCaptureResult(&result.result);
235 } else {
236 mListener->onCaptureResult(&result.result, *result.metadata);
237 }
238
239 if (result.metadata != nullptr) {
240 free_camera_metadata(result.metadata);
241 }
242 }
243
handleShutter()244 void QCamera3HdrPlusListenerThread::handleShutter()
245 {
246 uint32_t requestId;
247 int64_t apSensorTimestampNs;
248
249 {
250 std::unique_lock<std::mutex> l(mCallbackLock);
251 if (mShutters.size() == 0) {
252 ALOGW("%s: There is no shutter.", __FUNCTION__);
253 return;;
254 }
255
256 auto shutter = mShutters.front();
257 requestId = shutter.first;
258 apSensorTimestampNs = shutter.second;
259 mShutters.pop();
260 }
261
262 mListener->onShutter(requestId, apSensorTimestampNs);
263 }
264
handlePostview()265 void QCamera3HdrPlusListenerThread::handlePostview()
266 {
267 PendingPostview postview = {};
268
269 {
270 std::unique_lock<std::mutex> l(mCallbackLock);
271 if (mPostviews.size() == 0) {
272 ALOGW("%s: There is no postview.", __FUNCTION__);
273 return;;
274 }
275
276 postview = std::move(mPostviews.front());
277 mPostviews.pop();
278 }
279
280 mListener->onPostview(postview.requestId, std::move(postview.postview), postview.width,
281 postview.height, postview.stride, postview.format);
282 }
283
threadLoop()284 bool QCamera3HdrPlusListenerThread::threadLoop()
285 {
286 if (mListener == nullptr) {
287 ALOGE("%s: mListener is nullptr.", __FUNCTION__);
288 return false;
289 }
290
291 while (1) {
292 CallbackType nextCallback;
293
294 {
295 std::unique_lock<std::mutex> lock(mCallbackLock);
296 if (!mExitRequested && mPendingCallbacks.size() == 0) {
297 mCallbackCond.wait(lock,
298 [&] { return mExitRequested || mPendingCallbacks.size() > 0; });
299 }
300
301 if (mExitRequested) {
302 return false;
303 } else {
304 nextCallback = mPendingCallbacks.front();
305 mPendingCallbacks.pop();
306 }
307 }
308
309 switch (nextCallback) {
310 case CALLBACK_TYPE_OPENED:
311 handlePendingClient();
312 break;
313 case CALLBACK_TYPE_OPENFAILED:
314 handleOpenError();
315 break;
316 case CALLBACK_TYPE_FATAL_ERROR:
317 handleFatalError();
318 break;
319 case CALLBACK_TYPE_CAPTURE_RESULT:
320 handleCaptureResult();
321 break;
322 case CALLBACK_TYPE_SHUTTER:
323 handleShutter();
324 break;
325 case CALLBACK_TYPE_NEXT_CAPTURE_READY:
326 handleNextCaptureReady();
327 break;
328 case CALLBACK_TYPE_POSTVIEW:
329 handlePostview();
330 break;
331 default:
332 ALOGE("%s: Unknown callback type %d", __FUNCTION__, nextCallback);
333 break;
334 }
335 }
336
337 return false;
338 }
339
340 }; // namespace qcamera
341