OSDN Git Service

auto import from //depot/cupcake/@132589
[android-x86/frameworks-native.git] / 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                     mHeap(0),
33                     mFakeCamera(0),
34                     mPreviewFrameSize(0),
35                     mRawPictureCallback(0),
36                     mJpegPictureCallback(0),
37                     mPictureCallbackCookie(0),
38                     mPreviewCallback(0),
39                     mPreviewCallbackCookie(0),
40                     mAutoFocusCallback(0),
41                     mAutoFocusCallbackCookie(0),
42                     mCurrentPreviewFrame(0)
43 {
44     initDefaultParameters();
45 }
46
47 void CameraHardwareStub::initDefaultParameters()
48 {
49     CameraParameters p;
50
51     p.setPreviewSize(176, 144);
52     p.setPreviewFrameRate(15);
53     p.setPreviewFormat("yuv422sp");
54
55     p.setPictureSize(kCannedJpegWidth, kCannedJpegHeight);
56     p.setPictureFormat("jpeg");
57
58     if (setParameters(p) != NO_ERROR) {
59         LOGE("Failed to set default parameters?!");
60     } 
61 }
62
63 void CameraHardwareStub::initHeapLocked()
64 {
65     int width, height;
66     mParameters.getPreviewSize(&width, &height);
67
68     LOGD("initHeapLocked: preview size=%dx%d", width, height);
69
70     // Note that we enforce yuv422 in setParameters().
71     int how_big = width * height * 2;
72
73     // If we are being reinitialized to the same size as before, no
74     // work needs to be done.
75     if (how_big == mPreviewFrameSize)
76         return;
77
78     mPreviewFrameSize = how_big;
79
80     // Make a new mmap'ed heap that can be shared across processes. 
81     // use code below to test with pmem
82     mHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
83     // Make an IMemory for each frame so that we can reuse them in callbacks.
84     for (int i = 0; i < kBufferCount; i++) {
85         mBuffers[i] = new MemoryBase(mHeap, i * mPreviewFrameSize, mPreviewFrameSize);
86     }
87
88     // Recreate the fake camera to reflect the current size.
89     delete mFakeCamera;
90     mFakeCamera = new FakeCamera(width, height);
91 }
92
93 CameraHardwareStub::~CameraHardwareStub()
94 {
95     delete mFakeCamera;
96     mFakeCamera = 0; // paranoia
97     singleton.clear();
98 }
99
100 sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
101 {
102     return mHeap;
103 }
104
105 // ---------------------------------------------------------------------------
106
107 int CameraHardwareStub::previewThread()
108 {
109     mLock.lock();
110         // the attributes below can change under our feet...
111
112         int previewFrameRate = mParameters.getPreviewFrameRate();
113
114         // Find the offset within the heap of the current buffer.
115         ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
116
117         sp<MemoryHeapBase> heap = mHeap;
118     
119         // this assumes the internal state of fake camera doesn't change
120         // (or is thread safe)
121         FakeCamera* fakeCamera = mFakeCamera;
122         
123         sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
124         
125     mLock.unlock();
126
127     // TODO: here check all the conditions that could go wrong
128     if (buffer != 0) {
129         // Calculate how long to wait between frames.
130         int delay = (int)(1000000.0f / float(previewFrameRate));
131     
132         // This is always valid, even if the client died -- the memory
133         // is still mapped in our process.
134         void *base = heap->base();
135     
136         // Fill the current frame with the fake camera.
137         uint8_t *frame = ((uint8_t *)base) + offset;
138         fakeCamera->getNextFrameAsYuv422(frame);
139     
140         //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
141         
142         // Notify the client of a new frame.
143         mPreviewCallback(buffer, mPreviewCallbackCookie);
144     
145         // Advance the buffer pointer.
146         mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
147
148         // Wait for it...
149         usleep(delay);
150     }
151
152     return NO_ERROR;
153 }
154
155 status_t CameraHardwareStub::startPreview(preview_callback cb, void* user)
156 {
157     Mutex::Autolock lock(mLock);
158     if (mPreviewThread != 0) {
159         // already running
160         return INVALID_OPERATION;
161     }
162     mPreviewCallback = cb;
163     mPreviewCallbackCookie = user;
164     mPreviewThread = new PreviewThread(this);
165     return NO_ERROR;
166 }
167
168 void CameraHardwareStub::stopPreview()
169 {
170     sp<PreviewThread> previewThread;
171     
172     { // scope for the lock
173         Mutex::Autolock lock(mLock);
174         previewThread = mPreviewThread;
175     }
176
177     // don't hold the lock while waiting for the thread to quit
178     if (previewThread != 0) {
179         previewThread->requestExitAndWait();
180     }
181
182     Mutex::Autolock lock(mLock);
183     mPreviewThread.clear();
184 }
185
186 bool CameraHardwareStub::previewEnabled() {
187     return mPreviewThread != 0;
188 }
189
190 status_t CameraHardwareStub::startRecording(recording_callback cb, void* user)
191 {
192     return UNKNOWN_ERROR;
193 }
194
195 void CameraHardwareStub::stopRecording()
196 {
197 }
198
199 bool CameraHardwareStub::recordingEnabled()
200 {
201     return false;
202 }
203
204 void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
205 {
206 }
207
208 // ---------------------------------------------------------------------------
209
210 int CameraHardwareStub::beginAutoFocusThread(void *cookie)
211 {
212     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
213     return c->autoFocusThread();
214 }
215
216 int CameraHardwareStub::autoFocusThread()
217 {
218     if (mAutoFocusCallback != NULL) {
219         mAutoFocusCallback(true, mAutoFocusCallbackCookie);
220         mAutoFocusCallback = NULL;
221         return NO_ERROR;
222     }
223     return UNKNOWN_ERROR;
224 }
225
226 status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb,
227                                        void *user)
228 {
229     Mutex::Autolock lock(mLock);
230
231     if (mAutoFocusCallback != NULL) {
232         return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION;
233     }
234
235     mAutoFocusCallback = af_cb;
236     mAutoFocusCallbackCookie = user;
237     if (createThread(beginAutoFocusThread, this) == false)
238         return UNKNOWN_ERROR;
239     return NO_ERROR;
240 }
241
242 /*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
243 {
244     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
245     return c->pictureThread();
246 }
247
248 int CameraHardwareStub::pictureThread()
249 {
250     if (mShutterCallback)
251         mShutterCallback(mPictureCallbackCookie);
252
253     if (mRawPictureCallback) {
254         //FIXME: use a canned YUV image!
255         // In the meantime just make another fake camera picture.
256         int w, h;
257         mParameters.getPictureSize(&w, &h);
258         sp<MemoryHeapBase> heap = new MemoryHeapBase(w * 2 * h);
259         sp<MemoryBase> mem = new MemoryBase(heap, 0, w * 2 * h);
260         FakeCamera cam(w, h);
261         cam.getNextFrameAsYuv422((uint8_t *)heap->base());
262         if (mRawPictureCallback)
263             mRawPictureCallback(mem, mPictureCallbackCookie);
264     }
265
266     if (mJpegPictureCallback) {
267         sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
268         sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
269         memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
270         if (mJpegPictureCallback)
271             mJpegPictureCallback(mem, mPictureCallbackCookie);
272     }
273     return NO_ERROR;
274 }
275
276 status_t CameraHardwareStub::takePicture(shutter_callback shutter_cb,
277                                          raw_callback raw_cb,
278                                          jpeg_callback jpeg_cb,
279                                          void* user)
280 {
281     stopPreview();
282     mShutterCallback = shutter_cb;
283     mRawPictureCallback = raw_cb;
284     mJpegPictureCallback = jpeg_cb;
285     mPictureCallbackCookie = user;
286     if (createThread(beginPictureThread, this) == false)
287         return -1;
288     return NO_ERROR;
289 }
290
291 status_t CameraHardwareStub::cancelPicture(bool cancel_shutter,
292                                            bool cancel_raw,
293                                            bool cancel_jpeg)
294 {
295     if (cancel_shutter) mShutterCallback = NULL;
296     if (cancel_raw) mRawPictureCallback = NULL;
297     if (cancel_jpeg) mJpegPictureCallback = NULL;
298     return NO_ERROR;
299 }
300
301 status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
302 {
303     const size_t SIZE = 256;
304     char buffer[SIZE];
305     String8 result;
306     AutoMutex lock(&mLock);
307     if (mFakeCamera != 0) {
308         mFakeCamera->dump(fd, args);
309         mParameters.dump(fd, args);
310         snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
311         result.append(buffer);
312     } else {
313         result.append("No camera client yet.\n");
314     }
315     write(fd, result.string(), result.size());
316     return NO_ERROR;
317 }
318
319 status_t CameraHardwareStub::setParameters(const CameraParameters& params)
320 {
321     Mutex::Autolock lock(mLock);
322     // XXX verify params
323
324     if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) {
325         LOGE("Only yuv422sp preview is supported");
326         return -1;
327     }
328
329     if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
330         LOGE("Only jpeg still pictures are supported");
331         return -1;
332     }
333
334     int w, h;
335     params.getPictureSize(&w, &h);
336     if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
337         LOGE("Still picture size must be size of canned JPEG (%dx%d)",
338              kCannedJpegWidth, kCannedJpegHeight);
339         return -1;
340     }
341
342     mParameters = params;
343
344     initHeapLocked();
345
346     return NO_ERROR;
347 }
348
349 CameraParameters CameraHardwareStub::getParameters() const
350 {
351     Mutex::Autolock lock(mLock);
352     return mParameters;
353 }
354
355 void CameraHardwareStub::release()
356 {
357 }
358
359 wp<CameraHardwareInterface> CameraHardwareStub::singleton;
360
361 sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
362 {
363     if (singleton != 0) {
364         sp<CameraHardwareInterface> hardware = singleton.promote();
365         if (hardware != 0) {
366             return hardware;
367         }
368     }
369     sp<CameraHardwareInterface> hardware(new CameraHardwareStub());
370     singleton = hardware;
371     return hardware;
372 }
373
374 extern "C" sp<CameraHardwareInterface> openCameraHardware()
375 {
376     return CameraHardwareStub::createInstance();
377 }
378
379 }; // namespace android