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 ALOGE("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 ALOGD("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 status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf) 105 { 106 return NO_ERROR; 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 //ALOGV("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, NULL, 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, NULL, 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, NULL, 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 ALOGE("Only yuv420sp preview is supported"); 344 return -1; 345 } 346 347 if (strcmp(params.getPictureFormat(), 348 CameraParameters::PIXEL_FORMAT_JPEG) != 0) { 349 ALOGE("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 ALOGE("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 411