OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / services / camera / libcameraservice / CameraHardwareStub.cpp
1 /*
2 **
3 ** Copyright 2008, 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_TAG "CameraHardwareStub"
19 #include <utils/Log.h>
20
21 #include "CameraHardwareStub.h"
22 #include <utils/threads.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include "CannedJpeg.h"
27
28 namespace android {
29
30 CameraHardwareStub::CameraHardwareStub()
31                   : mParameters(),
32                     mPreviewHeap(0),
33                     mRawHeap(0),
34                     mFakeCamera(0),
35                     mPreviewFrameSize(0),
36                     mNotifyCb(0),
37                     mDataCb(0),
38                     mDataCbTimestamp(0),
39                     mCallbackCookie(0),
40                     mMsgEnabled(0),
41                     mCurrentPreviewFrame(0)
42 {
43     initDefaultParameters();
44 }
45
46 void CameraHardwareStub::initDefaultParameters()
47 {
48     CameraParameters p;
49
50     p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
51     p.setPreviewSize(320, 240);
52     p.setPreviewFrameRate(15);
53     p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
54
55     p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
56     p.setPictureSize(320, 240);
57     p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
58
59     if (setParameters(p) != NO_ERROR) {
60         LOGE("Failed to set default parameters?!");
61     }
62 }
63
64 void CameraHardwareStub::initHeapLocked()
65 {
66     // Create raw heap.
67     int picture_width, picture_height;
68     mParameters.getPictureSize(&picture_width, &picture_height);
69     mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
70
71     int preview_width, preview_height;
72     mParameters.getPreviewSize(&preview_width, &preview_height);
73     LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
74
75     // Note that we enforce yuv420sp in setParameters().
76     int how_big = preview_width * preview_height * 3 / 2;
77
78     // If we are being reinitialized to the same size as before, no
79     // work needs to be done.
80     if (how_big == mPreviewFrameSize)
81         return;
82
83     mPreviewFrameSize = how_big;
84
85     // Make a new mmap'ed heap that can be shared across processes.
86     // use code below to test with pmem
87     mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
88     // Make an IMemory for each frame so that we can reuse them in callbacks.
89     for (int i = 0; i < kBufferCount; i++) {
90         mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
91     }
92
93     // Recreate the fake camera to reflect the current size.
94     delete mFakeCamera;
95     mFakeCamera = new FakeCamera(preview_width, preview_height);
96 }
97
98 CameraHardwareStub::~CameraHardwareStub()
99 {
100     delete mFakeCamera;
101     mFakeCamera = 0; // paranoia
102 }
103
104 sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
105 {
106     return mPreviewHeap;
107 }
108
109 sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
110 {
111     return mRawHeap;
112 }
113
114 void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
115                                       data_callback data_cb,
116                                       data_callback_timestamp data_cb_timestamp,
117                                       void* user)
118 {
119     Mutex::Autolock lock(mLock);
120     mNotifyCb = notify_cb;
121     mDataCb = data_cb;
122     mDataCbTimestamp = data_cb_timestamp;
123     mCallbackCookie = user;
124 }
125
126 void CameraHardwareStub::enableMsgType(int32_t msgType)
127 {
128     Mutex::Autolock lock(mLock);
129     mMsgEnabled |= msgType;
130 }
131
132 void CameraHardwareStub::disableMsgType(int32_t msgType)
133 {
134     Mutex::Autolock lock(mLock);
135     mMsgEnabled &= ~msgType;
136 }
137
138 bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
139 {
140     Mutex::Autolock lock(mLock);
141     return (mMsgEnabled & msgType);
142 }
143
144 // ---------------------------------------------------------------------------
145
146 int CameraHardwareStub::previewThread()
147 {
148     mLock.lock();
149         // the attributes below can change under our feet...
150
151         int previewFrameRate = mParameters.getPreviewFrameRate();
152
153         // Find the offset within the heap of the current buffer.
154         ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
155
156         sp<MemoryHeapBase> heap = mPreviewHeap;
157
158         // this assumes the internal state of fake camera doesn't change
159         // (or is thread safe)
160         FakeCamera* fakeCamera = mFakeCamera;
161
162         sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
163
164     mLock.unlock();
165
166     // TODO: here check all the conditions that could go wrong
167     if (buffer != 0) {
168         // Calculate how long to wait between frames.
169         int delay = (int)(1000000.0f / float(previewFrameRate));
170
171         // This is always valid, even if the client died -- the memory
172         // is still mapped in our process.
173         void *base = heap->base();
174
175         // Fill the current frame with the fake camera.
176         uint8_t *frame = ((uint8_t *)base) + offset;
177         fakeCamera->getNextFrameAsYuv420(frame);
178
179         //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
180
181         // Notify the client of a new frame.
182         if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
183             mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
184
185         // Advance the buffer pointer.
186         mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
187
188         // Wait for it...
189         usleep(delay);
190     }
191
192     return NO_ERROR;
193 }
194
195 status_t CameraHardwareStub::startPreview()
196 {
197     Mutex::Autolock lock(mLock);
198     if (mPreviewThread != 0) {
199         // already running
200         return INVALID_OPERATION;
201     }
202     mPreviewThread = new PreviewThread(this);
203     return NO_ERROR;
204 }
205
206 void CameraHardwareStub::stopPreview()
207 {
208     sp<PreviewThread> previewThread;
209
210     { // scope for the lock
211         Mutex::Autolock lock(mLock);
212         previewThread = mPreviewThread;
213     }
214
215     // don't hold the lock while waiting for the thread to quit
216     if (previewThread != 0) {
217         previewThread->requestExitAndWait();
218     }
219
220     Mutex::Autolock lock(mLock);
221     mPreviewThread.clear();
222 }
223
224 bool CameraHardwareStub::previewEnabled() {
225     return mPreviewThread != 0;
226 }
227
228 status_t CameraHardwareStub::startRecording()
229 {
230     return UNKNOWN_ERROR;
231 }
232
233 void CameraHardwareStub::stopRecording()
234 {
235 }
236
237 bool CameraHardwareStub::recordingEnabled()
238 {
239     return false;
240 }
241
242 void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
243 {
244 }
245
246 // ---------------------------------------------------------------------------
247
248 int CameraHardwareStub::beginAutoFocusThread(void *cookie)
249 {
250     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
251     return c->autoFocusThread();
252 }
253
254 int CameraHardwareStub::autoFocusThread()
255 {
256     if (mMsgEnabled & CAMERA_MSG_FOCUS)
257         mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
258     return NO_ERROR;
259 }
260
261 status_t CameraHardwareStub::autoFocus()
262 {
263     Mutex::Autolock lock(mLock);
264     if (createThread(beginAutoFocusThread, this) == false)
265         return UNKNOWN_ERROR;
266     return NO_ERROR;
267 }
268
269 status_t CameraHardwareStub::cancelAutoFocus()
270 {
271     return NO_ERROR;
272 }
273
274 /*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
275 {
276     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
277     return c->pictureThread();
278 }
279
280 int CameraHardwareStub::pictureThread()
281 {
282     if (mMsgEnabled & CAMERA_MSG_SHUTTER)
283         mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
284
285     if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
286         //FIXME: use a canned YUV image!
287         // In the meantime just make another fake camera picture.
288         int w, h;
289         mParameters.getPictureSize(&w, &h);
290         sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
291         FakeCamera cam(w, h);
292         cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
293         mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
294     }
295
296     if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
297         sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
298         sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
299         memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
300         mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
301     }
302     return NO_ERROR;
303 }
304
305 status_t CameraHardwareStub::takePicture()
306 {
307     stopPreview();
308     if (createThread(beginPictureThread, this) == false)
309         return UNKNOWN_ERROR;
310     return NO_ERROR;
311 }
312
313 status_t CameraHardwareStub::cancelPicture()
314 {
315     return NO_ERROR;
316 }
317
318 status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
319 {
320     const size_t SIZE = 256;
321     char buffer[SIZE];
322     String8 result;
323     AutoMutex lock(&mLock);
324     if (mFakeCamera != 0) {
325         mFakeCamera->dump(fd);
326         mParameters.dump(fd, args);
327         snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
328         result.append(buffer);
329     } else {
330         result.append("No camera client yet.\n");
331     }
332     write(fd, result.string(), result.size());
333     return NO_ERROR;
334 }
335
336 status_t CameraHardwareStub::setParameters(const CameraParameters& params)
337 {
338     Mutex::Autolock lock(mLock);
339     // XXX verify params
340
341     if (strcmp(params.getPreviewFormat(),
342         CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
343         LOGE("Only yuv420sp preview is supported");
344         return -1;
345     }
346
347     if (strcmp(params.getPictureFormat(),
348         CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
349         LOGE("Only jpeg still pictures are supported");
350         return -1;
351     }
352
353     int w, h;
354     params.getPictureSize(&w, &h);
355     if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
356         LOGE("Still picture size must be size of canned JPEG (%dx%d)",
357              kCannedJpegWidth, kCannedJpegHeight);
358         return -1;
359     }
360
361     mParameters = params;
362     initHeapLocked();
363
364     return NO_ERROR;
365 }
366
367 CameraParameters CameraHardwareStub::getParameters() const
368 {
369     Mutex::Autolock lock(mLock);
370     return mParameters;
371 }
372
373 status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
374                                          int32_t arg2)
375 {
376     return BAD_VALUE;
377 }
378
379 void CameraHardwareStub::release()
380 {
381 }
382
383 sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
384 {
385     return new CameraHardwareStub();
386 }
387
388 static CameraInfo sCameraInfo[] = {
389     {
390         CAMERA_FACING_BACK,
391         90,  /* orientation */
392     }
393 };
394
395 extern "C" int HAL_getNumberOfCameras()
396 {
397     return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
398 }
399
400 extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
401 {
402     memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
403 }
404
405 extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
406 {
407     return CameraHardwareStub::createInstance();
408 }
409
410 }; // namespace android