OSDN Git Service

DO NOT MERGE FLACExtractor: copy protect mWriteBuffer am: 13c77f4fe0 am: 761abda1bd
[android-x86/frameworks-av.git] / camera / ProCamera.cpp
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
38 sp<ProCamera> ProCamera::connect(int cameraId)
39 {
40     return CameraBaseT::connect(cameraId, String16(),
41                                  ICameraService::USE_CALLING_UID);
42 }
43
44 ProCamera::ProCamera(int cameraId)
45     : CameraBase(cameraId)
46 {
47 }
48
49 CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService =
50         &ICameraService::connectPro;
51
52 ProCamera::~ProCamera()
53 {
54
55 }
56
57 /* IProCameraUser's implementation */
58
59 // callback from camera service
60 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
61 {
62     return CameraBaseT::notifyCallback(msgType, ext1, ext2);
63 }
64
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
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
122 status_t ProCamera::exclusiveTryLock()
123 {
124     sp <IProCameraUser> c = mCamera;
125     if (c == 0) return NO_INIT;
126
127     return c->exclusiveTryLock();
128 }
129 status_t ProCamera::exclusiveLock()
130 {
131     sp <IProCameraUser> c = mCamera;
132     if (c == 0) return NO_INIT;
133
134     return c->exclusiveLock();
135 }
136 status_t ProCamera::exclusiveUnlock()
137 {
138     sp <IProCameraUser> c = mCamera;
139     if (c == 0) return NO_INIT;
140
141     return c->exclusiveUnlock();
142 }
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.
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
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
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
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
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
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
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<IGraphicBufferProducer> producer;
253     sp<IGraphicBufferConsumer> consumer;
254     BufferQueue::createBufferQueue(&producer, &consumer);
255     sp<CpuConsumer> cc = new CpuConsumer(consumer, heapCount
256             /*, synchronousMode*/);
257     cc->setName(String8("ProCamera::mCpuConsumer"));
258
259     sp<Surface> stc = new Surface(producer);
260
261     status_t s = createStream(width, height, format,
262                               stc->getIGraphicBufferProducer(),
263                               streamId);
264
265     if (s != OK) {
266         ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
267                     width, height, format);
268         return s;
269     }
270
271     sp<ProFrameListener> frameAvailableListener =
272         new ProFrameListener(this, *streamId);
273
274     getStreamInfo(*streamId).cpuStream = true;
275     getStreamInfo(*streamId).cpuConsumer = cc;
276     getStreamInfo(*streamId).synchronousMode = synchronousMode;
277     getStreamInfo(*streamId).stc = stc;
278     // for lifetime management
279     getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
280
281     cc->setFrameAvailableListener(frameAvailableListener);
282
283     *cpuConsumer = cc;
284
285     return s;
286 }
287
288 camera_metadata* ProCamera::getCameraInfo(int cameraId) {
289     ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
290
291     sp <IProCameraUser> c = mCamera;
292     if (c == 0) return NULL;
293
294     camera_metadata* ptr = NULL;
295     status_t status = c->getCameraInfo(cameraId, &ptr);
296
297     if (status != OK) {
298         ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
299     }
300
301     return ptr;
302 }
303
304 status_t ProCamera::createDefaultRequest(int templateId,
305                                              camera_metadata** request) const {
306     ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
307
308     sp <IProCameraUser> c = mCamera;
309     if (c == 0) return NO_INIT;
310
311     return c->createDefaultRequest(templateId, request);
312 }
313
314 void ProCamera::onFrameAvailable(int streamId) {
315     ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
316
317     sp<ProCameraListener> listener = mListener;
318     StreamInfo& stream = getStreamInfo(streamId);
319
320     if (listener.get() != NULL) {
321         listener->onFrameAvailable(streamId, stream.cpuConsumer);
322     }
323
324     // Unblock waitForFrame(id) callers
325     {
326         Mutex::Autolock al(mWaitMutex);
327         getStreamInfo(streamId).frameReady++;
328         mWaitCondition.broadcast();
329     }
330 }
331
332 int ProCamera::waitForFrameBuffer(int streamId) {
333     status_t stat = BAD_VALUE;
334     Mutex::Autolock al(mWaitMutex);
335
336     StreamInfo& si = getStreamInfo(streamId);
337
338     if (si.frameReady > 0) {
339         int numFrames = si.frameReady;
340         si.frameReady = 0;
341         return numFrames;
342     } else {
343         while (true) {
344             stat = mWaitCondition.waitRelative(mWaitMutex,
345                                                 mWaitTimeout);
346             if (stat != OK) {
347                 ALOGE("%s: Error while waiting for frame buffer: %d",
348                     __FUNCTION__, stat);
349                 return stat;
350             }
351
352             if (si.frameReady > 0) {
353                 int numFrames = si.frameReady;
354                 si.frameReady = 0;
355                 return numFrames;
356             }
357             // else it was some other stream that got unblocked
358         }
359     }
360
361     return stat;
362 }
363
364 int ProCamera::dropFrameBuffer(int streamId, int count) {
365     StreamInfo& si = getStreamInfo(streamId);
366
367     if (!si.cpuStream) {
368         return BAD_VALUE;
369     } else if (count < 0) {
370         return BAD_VALUE;
371     }
372
373     if (!si.synchronousMode) {
374         ALOGW("%s: No need to drop frames on asynchronous streams,"
375               " as asynchronous mode only keeps 1 latest frame around.",
376               __FUNCTION__);
377         return BAD_VALUE;
378     }
379
380     int numDropped = 0;
381     for (int i = 0; i < count; ++i) {
382         CpuConsumer::LockedBuffer buffer;
383         if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
384             break;
385         }
386
387         si.cpuConsumer->unlockBuffer(buffer);
388         numDropped++;
389     }
390
391     return numDropped;
392 }
393
394 status_t ProCamera::waitForFrameMetadata() {
395     status_t stat = BAD_VALUE;
396     Mutex::Autolock al(mWaitMutex);
397
398     if (mMetadataReady) {
399         return OK;
400     } else {
401         while (true) {
402             stat = mWaitCondition.waitRelative(mWaitMutex,
403                                                mWaitTimeout);
404
405             if (stat != OK) {
406                 ALOGE("%s: Error while waiting for metadata: %d",
407                         __FUNCTION__, stat);
408                 return stat;
409             }
410
411             if (mMetadataReady) {
412                 mMetadataReady = false;
413                 return OK;
414             }
415             // else it was some other stream or metadata
416         }
417     }
418
419     return stat;
420 }
421
422 CameraMetadata ProCamera::consumeFrameMetadata() {
423     Mutex::Autolock al(mWaitMutex);
424
425     // Destructive: Subsequent calls return empty metadatas
426     CameraMetadata tmp = mLatestMetadata;
427     mLatestMetadata.clear();
428
429     return tmp;
430 }
431
432 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
433     return mStreams.editValueFor(streamId);
434 }
435
436 }; // namespace android