status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { LOG1("sendCommand (pid %d)", getCallingPid()); int orientation; Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) { // Mirror the preview if the camera is front-facing. orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT); if (orientation == -1) return BAD_VALUE; if (mOrientation != orientation) { mOrientation = orientation; if (mPreviewWindow != 0) { native_window_set_buffers_transform(mPreviewWindow.get(), mOrientation); } } return OK; } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) { switch (arg1) { case 0: return enableShutterSound(false); case 1: return enableShutterSound(true); default: return BAD_VALUE; } return OK; } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) { mCameraService->playSound(CameraService::SOUND_RECORDING); } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) { // Silently ignore this command return INVALID_OPERATION; } else if (cmd == CAMERA_CMD_PING) { // If mHardware is 0, checkPidAndHardware will return error. return OK; #ifdef QCOM_HARDWARE } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) { enableMsgType(CAMERA_MSG_STATS_DATA); } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) { disableMsgType(CAMERA_MSG_STATS_DATA); } else if (cmd == CAMERA_CMD_METADATA_ON) { enableMsgType(CAMERA_MSG_META_DATA); } else if (cmd == CAMERA_CMD_METADATA_OFF) { disableMsgType(CAMERA_MSG_META_DATA); } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) { mLongshotEnabled = true; } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) { mLongshotEnabled = false; disableMsgType(CAMERA_MSG_SHUTTER); disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); #endif } return mHardware->sendCommand(cmd, arg1, arg2); }
status_t CameraClient::initialize(camera_module_t *module) { int callingPid = getCallingPid(); status_t res; LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); // Verify ops permissions res = startCameraOps(); if (res != OK) { return res; } char camera_device_name[10]; snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); mHardware = new CameraHardwareInterface(camera_device_name); res = mHardware->initialize(&module->common); if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mHardware.clear(); return res; } // mtk callback mHardware->setMtkCallbacks( mtkMetadataCallback, (void *)(uintptr_t)mCameraId ); mHardware->setCallbacks( notifyCallback, dataCallback, dataCallbackTimestamp, (void *)(uintptr_t)mCameraId); // Enable zoom, error, focus, and metadata messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE); //!++ #if 1 // Enable MTK-extended messages by default enableMsgType(MTK_CAMERA_MSG_EXT_NOTIFY | MTK_CAMERA_MSG_EXT_DATA); #endif //!-- LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId); return OK; }
status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { LOG1("sendCommand (pid %d)", getCallingPid()); int orientation; Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) { // Mirror the preview if the camera is front-facing. orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT); if (orientation == -1) return BAD_VALUE; if (mOrientation != orientation) { mOrientation = orientation; if (mPreviewWindow != 0) { native_window_set_buffers_transform(mPreviewWindow.get(), mOrientation); } } return OK; } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) { switch (arg1) { case 0: enableShutterSound(false); break; case 1: enableShutterSound(true); break; default: return BAD_VALUE; } return OK; } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) { mCameraService->playSound(SOUND_RECORDING); } else if (cmd == CAMERA_CMD_HISTOGRAM_ON ) { enableMsgType(CAMERA_MSG_STATS_DATA); } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) { disableMsgType(CAMERA_MSG_STATS_DATA); } else if (cmd == CAMERA_CMD_START_FACE_DETECTION) { mFaceDetection = true; enableMsgType(CAMERA_MSG_PREVIEW_METADATA); } else if (cmd == CAMERA_CMD_STOP_FACE_DETECTION) { mFaceDetection = false; disableMsgType(CAMERA_MSG_PREVIEW_METADATA); } return mHardware->sendCommand(cmd, arg1, arg2); }
// take a picture - image is returned in callback status_t CameraService::Client::takePicture(int msgType) { char prop[PROPERTY_VALUE_MAX]; LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; //zxj ++ mstopPreview = true; //zxj -- if ((msgType & CAMERA_MSG_RAW_IMAGE) && (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) { LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY" " cannot be both enabled"); return BAD_VALUE; } // We only accept picture related message types // and ignore other types of messages for takePicture(). int picMsgType = msgType & (CAMERA_MSG_SHUTTER | CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_RAW_IMAGE | CAMERA_MSG_RAW_IMAGE_NOTIFY | CAMERA_MSG_COMPRESSED_IMAGE); disableMsgType(CAMERA_MSG_PREVIEW_METADATA); enableMsgType(picMsgType); mburstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter"); if(mburstCnt <= 0) mburstCnt = 1; LOG1("mburstCnt = %d", mburstCnt); return mHardware->takePicture(); }
status_t CameraService::Client::startPreviewMode() { LOG1("startPreviewMode"); status_t result = NO_ERROR; // if preview has been enabled, nothing needs to be done if (mHardware->previewEnabled()) { return NO_ERROR; } if (mUseOverlay) { // If preview display has been set, set overlay now. if (mSurface != 0) { result = setOverlay(); } #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP result = mHardware->startPreview(); #endif if (result != NO_ERROR) return result; #ifndef USE_OVERLAY_FORMAT_YCbCr_420_SP result = mHardware->startPreview(); #endif } else { enableMsgType(CAMERA_MSG_PREVIEW_FRAME); result = mHardware->startPreview(); if (result != NO_ERROR) return result; // If preview display has been set, register preview buffers now. if (mSurface != 0) { // Unregister here because the surface may be previously registered // with the raw (snapshot) heap. mSurface->unregisterBuffers(); result = registerPreviewBuffers(); } } return result; }
// start preview mode status_t CameraClient::startPreview() { #ifdef CAMERA_MSG_MGMT enableMsgType(CAMERA_MSG_PREVIEW_METADATA); #endif LOG1("startPreview (pid %d)", getCallingPid()); return startCameraMode(CAMERA_PREVIEW_MODE); }
// take a picture - image is returned in callback status_t CameraService::Client::takePicture(int msgType) { LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; if ((msgType & CAMERA_MSG_RAW_IMAGE) && (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) { LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY" " cannot be both enabled"); return BAD_VALUE; } // We only accept picture related message types // and ignore other types of messages for takePicture(). int picMsgType = msgType & (CAMERA_MSG_SHUTTER | CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_RAW_IMAGE | CAMERA_MSG_RAW_IMAGE_NOTIFY | CAMERA_MSG_COMPRESSED_IMAGE); enableMsgType(picMsgType); return mHardware->takePicture(); }
// start preview mode status_t CameraClient::startPreview() { LOG1("startPreview (pid %d)", getCallingPid()); #ifdef QCOM_HARDWARE enableMsgType(CAMERA_MSG_PREVIEW_METADATA); #endif return startCameraMode(CAMERA_PREVIEW_MODE); }
status_t CameraService::Client::startRecordingMode() { LOG1("startRecordingMode"); status_t result = NO_ERROR; // if recording has been enabled, nothing needs to be done if (mHardware->recordingEnabled()) { return NO_ERROR; } // if preview has not been started, start preview first if (!mHardware->previewEnabled()) { result = startPreviewMode(); if (result != NO_ERROR) { return result; } } // start recording mode enableMsgType(CAMERA_MSG_VIDEO_FRAME); mCameraService->playSound(SOUND_RECORDING); result = mHardware->startRecording(); if (result != NO_ERROR) { LOGE("mHardware->startRecording() failed with status %d", result); } return result; }
CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, const sp<CameraHardwareInterface>& hardware, int cameraId, int cameraFacing, int clientPid) { int callingPid = getCallingPid(); LOG1("Client::Client E (pid %d)", callingPid); mCameraService = cameraService; mCameraClient = cameraClient; mHardware = hardware; mCameraId = cameraId; mCameraFacing = cameraFacing; mClientPid = clientPid; mMsgEnabled = 0; mSurface = 0; mPreviewWindow = 0; mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)cameraId); // Enable zoom, error, focus, and metadata messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | CAMERA_MSG_PREVIEW_METADATA); // Callback is disabled by default mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT); mPlayShutterSound = true; cameraService->setCameraBusy(cameraId); cameraService->loadSound(); LOG1("Client::Client X (pid %d)", callingPid); }
// start preview mode status_t CameraService::Client::startPreview() { LOG1("startPreview (pid %d)", getCallingPid()); //zxj ++ mstopPreview = false; //zxj -- if (mFaceDetection) { enableMsgType(CAMERA_MSG_PREVIEW_METADATA); } return startCameraMode(CAMERA_PREVIEW_MODE); }
// set the preview callback flag to affect how the received frames from // preview are handled. void CameraService::Client::setPreviewCallbackFlag(int callback_flag) { LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid()); Mutex::Autolock lock(mLock); if (checkPidAndHardware() != NO_ERROR) return; mPreviewCallbackFlag = callback_flag; if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) { enableMsgType(CAMERA_MSG_PREVIEW_FRAME); } else { disableMsgType(CAMERA_MSG_PREVIEW_FRAME); } }
// take a picture - image is returned in callback status_t CameraClient::takePicture(int msgType) { LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; if ((msgType & CAMERA_MSG_RAW_IMAGE) && (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) { ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY" " cannot be both enabled"); return BAD_VALUE; } // We only accept picture related message types // and ignore other types of messages for takePicture(). int picMsgType = msgType & (CAMERA_MSG_SHUTTER | CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_RAW_IMAGE | CAMERA_MSG_RAW_IMAGE_NOTIFY | #if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE) CAMERA_MSG_RAW_BURST | #endif CAMERA_MSG_COMPRESSED_IMAGE); #if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE) picMsgType |= CAMERA_MSG_COMPRESSED_BURST_IMAGE; #endif #ifdef CAMERA_MSG_MGMT disableMsgType(CAMERA_MSG_PREVIEW_METADATA); #endif enableMsgType(picMsgType); #ifdef QCOM_HARDWARE mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter"); if(mBurstCnt <= 0) mBurstCnt = 1; LOG1("mBurstCnt = %d", mBurstCnt); // HTC HDR mode requires that we snap multiple times, but only get one jpeg int numJpegs = mHardware->getParameters().getInt("num-jpegs-per-shutter"); if (numJpegs == 1 && mBurstCnt > 1) { while (mBurstCnt > 1) { result = mHardware->takePicture(); mBurstCnt--; } } #endif return mHardware->takePicture(); }
/****************************************************************************** * Burst Shutter Callback Handler * ext2: count-down shutter number; 0: the last one shutter. ******************************************************************************/ void CameraClient:: handleMtkExtBurstShutter(int32_t /*ext1*/, int32_t ext2) { handleShutter(); if (0 < ext2) { // not the last one burst shutter. enableMsgType(CAMERA_MSG_SHUTTER); ALOGD("[handleMtkExtBurstShutter] count-down burst shutter number:%d - enableMsgType(CAMERA_MSG_SHUTTER) \r\n", ext2); } else { ALOGD("[handleMtkExtBurstShutter] the last one burst shutter \r\n"); } }
// take a picture - image is returned in callback status_t CameraService::Client::takePicture() { LOG1("takePicture (pid %d)", getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; enableMsgType(CAMERA_MSG_SHUTTER | CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_RAW_IMAGE | CAMERA_MSG_COMPRESSED_IMAGE); return mHardware->takePicture(); }
// picture callback - compressed picture ready void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) { if (mburstCnt) mburstCnt--; if (!mburstCnt) { LOG1("mburstCnt = %d", mburstCnt); disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); if (mFaceDetection) { enableMsgType(CAMERA_MSG_PREVIEW_METADATA); } } sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL); } }
status_t CameraClient::initialize(camera_module_t *module) { int callingPid = getCallingPid(); status_t res; LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); // Verify ops permissions res = startCameraOps(); if (res != OK) { return res; } char camera_device_name[10]; snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); mHardware = new CameraHardwareInterface(camera_device_name); res = mHardware->initialize(&module->common); if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mHardware.clear(); return NO_INIT; } mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)mCameraId); // Enable zoom, error, focus, and metadata messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS #ifndef QCOM_HARDWARE | CAMERA_MSG_PREVIEW_METADATA #endif #ifndef OMAP_ICS_CAMERA | CAMERA_MSG_FOCUS_MOVE #endif ); LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId); return OK; }
CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, const sp<CameraHardwareInterface>& hardware, int cameraId, int cameraFacing, int clientPid) { int callingPid = getCallingPid(); LOG1("Client::Client E (pid %d)", callingPid); mCameraService = cameraService; mCameraClient = cameraClient; mHardware = hardware; mCameraId = cameraId; mCameraFacing = cameraFacing; mClientPid = clientPid; mMsgEnabled = 0; #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP if (mHardware != NULL) { #endif mUseOverlay = mHardware->useOverlay(); mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)cameraId); // Enable zoom, error, and focus messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS); mOverlayW = 0; mOverlayH = 0; // Callback is disabled by default mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT); mOrientationChanged = false; cameraService->setCameraBusy(cameraId); cameraService->loadSound(); #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP } #endif LOG1("Client::Client X (pid %d)", callingPid); }
// set the ISurface that the preview will use status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) { LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; result = NO_ERROR; // return if no change in surface. // asBinder() is safe on NULL (returns NULL) if (surface->asBinder() == mSurface->asBinder()) { return result; } if (mSurface != 0) { LOG1("clearing old preview surface %p", mSurface.get()); if (mUseOverlay) { // Force the destruction of any previous overlay sp<Overlay> dummy; mHardware->setOverlay(dummy); mOverlayRef = 0; } else { mSurface->unregisterBuffers(); } } mSurface = surface; mOverlayRef = 0; // If preview has been already started, set overlay or register preview // buffers now. #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP if (mHardware->previewEnabled() || mUseOverlay) { #else if (mHardware->previewEnabled()) { #endif if (mUseOverlay) { #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP if (mSurface != NULL) { #endif result = setOverlay(); #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP } #endif } else if (mSurface != 0) { result = registerPreviewBuffers(); } } return result; } status_t CameraService::Client::registerPreviewBuffers() { int w, h; CameraParameters params(mHardware->getParameters()); params.getPreviewSize(&w, &h); //for 720p recording , preview can be 800X448 if(w == preview_sizes[0].width && h== preview_sizes[0].height){ LOGD("registerpreviewbufs :changing dimensions to 768X432 for 720p recording."); w = preview_sizes[1].width; h = preview_sizes[1].height; } // FIXME: don't use a hardcoded format here. ISurface::BufferHeap buffers(w, h, w, h, HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0, mHardware->getPreviewHeap()); status_t result = mSurface->registerBuffers(buffers); if (result != NO_ERROR) { LOGE("registerBuffers failed with status %d", result); } return result; } status_t CameraService::Client::setOverlay() { int w, h; CameraParameters params(mHardware->getParameters()); params.getPreviewSize(&w, &h); //for 720p recording , preview can be 800X448 if(w == preview_sizes[0].width && h==preview_sizes[0].height){ LOGD("Changing overlay dimensions to 768X432 for 720p recording."); w = preview_sizes[1].width; h = preview_sizes[1].height; } if (w != mOverlayW || h != mOverlayH || mOrientationChanged) { // Force the destruction of any previous overlay sp<Overlay> dummy; mHardware->setOverlay(dummy); mOverlayRef = 0; #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP if (mOverlay != NULL) { mOverlay->destroy(); } #endif mOrientationChanged = false; } status_t result = NO_ERROR; if (mSurface == 0) { result = mHardware->setOverlay(NULL); } else { if (mOverlayRef == 0) { // FIXME: // Surfaceflinger may hold onto the previous overlay reference for some // time after we try to destroy it. retry a few times. In the future, we // should make the destroy call block, or possibly specify that we can // wait in the createOverlay call if the previous overlay is in the // process of being destroyed. for (int retry = 0; retry < 50; ++retry) { mOverlayRef = mSurface->createOverlay(w, h, #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP HAL_PIXEL_FORMAT_YCbCr_420_SP, #else OVERLAY_FORMAT_DEFAULT, #endif mOrientation); if (mOverlayRef != 0) break; LOGW("Overlay create failed - retrying"); usleep(20000); } if (mOverlayRef == 0) { LOGE("Overlay Creation Failed!"); return -EINVAL; } #ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP mOverlay = new Overlay(mOverlayRef); result = mHardware->setOverlay(mOverlay); #else result = mHardware->setOverlay(new Overlay(mOverlayRef)); #endif } } if (result != NO_ERROR) { LOGE("mHardware->setOverlay() failed with status %d\n", result); return result; } mOverlayW = w; mOverlayH = h; return result; } // set the preview callback flag to affect how the received frames from // preview are handled. void CameraService::Client::setPreviewCallbackFlag(int callback_flag) { LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid()); Mutex::Autolock lock(mLock); if (checkPidAndHardware() != NO_ERROR) return; mPreviewCallbackFlag = callback_flag; // If we don't use overlay, we always need the preview frame for display. // If we do use overlay, we only need the preview frame if the user // wants the data. if (mUseOverlay) { if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) { enableMsgType(CAMERA_MSG_PREVIEW_FRAME); } else { disableMsgType(CAMERA_MSG_PREVIEW_FRAME); } } }