• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright (C) 2013, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "ProCamera"
20 #include <utils/Log.h>
21 #include <utils/threads.h>
22 #include <utils/Mutex.h>
23 
24 #include <binder/IPCThreadState.h>
25 #include <binder/IServiceManager.h>
26 #include <binder/IMemory.h>
27 
28 #include <camera/ProCamera.h>
29 #include <camera/ICameraService.h>
30 #include <camera/IProCameraUser.h>
31 #include <camera/IProCameraCallbacks.h>
32 
33 #include <gui/IGraphicBufferProducer.h>
34 
35 #include <system/camera_metadata.h>
36 
37 namespace android {
38 
connect(int cameraId)39 sp<ProCamera> ProCamera::connect(int cameraId)
40 {
41     return CameraBaseT::connect(cameraId, String16(),
42                                  ICameraService::USE_CALLING_UID);
43 }
44 
ProCamera(int cameraId)45 ProCamera::ProCamera(int cameraId)
46     : CameraBase(cameraId)
47 {
48 }
49 
~ProCamera()50 ProCamera::~ProCamera()
51 {
52 
53 }
54 
55 /* IProCameraUser's implementation */
56 
57 // callback from camera service
notifyCallback(int32_t msgType,int32_t ext1,int32_t ext2)58 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
59 {
60     return CameraBaseT::notifyCallback(msgType, ext1, ext2);
61 }
62 
onLockStatusChanged(IProCameraCallbacks::LockStatus newLockStatus)63 void ProCamera::onLockStatusChanged(
64                                  IProCameraCallbacks::LockStatus newLockStatus)
65 {
66     ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
67 
68     sp<ProCameraListener> listener;
69     {
70         Mutex::Autolock _l(mLock);
71         listener = mListener;
72     }
73     if (listener != NULL) {
74         switch (newLockStatus) {
75             case IProCameraCallbacks::LOCK_ACQUIRED:
76                 listener->onLockAcquired();
77                 break;
78             case IProCameraCallbacks::LOCK_RELEASED:
79                 listener->onLockReleased();
80                 break;
81             case IProCameraCallbacks::LOCK_STOLEN:
82                 listener->onLockStolen();
83                 break;
84             default:
85                 ALOGE("%s: Unknown lock status: %d",
86                       __FUNCTION__, newLockStatus);
87         }
88     }
89 }
90 
onResultReceived(int32_t frameId,camera_metadata * result)91 void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
92     ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
93 
94     sp<ProCameraListener> listener;
95     {
96         Mutex::Autolock _l(mLock);
97         listener = mListener;
98     }
99 
100     CameraMetadata tmp(result);
101 
102     // Unblock waitForFrame(id) callers
103     {
104         Mutex::Autolock al(mWaitMutex);
105         mMetadataReady = true;
106         mLatestMetadata = tmp; // make copy
107         mWaitCondition.broadcast();
108     }
109 
110     result = tmp.release();
111 
112     if (listener != NULL) {
113         listener->onResultReceived(frameId, result);
114     } else {
115         free_camera_metadata(result);
116     }
117 
118 }
119 
exclusiveTryLock()120 status_t ProCamera::exclusiveTryLock()
121 {
122     sp <IProCameraUser> c = mCamera;
123     if (c == 0) return NO_INIT;
124 
125     return c->exclusiveTryLock();
126 }
exclusiveLock()127 status_t ProCamera::exclusiveLock()
128 {
129     sp <IProCameraUser> c = mCamera;
130     if (c == 0) return NO_INIT;
131 
132     return c->exclusiveLock();
133 }
exclusiveUnlock()134 status_t ProCamera::exclusiveUnlock()
135 {
136     sp <IProCameraUser> c = mCamera;
137     if (c == 0) return NO_INIT;
138 
139     return c->exclusiveUnlock();
140 }
hasExclusiveLock()141 bool ProCamera::hasExclusiveLock()
142 {
143     sp <IProCameraUser> c = mCamera;
144     if (c == 0) return NO_INIT;
145 
146     return c->hasExclusiveLock();
147 }
148 
149 // Note that the callee gets a copy of the metadata.
submitRequest(const struct camera_metadata * metadata,bool streaming)150 int ProCamera::submitRequest(const struct camera_metadata* metadata,
151                              bool streaming)
152 {
153     sp <IProCameraUser> c = mCamera;
154     if (c == 0) return NO_INIT;
155 
156     return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
157                             streaming);
158 }
159 
cancelRequest(int requestId)160 status_t ProCamera::cancelRequest(int requestId)
161 {
162     sp <IProCameraUser> c = mCamera;
163     if (c == 0) return NO_INIT;
164 
165     return c->cancelRequest(requestId);
166 }
167 
deleteStream(int streamId)168 status_t ProCamera::deleteStream(int streamId)
169 {
170     sp <IProCameraUser> c = mCamera;
171     if (c == 0) return NO_INIT;
172 
173     status_t s = c->deleteStream(streamId);
174 
175     mStreams.removeItem(streamId);
176 
177     return s;
178 }
179 
createStream(int width,int height,int format,const sp<Surface> & surface,int * streamId)180 status_t ProCamera::createStream(int width, int height, int format,
181                                  const sp<Surface>& surface,
182                                  /*out*/
183                                  int* streamId)
184 {
185     *streamId = -1;
186 
187     ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
188                                                                        format);
189 
190     if (surface == 0) {
191         return BAD_VALUE;
192     }
193 
194     return createStream(width, height, format,
195                         surface->getIGraphicBufferProducer(),
196                         streamId);
197 }
198 
createStream(int width,int height,int format,const sp<IGraphicBufferProducer> & bufferProducer,int * streamId)199 status_t ProCamera::createStream(int width, int height, int format,
200                                  const sp<IGraphicBufferProducer>& bufferProducer,
201                                  /*out*/
202                                  int* streamId) {
203     *streamId = -1;
204 
205     ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
206                                                                        format);
207 
208     if (bufferProducer == 0) {
209         return BAD_VALUE;
210     }
211 
212     sp <IProCameraUser> c = mCamera;
213     status_t stat = c->createStream(width, height, format, bufferProducer,
214                                     streamId);
215 
216     if (stat == OK) {
217         StreamInfo s(*streamId);
218 
219         mStreams.add(*streamId, s);
220     }
221 
222     return stat;
223 }
224 
createStreamCpu(int width,int height,int format,int heapCount,sp<CpuConsumer> * cpuConsumer,int * streamId)225 status_t ProCamera::createStreamCpu(int width, int height, int format,
226                                     int heapCount,
227                                     /*out*/
228                                     sp<CpuConsumer>* cpuConsumer,
229                                     int* streamId) {
230     return createStreamCpu(width, height, format, heapCount,
231                            /*synchronousMode*/true,
232                            cpuConsumer, streamId);
233 }
234 
createStreamCpu(int width,int height,int format,int heapCount,bool synchronousMode,sp<CpuConsumer> * cpuConsumer,int * streamId)235 status_t ProCamera::createStreamCpu(int width, int height, int format,
236                                     int heapCount,
237                                     bool synchronousMode,
238                                     /*out*/
239                                     sp<CpuConsumer>* cpuConsumer,
240                                     int* streamId)
241 {
242     ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
243                                                                         format);
244 
245     *cpuConsumer = NULL;
246 
247     sp <IProCameraUser> c = mCamera;
248     if (c == 0) return NO_INIT;
249 
250     sp<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode);
251     cc->setName(String8("ProCamera::mCpuConsumer"));
252 
253     sp<Surface> stc = new Surface(
254         cc->getProducerInterface());
255 
256     status_t s = createStream(width, height, format,
257                               stc->getIGraphicBufferProducer(),
258                               streamId);
259 
260     if (s != OK) {
261         ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
262                     width, height, format);
263         return s;
264     }
265 
266     sp<ProFrameListener> frameAvailableListener =
267         new ProFrameListener(this, *streamId);
268 
269     getStreamInfo(*streamId).cpuStream = true;
270     getStreamInfo(*streamId).cpuConsumer = cc;
271     getStreamInfo(*streamId).synchronousMode = synchronousMode;
272     getStreamInfo(*streamId).stc = stc;
273     // for lifetime management
274     getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
275 
276     cc->setFrameAvailableListener(frameAvailableListener);
277 
278     *cpuConsumer = cc;
279 
280     return s;
281 }
282 
getCameraInfo(int cameraId)283 camera_metadata* ProCamera::getCameraInfo(int cameraId) {
284     ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
285 
286     sp <IProCameraUser> c = mCamera;
287     if (c == 0) return NULL;
288 
289     camera_metadata* ptr = NULL;
290     status_t status = c->getCameraInfo(cameraId, &ptr);
291 
292     if (status != OK) {
293         ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
294     }
295 
296     return ptr;
297 }
298 
createDefaultRequest(int templateId,camera_metadata ** request) const299 status_t ProCamera::createDefaultRequest(int templateId,
300                                              camera_metadata** request) const {
301     ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
302 
303     sp <IProCameraUser> c = mCamera;
304     if (c == 0) return NO_INIT;
305 
306     return c->createDefaultRequest(templateId, request);
307 }
308 
onFrameAvailable(int streamId)309 void ProCamera::onFrameAvailable(int streamId) {
310     ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
311 
312     sp<ProCameraListener> listener = mListener;
313     StreamInfo& stream = getStreamInfo(streamId);
314 
315     if (listener.get() != NULL) {
316         listener->onFrameAvailable(streamId, stream.cpuConsumer);
317     }
318 
319     // Unblock waitForFrame(id) callers
320     {
321         Mutex::Autolock al(mWaitMutex);
322         getStreamInfo(streamId).frameReady++;
323         mWaitCondition.broadcast();
324     }
325 }
326 
waitForFrameBuffer(int streamId)327 int ProCamera::waitForFrameBuffer(int streamId) {
328     status_t stat = BAD_VALUE;
329     Mutex::Autolock al(mWaitMutex);
330 
331     StreamInfo& si = getStreamInfo(streamId);
332 
333     if (si.frameReady > 0) {
334         int numFrames = si.frameReady;
335         si.frameReady = 0;
336         return numFrames;
337     } else {
338         while (true) {
339             stat = mWaitCondition.waitRelative(mWaitMutex,
340                                                 mWaitTimeout);
341             if (stat != OK) {
342                 ALOGE("%s: Error while waiting for frame buffer: %d",
343                     __FUNCTION__, stat);
344                 return stat;
345             }
346 
347             if (si.frameReady > 0) {
348                 int numFrames = si.frameReady;
349                 si.frameReady = 0;
350                 return numFrames;
351             }
352             // else it was some other stream that got unblocked
353         }
354     }
355 
356     return stat;
357 }
358 
dropFrameBuffer(int streamId,int count)359 int ProCamera::dropFrameBuffer(int streamId, int count) {
360     StreamInfo& si = getStreamInfo(streamId);
361 
362     if (!si.cpuStream) {
363         return BAD_VALUE;
364     } else if (count < 0) {
365         return BAD_VALUE;
366     }
367 
368     if (!si.synchronousMode) {
369         ALOGW("%s: No need to drop frames on asynchronous streams,"
370               " as asynchronous mode only keeps 1 latest frame around.",
371               __FUNCTION__);
372         return BAD_VALUE;
373     }
374 
375     int numDropped = 0;
376     for (int i = 0; i < count; ++i) {
377         CpuConsumer::LockedBuffer buffer;
378         if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
379             break;
380         }
381 
382         si.cpuConsumer->unlockBuffer(buffer);
383         numDropped++;
384     }
385 
386     return numDropped;
387 }
388 
waitForFrameMetadata()389 status_t ProCamera::waitForFrameMetadata() {
390     status_t stat = BAD_VALUE;
391     Mutex::Autolock al(mWaitMutex);
392 
393     if (mMetadataReady) {
394         return OK;
395     } else {
396         while (true) {
397             stat = mWaitCondition.waitRelative(mWaitMutex,
398                                                mWaitTimeout);
399 
400             if (stat != OK) {
401                 ALOGE("%s: Error while waiting for metadata: %d",
402                         __FUNCTION__, stat);
403                 return stat;
404             }
405 
406             if (mMetadataReady) {
407                 mMetadataReady = false;
408                 return OK;
409             }
410             // else it was some other stream or metadata
411         }
412     }
413 
414     return stat;
415 }
416 
consumeFrameMetadata()417 CameraMetadata ProCamera::consumeFrameMetadata() {
418     Mutex::Autolock al(mWaitMutex);
419 
420     // Destructive: Subsequent calls return empty metadatas
421     CameraMetadata tmp = mLatestMetadata;
422     mLatestMetadata.clear();
423 
424     return tmp;
425 }
426 
getStreamInfo(int streamId)427 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
428     return mStreams.editValueFor(streamId);
429 }
430 
431 }; // namespace android
432