Loading services/camera/libcameraservice/Camera2Client.cpp +405 −62 Original line number Diff line number Diff line Loading @@ -394,7 +394,7 @@ status_t Camera2Client::setPreviewTexture( } status_t Camera2Client::setPreviewWindowLocked(const sp<IBinder>& binder, const sp<ANativeWindow>& window) { sp<ANativeWindow> window) { ATRACE_CALL(); status_t res; Loading @@ -402,23 +402,24 @@ status_t Camera2Client::setPreviewWindowLocked(const sp<IBinder>& binder, return NO_ERROR; } // TODO: Should wait until HAL has no remaining requests if (mPreviewStreamId != NO_STREAM) { res = mDevice->deleteStream(mPreviewStreamId); res = mDevice->waitUntilDrained(); if (res != OK) { ALOGE("%s: Error waiting for preview to drain: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } } res = mDevice->createStream(window, mParameters.previewWidth, mParameters.previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mPreviewStreamId); res = mDevice->deleteStream(mPreviewStreamId); if (res != OK) { ALOGE("%s: Unable to delete old preview stream: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } mPreviewStreamId = NO_STREAM; } mPreviewSurface = binder; mPreviewWindow = window; if (mState == WAITING_FOR_PREVIEW_WINDOW) { return startPreviewLocked(); Loading Loading @@ -447,34 +448,40 @@ status_t Camera2Client::startPreviewLocked() { return INVALID_OPERATION; } if (mPreviewStreamId == NO_STREAM) { if (mPreviewWindow == 0) { mState = WAITING_FOR_PREVIEW_WINDOW; return OK; } mState = STOPPED; if (mPreviewRequest == NULL) { updatePreviewRequest(); res = updatePreviewStream(); if (res != OK) { ALOGE("%s: Camera %d: Unable to update preview stream: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } uint8_t outputStream = mPreviewStreamId; camera_metadata_entry_t outputStreams; res = find_camera_metadata_entry(mPreviewRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreams); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(mPreviewRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &outputStream, 1); } else if (res == OK) { res = update_camera_metadata_entry(mPreviewRequest, outputStreams.index, &outputStream, 1, NULL); if (mPreviewRequest == NULL) { res = updatePreviewRequest(); if (res != OK) { ALOGE("%s: Camera %d: Unable to create preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } res = updateEntry(mPreviewRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &mPreviewStreamId, 1); if (res != OK) { ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mState = STOPPED; return res; } res = sort_camera_metadata(mPreviewRequest); if (res != OK) { ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } Loading @@ -483,7 +490,6 @@ status_t Camera2Client::startPreviewLocked() { ALOGE("%s: Camera %d: Unable to set preview request to start preview: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mState = STOPPED; return res; } mState = PREVIEW; Loading Loading @@ -596,41 +602,37 @@ status_t Camera2Client::takePicture(int msgType) { res = updateCaptureStream(); if (res != OK) { ALOGE("%s: Can't set up still image stream: %s (%d)", __FUNCTION__, strerror(-res), res); ALOGE("%s: Camera %d: Can't set up still image stream: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } if (mCaptureRequest == NULL) { res = updateCaptureRequest(); if (res != OK) { ALOGE("%s: Can't set up still image capture request: %s (%d)", __FUNCTION__, strerror(-res), res); ALOGE("%s: Camera %d: Can't create still image capture request: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } // TODO: For video snapshot, need 3 streams here // TODO: For video snapshot, will need 3 streams here camera_metadata_entry_t outputStreams; uint8_t streamIds[2] = { mPreviewStreamId, mCaptureStreamId }; res = find_camera_metadata_entry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreams); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS, streamIds, 2); } else if (res == OK) { res = update_camera_metadata_entry(mCaptureRequest, outputStreams.index, streamIds, 2, NULL); } res = updateEntry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &streamIds, 2); if (res != OK) { ALOGE("%s: Camera %d: Unable to set up still image capture request: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = sort_camera_metadata(mCaptureRequest); if (res != OK) { ALOGE("%s: Camera %d: Unable to sort capture request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } camera_metadata_t *captureCopy = clone_camera_metadata(mCaptureRequest); if (captureCopy == NULL) { Loading Loading @@ -1168,8 +1170,27 @@ status_t Camera2Client::setParameters(const String8& params) { mParameters.recordingHint = recordingHint; mParameters.videoStabilization = videoStabilization; updatePreviewRequest(); updateCaptureRequest(); res = updatePreviewRequest(); if (res != OK) { ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = updateCaptureRequest(); if (res != OK) { ALOGE("%s: Camera %d: Unable to update capture request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } if (mState == PREVIEW) { res = mDevice->setStreamingRequest(mPreviewRequest); if (res != OK) { ALOGE("%s: Camera %d: Error streaming new preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } return OK; } Loading Loading @@ -1980,6 +2001,53 @@ status_t Camera2Client::buildDefaultParameters() { return OK; } status_t Camera2Client::updatePreviewStream() { ATRACE_CALL(); status_t res; if (mPreviewStreamId != NO_STREAM) { // Check if stream parameters have to change uint32_t currentWidth, currentHeight; res = mDevice->getStreamInfo(mPreviewStreamId, ¤tWidth, ¤tHeight, 0); if (res != OK) { ALOGE("%s: Camera %d: Error querying preview stream info: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } if (currentWidth != (uint32_t)mParameters.previewWidth || currentHeight != (uint32_t)mParameters.previewHeight) { res = mDevice->waitUntilDrained(); if (res != OK) { ALOGE("%s: Camera %d: Error waiting for preview to drain: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = mDevice->deleteStream(mPreviewStreamId); if (res != OK) { ALOGE("%s: Camera %d: Unable to delete old output stream " "for preview: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } mPreviewStreamId = NO_STREAM; } } if (mPreviewStreamId == NO_STREAM) { res = mDevice->createStream(mPreviewWindow, mParameters.previewWidth, mParameters.previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mPreviewStreamId); if (res != OK) { ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } return OK; } status_t Camera2Client::updatePreviewRequest() { ATRACE_CALL(); status_t res; Loading @@ -1992,11 +2060,20 @@ status_t Camera2Client::updatePreviewRequest() { return res; } } // TODO: Adjust for params changes res = updateRequestCommon(mPreviewRequest); if (res != OK) { ALOGE("%s: Camera %d: Unable to update common entries of preview " "request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } return OK; } status_t Camera2Client::updateCaptureStream() { ATRACE_CALL(); status_t res; // Find out buffer size for JPEG camera_metadata_entry_t maxJpegSize = Loading Loading @@ -2025,19 +2102,8 @@ status_t Camera2Client::updateCaptureStream() { mCaptureMemory = new MemoryBase(mCaptureHeap, 0, maxJpegSize.data.i32[0]); } if (mCaptureStreamId == NO_STREAM) { // Create stream for HAL production res = mDevice->createStream(mCaptureWindow, mParameters.pictureWidth, mParameters.pictureHeight, HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0], &mCaptureStreamId); if (res != OK) { ALOGE("%s: Camera %d: Can't create output stream for capture: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } else { if (mCaptureStreamId != NO_STREAM) { // Check if stream parameters have to change uint32_t currentWidth, currentHeight; res = mDevice->getStreamInfo(mCaptureStreamId, Loading @@ -2057,11 +2123,25 @@ status_t Camera2Client::updateCaptureStream() { return res; } mCaptureStreamId = NO_STREAM; return updateCaptureStream(); } } if (mCaptureStreamId == NO_STREAM) { // Create stream for HAL production res = mDevice->createStream(mCaptureWindow, mParameters.pictureWidth, mParameters.pictureHeight, HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0], &mCaptureStreamId); if (res != OK) { ALOGE("%s: Camera %d: Can't create output stream for capture: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } return OK; } status_t Camera2Client::updateCaptureRequest() { ATRACE_CALL(); status_t res; Loading @@ -2074,10 +2154,273 @@ status_t Camera2Client::updateCaptureRequest() { return res; } } // TODO: Adjust for params changes res = updateRequestCommon(mCaptureRequest); if (res != OK) { ALOGE("%s: Camera %d: Unable to update common entries of capture " "request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = updateEntry(mCaptureRequest, ANDROID_JPEG_THUMBNAIL_SIZE, mParameters.jpegThumbSize, 2); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_THUMBNAIL_QUALITY, &mParameters.jpegThumbQuality, 1); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_QUALITY, &mParameters.jpegQuality, 1); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_ORIENTATION, &mParameters.jpegRotation, 1); if (res != OK) return res; if (mParameters.gpsEnabled) { res = updateEntry(mCaptureRequest, ANDROID_JPEG_GPS_COORDINATES, mParameters.gpsCoordinates, 3); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_GPS_TIMESTAMP, &mParameters.gpsTimestamp, 1); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_GPS_PROCESSING_METHOD, mParameters.gpsProcessingMethod.string(), mParameters.gpsProcessingMethod.size()); if (res != OK) return res; } else { res = deleteEntry(mCaptureRequest, ANDROID_JPEG_GPS_COORDINATES); if (res != OK) return res; res = deleteEntry(mCaptureRequest, ANDROID_JPEG_GPS_TIMESTAMP); if (res != OK) return res; res = deleteEntry(mCaptureRequest, ANDROID_JPEG_GPS_PROCESSING_METHOD); if (res != OK) return res; } return OK; } status_t Camera2Client::updateRequestCommon(camera_metadata_t *request) { ATRACE_CALL(); status_t res; res = updateEntry(request, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, mParameters.previewFpsRange, 2); if (res != OK) return res; uint8_t wbMode = mParameters.autoWhiteBalanceLock ? ANDROID_CONTROL_AWB_LOCKED : mParameters.wbMode; res = updateEntry(request, ANDROID_CONTROL_AWB_MODE, &wbMode, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_EFFECT_MODE, &mParameters.effectMode, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AE_ANTIBANDING_MODE, &mParameters.antibandingMode, 1); if (res != OK) return res; uint8_t controlMode = (mParameters.sceneMode == ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED) ? ANDROID_CONTROL_AUTO : ANDROID_CONTROL_USE_SCENE_MODE; res = updateEntry(request, ANDROID_CONTROL_MODE, &controlMode, 1); if (res != OK) return res; if (controlMode == ANDROID_CONTROL_USE_SCENE_MODE) { res = updateEntry(request, ANDROID_CONTROL_SCENE_MODE, &mParameters.sceneMode, 1); if (res != OK) return res; } uint8_t flashMode = ANDROID_FLASH_OFF; uint8_t aeMode; switch (mParameters.flashMode) { case Parameters::FLASH_MODE_OFF: aeMode = ANDROID_CONTROL_AE_ON; break; case Parameters::FLASH_MODE_AUTO: aeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH; break; case Parameters::FLASH_MODE_ON: aeMode = ANDROID_CONTROL_AE_ON_ALWAYS_FLASH; break; case Parameters::FLASH_MODE_TORCH: aeMode = ANDROID_CONTROL_AE_ON; flashMode = ANDROID_FLASH_TORCH; break; case Parameters::FLASH_MODE_RED_EYE: aeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE; break; default: ALOGE("%s: Camera %d: Unknown flash mode %d", __FUNCTION__, mCameraId, mParameters.flashMode); return BAD_VALUE; } if (mParameters.autoExposureLock) aeMode = ANDROID_CONTROL_AE_LOCKED; res = updateEntry(request, ANDROID_FLASH_MODE, &flashMode, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AE_MODE, &aeMode, 1); if (res != OK) return res; float focusDistance = 0; // infinity focus in diopters uint8_t focusMode; switch (mParameters.focusMode) { case Parameters::FOCUS_MODE_AUTO: case Parameters::FOCUS_MODE_MACRO: case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO: case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE: case Parameters::FOCUS_MODE_EDOF: focusMode = mParameters.focusMode; break; case Parameters::FOCUS_MODE_INFINITY: case Parameters::FOCUS_MODE_FIXED: focusMode = ANDROID_CONTROL_AF_OFF; break; default: ALOGE("%s: Camera %d: Unknown focus mode %d", __FUNCTION__, mCameraId, mParameters.focusMode); return BAD_VALUE; } res = updateEntry(request, ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AF_MODE, &focusMode, 1); if (res != OK) return res; size_t focusingAreasSize = mParameters.focusingAreas.size() * 5; int32_t *focusingAreas = new int32_t[focusingAreasSize]; for (size_t i = 0; i < focusingAreasSize; i += 5) { focusingAreas[i + 0] = mParameters.focusingAreas[i].left; focusingAreas[i + 1] = mParameters.focusingAreas[i].top; focusingAreas[i + 2] = mParameters.focusingAreas[i].right; focusingAreas[i + 3] = mParameters.focusingAreas[i].bottom; focusingAreas[i + 4] = mParameters.focusingAreas[i].weight; } res = updateEntry(request, ANDROID_CONTROL_AF_REGIONS, focusingAreas,focusingAreasSize); if (res != OK) return res; delete[] focusingAreas; res = updateEntry(request, ANDROID_CONTROL_AE_EXP_COMPENSATION, &mParameters.exposureCompensation, 1); if (res != OK) return res; size_t meteringAreasSize = mParameters.meteringAreas.size() * 5; int32_t *meteringAreas = new int32_t[meteringAreasSize]; for (size_t i = 0; i < meteringAreasSize; i += 5) { meteringAreas[i + 0] = mParameters.meteringAreas[i].left; meteringAreas[i + 1] = mParameters.meteringAreas[i].top; meteringAreas[i + 2] = mParameters.meteringAreas[i].right; meteringAreas[i + 3] = mParameters.meteringAreas[i].bottom; meteringAreas[i + 4] = mParameters.meteringAreas[i].weight; } res = updateEntry(request, ANDROID_CONTROL_AE_REGIONS, meteringAreas, meteringAreasSize); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AWB_REGIONS, meteringAreas, meteringAreasSize); if (res != OK) return res; delete[] meteringAreas; // Need to convert zoom index into a crop rectangle. The rectangle is // chosen to maximize its area on the sensor camera_metadata_entry_t maxDigitalZoom = staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM); float zoomIncrement = (maxDigitalZoom.data.f[0] - 1) / (NUM_ZOOM_STEPS-1); float zoomRatio = 1 + zoomIncrement * mParameters.zoom; camera_metadata_entry_t activePixelArraySize = staticInfo(ANDROID_SENSOR_ACTIVE_ARRAY_SIZE, 2, 2); int32_t arrayWidth = activePixelArraySize.data.i32[0]; int32_t arrayHeight = activePixelArraySize.data.i32[1]; float zoomLeft, zoomTop, zoomWidth, zoomHeight; if (mParameters.previewWidth >= mParameters.previewHeight) { zoomWidth = arrayWidth / zoomRatio; zoomHeight = zoomWidth * mParameters.previewHeight / mParameters.previewWidth; } else { zoomHeight = arrayHeight / zoomRatio; zoomWidth = zoomHeight * mParameters.previewWidth / mParameters.previewHeight; } zoomLeft = (arrayWidth - zoomWidth) / 2; zoomTop = (arrayHeight - zoomHeight) / 2; int32_t cropRegion[3] = { zoomLeft, zoomTop, zoomWidth }; res = updateEntry(request, ANDROID_SCALER_CROP_REGION, cropRegion, 3); if (res != OK) return res; // TODO: Decide how to map recordingHint, or whether just to ignore it uint8_t vstabMode = mParameters.videoStabilization ? ANDROID_CONTROL_VIDEO_STABILIZATION_ON : ANDROID_CONTROL_VIDEO_STABILIZATION_OFF; res = updateEntry(request, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &vstabMode, 1); if (res != OK) return res; return OK; } status_t Camera2Client::updateEntry(camera_metadata_t *buffer, uint32_t tag, const void *data, size_t data_count) { camera_metadata_entry_t entry; status_t res; res = find_camera_metadata_entry(buffer, tag, &entry); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(buffer, tag, data, data_count); } else if (res == OK) { res = update_camera_metadata_entry(buffer, entry.index, data, data_count, NULL); } if (res != OK) { ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); } return res; } status_t Camera2Client::deleteEntry(camera_metadata_t *buffer, uint32_t tag) { camera_metadata_entry_t entry; status_t res; res = find_camera_metadata_entry(buffer, tag, &entry); if (res == NAME_NOT_FOUND) { return OK; } else if (res != OK) { ALOGE("%s: Error looking for entry %s.%s (%x): %s %d", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); return res; } res = delete_camera_metadata_entry(buffer, entry.index); if (res != OK) { ALOGE("%s: Error deleting entry %s.%s (%x): %s %d", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); } return res; } int Camera2Client::formatStringToEnum(const char *format) { return !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422SP) ? Loading services/camera/libcameraservice/Camera2Client.h +21 −4 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ private: // The following must be called with mICamaeraLock already locked status_t setPreviewWindowLocked(const sp<IBinder>& binder, const sp<ANativeWindow>& window); sp<ANativeWindow> window); void stopPreviewLocked(); status_t startPreviewLocked(); Loading Loading @@ -192,6 +192,8 @@ private: static const int NO_STREAM = -1; sp<IBinder> mPreviewSurface; sp<ANativeWindow> mPreviewWindow; int mPreviewStreamId; camera_metadata_t *mPreviewRequest; Loading Loading @@ -219,14 +221,29 @@ private: // old API parameter map. status_t buildDefaultParameters(); // Update preview request based on mParams // Update preview request based on mParameters status_t updatePreviewRequest(); // Update preview stream based on mParameters status_t updatePreviewStream(); // Update capture request based on mParams // Update capture request based on mParameters status_t updateCaptureRequest(); // Update capture stream based on mParams // Update capture stream based on mParameters status_t updateCaptureStream(); // Update parameters all requests use, based on mParameters status_t updateRequestCommon(camera_metadata_t *request); // Update specific metadata entry with new values. Adds entry if it does not // exist, which will invalidate sorting static status_t updateEntry(camera_metadata_t *buffer, uint32_t tag, const void *data, size_t data_count); // Remove metadata entry. Will invalidate sorting. If entry does not exist, // does nothing. static status_t deleteEntry(camera_metadata_t *buffer, uint32_t tag); // Convert camera1 preview format string to camera2 enum static int formatStringToEnum(const char *format); static const char *formatEnumToString(int format); Loading Loading
services/camera/libcameraservice/Camera2Client.cpp +405 −62 Original line number Diff line number Diff line Loading @@ -394,7 +394,7 @@ status_t Camera2Client::setPreviewTexture( } status_t Camera2Client::setPreviewWindowLocked(const sp<IBinder>& binder, const sp<ANativeWindow>& window) { sp<ANativeWindow> window) { ATRACE_CALL(); status_t res; Loading @@ -402,23 +402,24 @@ status_t Camera2Client::setPreviewWindowLocked(const sp<IBinder>& binder, return NO_ERROR; } // TODO: Should wait until HAL has no remaining requests if (mPreviewStreamId != NO_STREAM) { res = mDevice->deleteStream(mPreviewStreamId); res = mDevice->waitUntilDrained(); if (res != OK) { ALOGE("%s: Error waiting for preview to drain: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } } res = mDevice->createStream(window, mParameters.previewWidth, mParameters.previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mPreviewStreamId); res = mDevice->deleteStream(mPreviewStreamId); if (res != OK) { ALOGE("%s: Unable to delete old preview stream: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } mPreviewStreamId = NO_STREAM; } mPreviewSurface = binder; mPreviewWindow = window; if (mState == WAITING_FOR_PREVIEW_WINDOW) { return startPreviewLocked(); Loading Loading @@ -447,34 +448,40 @@ status_t Camera2Client::startPreviewLocked() { return INVALID_OPERATION; } if (mPreviewStreamId == NO_STREAM) { if (mPreviewWindow == 0) { mState = WAITING_FOR_PREVIEW_WINDOW; return OK; } mState = STOPPED; if (mPreviewRequest == NULL) { updatePreviewRequest(); res = updatePreviewStream(); if (res != OK) { ALOGE("%s: Camera %d: Unable to update preview stream: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } uint8_t outputStream = mPreviewStreamId; camera_metadata_entry_t outputStreams; res = find_camera_metadata_entry(mPreviewRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreams); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(mPreviewRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &outputStream, 1); } else if (res == OK) { res = update_camera_metadata_entry(mPreviewRequest, outputStreams.index, &outputStream, 1, NULL); if (mPreviewRequest == NULL) { res = updatePreviewRequest(); if (res != OK) { ALOGE("%s: Camera %d: Unable to create preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } res = updateEntry(mPreviewRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &mPreviewStreamId, 1); if (res != OK) { ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mState = STOPPED; return res; } res = sort_camera_metadata(mPreviewRequest); if (res != OK) { ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } Loading @@ -483,7 +490,6 @@ status_t Camera2Client::startPreviewLocked() { ALOGE("%s: Camera %d: Unable to set preview request to start preview: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mState = STOPPED; return res; } mState = PREVIEW; Loading Loading @@ -596,41 +602,37 @@ status_t Camera2Client::takePicture(int msgType) { res = updateCaptureStream(); if (res != OK) { ALOGE("%s: Can't set up still image stream: %s (%d)", __FUNCTION__, strerror(-res), res); ALOGE("%s: Camera %d: Can't set up still image stream: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } if (mCaptureRequest == NULL) { res = updateCaptureRequest(); if (res != OK) { ALOGE("%s: Can't set up still image capture request: %s (%d)", __FUNCTION__, strerror(-res), res); ALOGE("%s: Camera %d: Can't create still image capture request: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } // TODO: For video snapshot, need 3 streams here // TODO: For video snapshot, will need 3 streams here camera_metadata_entry_t outputStreams; uint8_t streamIds[2] = { mPreviewStreamId, mCaptureStreamId }; res = find_camera_metadata_entry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreams); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS, streamIds, 2); } else if (res == OK) { res = update_camera_metadata_entry(mCaptureRequest, outputStreams.index, streamIds, 2, NULL); } res = updateEntry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS, &streamIds, 2); if (res != OK) { ALOGE("%s: Camera %d: Unable to set up still image capture request: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = sort_camera_metadata(mCaptureRequest); if (res != OK) { ALOGE("%s: Camera %d: Unable to sort capture request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } camera_metadata_t *captureCopy = clone_camera_metadata(mCaptureRequest); if (captureCopy == NULL) { Loading Loading @@ -1168,8 +1170,27 @@ status_t Camera2Client::setParameters(const String8& params) { mParameters.recordingHint = recordingHint; mParameters.videoStabilization = videoStabilization; updatePreviewRequest(); updateCaptureRequest(); res = updatePreviewRequest(); if (res != OK) { ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = updateCaptureRequest(); if (res != OK) { ALOGE("%s: Camera %d: Unable to update capture request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } if (mState == PREVIEW) { res = mDevice->setStreamingRequest(mPreviewRequest); if (res != OK) { ALOGE("%s: Camera %d: Error streaming new preview request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } return OK; } Loading Loading @@ -1980,6 +2001,53 @@ status_t Camera2Client::buildDefaultParameters() { return OK; } status_t Camera2Client::updatePreviewStream() { ATRACE_CALL(); status_t res; if (mPreviewStreamId != NO_STREAM) { // Check if stream parameters have to change uint32_t currentWidth, currentHeight; res = mDevice->getStreamInfo(mPreviewStreamId, ¤tWidth, ¤tHeight, 0); if (res != OK) { ALOGE("%s: Camera %d: Error querying preview stream info: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } if (currentWidth != (uint32_t)mParameters.previewWidth || currentHeight != (uint32_t)mParameters.previewHeight) { res = mDevice->waitUntilDrained(); if (res != OK) { ALOGE("%s: Camera %d: Error waiting for preview to drain: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = mDevice->deleteStream(mPreviewStreamId); if (res != OK) { ALOGE("%s: Camera %d: Unable to delete old output stream " "for preview: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } mPreviewStreamId = NO_STREAM; } } if (mPreviewStreamId == NO_STREAM) { res = mDevice->createStream(mPreviewWindow, mParameters.previewWidth, mParameters.previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mPreviewStreamId); if (res != OK) { ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } return OK; } status_t Camera2Client::updatePreviewRequest() { ATRACE_CALL(); status_t res; Loading @@ -1992,11 +2060,20 @@ status_t Camera2Client::updatePreviewRequest() { return res; } } // TODO: Adjust for params changes res = updateRequestCommon(mPreviewRequest); if (res != OK) { ALOGE("%s: Camera %d: Unable to update common entries of preview " "request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } return OK; } status_t Camera2Client::updateCaptureStream() { ATRACE_CALL(); status_t res; // Find out buffer size for JPEG camera_metadata_entry_t maxJpegSize = Loading Loading @@ -2025,19 +2102,8 @@ status_t Camera2Client::updateCaptureStream() { mCaptureMemory = new MemoryBase(mCaptureHeap, 0, maxJpegSize.data.i32[0]); } if (mCaptureStreamId == NO_STREAM) { // Create stream for HAL production res = mDevice->createStream(mCaptureWindow, mParameters.pictureWidth, mParameters.pictureHeight, HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0], &mCaptureStreamId); if (res != OK) { ALOGE("%s: Camera %d: Can't create output stream for capture: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } else { if (mCaptureStreamId != NO_STREAM) { // Check if stream parameters have to change uint32_t currentWidth, currentHeight; res = mDevice->getStreamInfo(mCaptureStreamId, Loading @@ -2057,11 +2123,25 @@ status_t Camera2Client::updateCaptureStream() { return res; } mCaptureStreamId = NO_STREAM; return updateCaptureStream(); } } if (mCaptureStreamId == NO_STREAM) { // Create stream for HAL production res = mDevice->createStream(mCaptureWindow, mParameters.pictureWidth, mParameters.pictureHeight, HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0], &mCaptureStreamId); if (res != OK) { ALOGE("%s: Camera %d: Can't create output stream for capture: " "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } } return OK; } status_t Camera2Client::updateCaptureRequest() { ATRACE_CALL(); status_t res; Loading @@ -2074,10 +2154,273 @@ status_t Camera2Client::updateCaptureRequest() { return res; } } // TODO: Adjust for params changes res = updateRequestCommon(mCaptureRequest); if (res != OK) { ALOGE("%s: Camera %d: Unable to update common entries of capture " "request: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); return res; } res = updateEntry(mCaptureRequest, ANDROID_JPEG_THUMBNAIL_SIZE, mParameters.jpegThumbSize, 2); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_THUMBNAIL_QUALITY, &mParameters.jpegThumbQuality, 1); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_QUALITY, &mParameters.jpegQuality, 1); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_ORIENTATION, &mParameters.jpegRotation, 1); if (res != OK) return res; if (mParameters.gpsEnabled) { res = updateEntry(mCaptureRequest, ANDROID_JPEG_GPS_COORDINATES, mParameters.gpsCoordinates, 3); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_GPS_TIMESTAMP, &mParameters.gpsTimestamp, 1); if (res != OK) return res; res = updateEntry(mCaptureRequest, ANDROID_JPEG_GPS_PROCESSING_METHOD, mParameters.gpsProcessingMethod.string(), mParameters.gpsProcessingMethod.size()); if (res != OK) return res; } else { res = deleteEntry(mCaptureRequest, ANDROID_JPEG_GPS_COORDINATES); if (res != OK) return res; res = deleteEntry(mCaptureRequest, ANDROID_JPEG_GPS_TIMESTAMP); if (res != OK) return res; res = deleteEntry(mCaptureRequest, ANDROID_JPEG_GPS_PROCESSING_METHOD); if (res != OK) return res; } return OK; } status_t Camera2Client::updateRequestCommon(camera_metadata_t *request) { ATRACE_CALL(); status_t res; res = updateEntry(request, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, mParameters.previewFpsRange, 2); if (res != OK) return res; uint8_t wbMode = mParameters.autoWhiteBalanceLock ? ANDROID_CONTROL_AWB_LOCKED : mParameters.wbMode; res = updateEntry(request, ANDROID_CONTROL_AWB_MODE, &wbMode, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_EFFECT_MODE, &mParameters.effectMode, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AE_ANTIBANDING_MODE, &mParameters.antibandingMode, 1); if (res != OK) return res; uint8_t controlMode = (mParameters.sceneMode == ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED) ? ANDROID_CONTROL_AUTO : ANDROID_CONTROL_USE_SCENE_MODE; res = updateEntry(request, ANDROID_CONTROL_MODE, &controlMode, 1); if (res != OK) return res; if (controlMode == ANDROID_CONTROL_USE_SCENE_MODE) { res = updateEntry(request, ANDROID_CONTROL_SCENE_MODE, &mParameters.sceneMode, 1); if (res != OK) return res; } uint8_t flashMode = ANDROID_FLASH_OFF; uint8_t aeMode; switch (mParameters.flashMode) { case Parameters::FLASH_MODE_OFF: aeMode = ANDROID_CONTROL_AE_ON; break; case Parameters::FLASH_MODE_AUTO: aeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH; break; case Parameters::FLASH_MODE_ON: aeMode = ANDROID_CONTROL_AE_ON_ALWAYS_FLASH; break; case Parameters::FLASH_MODE_TORCH: aeMode = ANDROID_CONTROL_AE_ON; flashMode = ANDROID_FLASH_TORCH; break; case Parameters::FLASH_MODE_RED_EYE: aeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE; break; default: ALOGE("%s: Camera %d: Unknown flash mode %d", __FUNCTION__, mCameraId, mParameters.flashMode); return BAD_VALUE; } if (mParameters.autoExposureLock) aeMode = ANDROID_CONTROL_AE_LOCKED; res = updateEntry(request, ANDROID_FLASH_MODE, &flashMode, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AE_MODE, &aeMode, 1); if (res != OK) return res; float focusDistance = 0; // infinity focus in diopters uint8_t focusMode; switch (mParameters.focusMode) { case Parameters::FOCUS_MODE_AUTO: case Parameters::FOCUS_MODE_MACRO: case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO: case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE: case Parameters::FOCUS_MODE_EDOF: focusMode = mParameters.focusMode; break; case Parameters::FOCUS_MODE_INFINITY: case Parameters::FOCUS_MODE_FIXED: focusMode = ANDROID_CONTROL_AF_OFF; break; default: ALOGE("%s: Camera %d: Unknown focus mode %d", __FUNCTION__, mCameraId, mParameters.focusMode); return BAD_VALUE; } res = updateEntry(request, ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AF_MODE, &focusMode, 1); if (res != OK) return res; size_t focusingAreasSize = mParameters.focusingAreas.size() * 5; int32_t *focusingAreas = new int32_t[focusingAreasSize]; for (size_t i = 0; i < focusingAreasSize; i += 5) { focusingAreas[i + 0] = mParameters.focusingAreas[i].left; focusingAreas[i + 1] = mParameters.focusingAreas[i].top; focusingAreas[i + 2] = mParameters.focusingAreas[i].right; focusingAreas[i + 3] = mParameters.focusingAreas[i].bottom; focusingAreas[i + 4] = mParameters.focusingAreas[i].weight; } res = updateEntry(request, ANDROID_CONTROL_AF_REGIONS, focusingAreas,focusingAreasSize); if (res != OK) return res; delete[] focusingAreas; res = updateEntry(request, ANDROID_CONTROL_AE_EXP_COMPENSATION, &mParameters.exposureCompensation, 1); if (res != OK) return res; size_t meteringAreasSize = mParameters.meteringAreas.size() * 5; int32_t *meteringAreas = new int32_t[meteringAreasSize]; for (size_t i = 0; i < meteringAreasSize; i += 5) { meteringAreas[i + 0] = mParameters.meteringAreas[i].left; meteringAreas[i + 1] = mParameters.meteringAreas[i].top; meteringAreas[i + 2] = mParameters.meteringAreas[i].right; meteringAreas[i + 3] = mParameters.meteringAreas[i].bottom; meteringAreas[i + 4] = mParameters.meteringAreas[i].weight; } res = updateEntry(request, ANDROID_CONTROL_AE_REGIONS, meteringAreas, meteringAreasSize); if (res != OK) return res; res = updateEntry(request, ANDROID_CONTROL_AWB_REGIONS, meteringAreas, meteringAreasSize); if (res != OK) return res; delete[] meteringAreas; // Need to convert zoom index into a crop rectangle. The rectangle is // chosen to maximize its area on the sensor camera_metadata_entry_t maxDigitalZoom = staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM); float zoomIncrement = (maxDigitalZoom.data.f[0] - 1) / (NUM_ZOOM_STEPS-1); float zoomRatio = 1 + zoomIncrement * mParameters.zoom; camera_metadata_entry_t activePixelArraySize = staticInfo(ANDROID_SENSOR_ACTIVE_ARRAY_SIZE, 2, 2); int32_t arrayWidth = activePixelArraySize.data.i32[0]; int32_t arrayHeight = activePixelArraySize.data.i32[1]; float zoomLeft, zoomTop, zoomWidth, zoomHeight; if (mParameters.previewWidth >= mParameters.previewHeight) { zoomWidth = arrayWidth / zoomRatio; zoomHeight = zoomWidth * mParameters.previewHeight / mParameters.previewWidth; } else { zoomHeight = arrayHeight / zoomRatio; zoomWidth = zoomHeight * mParameters.previewWidth / mParameters.previewHeight; } zoomLeft = (arrayWidth - zoomWidth) / 2; zoomTop = (arrayHeight - zoomHeight) / 2; int32_t cropRegion[3] = { zoomLeft, zoomTop, zoomWidth }; res = updateEntry(request, ANDROID_SCALER_CROP_REGION, cropRegion, 3); if (res != OK) return res; // TODO: Decide how to map recordingHint, or whether just to ignore it uint8_t vstabMode = mParameters.videoStabilization ? ANDROID_CONTROL_VIDEO_STABILIZATION_ON : ANDROID_CONTROL_VIDEO_STABILIZATION_OFF; res = updateEntry(request, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &vstabMode, 1); if (res != OK) return res; return OK; } status_t Camera2Client::updateEntry(camera_metadata_t *buffer, uint32_t tag, const void *data, size_t data_count) { camera_metadata_entry_t entry; status_t res; res = find_camera_metadata_entry(buffer, tag, &entry); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(buffer, tag, data, data_count); } else if (res == OK) { res = update_camera_metadata_entry(buffer, entry.index, data, data_count, NULL); } if (res != OK) { ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); } return res; } status_t Camera2Client::deleteEntry(camera_metadata_t *buffer, uint32_t tag) { camera_metadata_entry_t entry; status_t res; res = find_camera_metadata_entry(buffer, tag, &entry); if (res == NAME_NOT_FOUND) { return OK; } else if (res != OK) { ALOGE("%s: Error looking for entry %s.%s (%x): %s %d", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); return res; } res = delete_camera_metadata_entry(buffer, entry.index); if (res != OK) { ALOGE("%s: Error deleting entry %s.%s (%x): %s %d", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); } return res; } int Camera2Client::formatStringToEnum(const char *format) { return !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422SP) ? Loading
services/camera/libcameraservice/Camera2Client.h +21 −4 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ private: // The following must be called with mICamaeraLock already locked status_t setPreviewWindowLocked(const sp<IBinder>& binder, const sp<ANativeWindow>& window); sp<ANativeWindow> window); void stopPreviewLocked(); status_t startPreviewLocked(); Loading Loading @@ -192,6 +192,8 @@ private: static const int NO_STREAM = -1; sp<IBinder> mPreviewSurface; sp<ANativeWindow> mPreviewWindow; int mPreviewStreamId; camera_metadata_t *mPreviewRequest; Loading Loading @@ -219,14 +221,29 @@ private: // old API parameter map. status_t buildDefaultParameters(); // Update preview request based on mParams // Update preview request based on mParameters status_t updatePreviewRequest(); // Update preview stream based on mParameters status_t updatePreviewStream(); // Update capture request based on mParams // Update capture request based on mParameters status_t updateCaptureRequest(); // Update capture stream based on mParams // Update capture stream based on mParameters status_t updateCaptureStream(); // Update parameters all requests use, based on mParameters status_t updateRequestCommon(camera_metadata_t *request); // Update specific metadata entry with new values. Adds entry if it does not // exist, which will invalidate sorting static status_t updateEntry(camera_metadata_t *buffer, uint32_t tag, const void *data, size_t data_count); // Remove metadata entry. Will invalidate sorting. If entry does not exist, // does nothing. static status_t deleteEntry(camera_metadata_t *buffer, uint32_t tag); // Convert camera1 preview format string to camera2 enum static int formatStringToEnum(const char *format); static const char *formatEnumToString(int format); Loading