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