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