Camera service: Minimally functional preview for camera 2 devices.
- Camera app starts up
- Basic preview operation with defaults
- Shutdown sequence is very minimal
Bug: 6243944
Change-Id: I67673b7c1fc08956d218d99f9171e74a7a82bf07
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index d0a84a5..9825af7 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -57,7 +57,10 @@
int clientPid):
Client(cameraService, cameraClient,
cameraId, cameraFacing, clientPid),
- mParams(NULL)
+ mState(NOT_INITIALIZED),
+ mParams(NULL),
+ mPreviewStreamId(NO_PREVIEW_STREAM),
+ mPreviewRequest(NULL)
{
ALOG1_ENTRY;
@@ -90,6 +93,8 @@
mParams->dump();
}
+ mState = STOPPED;
+
ALOG1_EXIT;
return OK;
}
@@ -118,7 +123,12 @@
if (mDevice == 0) return;
- mDevice->setStreamingRequest(NULL);
+ stopPreview();
+
+ if (mPreviewStreamId != NO_PREVIEW_STREAM) {
+ mDevice->deleteStream(mPreviewStreamId);
+ mPreviewStreamId = NO_PREVIEW_STREAM;
+ }
CameraService::Client::disconnect();
}
@@ -135,12 +145,67 @@
return BAD_VALUE;
}
-status_t Camera2Client::setPreviewDisplay(const sp<Surface>& surface) {
- return BAD_VALUE;
+status_t Camera2Client::setPreviewDisplay(
+ const sp<Surface>& surface) {
+ ALOG1_ENTRY;
+ if (mState == PREVIEW) return INVALID_OPERATION;
+
+ sp<IBinder> binder;
+ sp<ANativeWindow> window;
+ if (surface != 0) {
+ binder = surface->asBinder();
+ window = surface;
+ }
+
+ return setPreviewWindow(binder,window);
}
-status_t Camera2Client::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) {
- return BAD_VALUE;
+status_t Camera2Client::setPreviewTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) {
+ ALOG1_ENTRY;
+ if (mState == PREVIEW) return INVALID_OPERATION;
+
+ sp<IBinder> binder;
+ sp<ANativeWindow> window;
+ if (surfaceTexture != 0) {
+ binder = surfaceTexture->asBinder();
+ window = new SurfaceTextureClient(surfaceTexture);
+ }
+ return setPreviewWindow(binder, window);
+}
+
+status_t Camera2Client::setPreviewWindow(const sp<IBinder>& binder,
+ const sp<ANativeWindow>& window) {
+ ALOG1_ENTRY;
+ status_t res;
+
+ if (binder == mPreviewSurface) {
+ return NO_ERROR;
+ }
+
+ if (mPreviewStreamId != NO_PREVIEW_STREAM) {
+ res = mDevice->deleteStream(mPreviewStreamId);
+ if (res != OK) {
+ return res;
+ }
+ }
+
+ int previewWidth, previewHeight;
+ mParams->getPreviewSize(&previewWidth, &previewHeight);
+
+ res = mDevice->createStream(window,
+ previewWidth, previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE,
+ &mPreviewStreamId);
+ if (res != OK) {
+ return res;
+ }
+
+ if (mState == WAITING_FOR_PREVIEW_WINDOW) {
+ return startPreview();
+ }
+
+ ALOG1_EXIT;
+ return OK;
}
void Camera2Client::setPreviewCallbackFlag(int flag) {
@@ -148,15 +213,63 @@
}
status_t Camera2Client::startPreview() {
- return BAD_VALUE;
+ ALOG1_ENTRY;
+ status_t res;
+ if (mState == PREVIEW) return INVALID_OPERATION;
+
+ if (mPreviewStreamId == NO_PREVIEW_STREAM) {
+ mState = WAITING_FOR_PREVIEW_WINDOW;
+ return OK;
+ }
+
+ if (mPreviewRequest == NULL) {
+ updatePreviewRequest();
+ }
+
+ 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 (res != OK) {
+ ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ mState = STOPPED;
+ return res;
+ }
+
+ res = mDevice->setStreamingRequest(mPreviewRequest);
+ if (res != OK) {
+ 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;
+
+ return OK;
}
void Camera2Client::stopPreview() {
+ ALOG1_ENTRY;
+ if (mState != PREVIEW) return;
+ mDevice->setStreamingRequest(NULL);
+ mState = STOPPED;
}
bool Camera2Client::previewEnabled() {
- return false;
+ return mState == PREVIEW;
}
status_t Camera2Client::storeMetaDataInBuffers(bool enabled) {
@@ -179,11 +292,11 @@
}
status_t Camera2Client::autoFocus() {
- return BAD_VALUE;
+ return OK;
}
status_t Camera2Client::cancelAutoFocus() {
- return BAD_VALUE;
+ return OK;
}
status_t Camera2Client::takePicture(int msgType) {
@@ -191,7 +304,7 @@
}
status_t Camera2Client::setParameters(const String8& params) {
- return BAD_VALUE;
+ return OK;
}
String8 Camera2Client::getParameters() const {
@@ -199,7 +312,7 @@
}
status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
- return BAD_VALUE;
+ return OK;
}
// private methods
@@ -781,7 +894,7 @@
"(0,0,0,0,0)");
mParams->set(CameraParameters::KEY_ZOOM, 0);
- mParams->set(CameraParameters::KEY_MAX_ZOOM, kNumZoomSteps - 1);
+ mParams->set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
camera_metadata_entry_t maxDigitalZoom;
res = find_camera_metadata_entry(mDevice->info(),
@@ -792,9 +905,9 @@
String8 zoomRatios;
float zoom = 1.f;
float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
- (kNumZoomSteps-1);
+ (NUM_ZOOM_STEPS-1);
bool addComma = false;
- for (size_t i=0; i < kNumZoomSteps; i++) {
+ for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
if (addComma) zoomRatios += ",";
addComma = true;
zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
@@ -846,4 +959,21 @@
return OK;
}
+status_t Camera2Client::updatePreviewRequest() {
+ ALOG1_ENTRY
+ status_t res;
+ if (mPreviewRequest == NULL) {
+ res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+ &mPreviewRequest);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to create default preview request: "
+ "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+ return res;
+ }
+ }
+ // TODO: Adjust for mParams changes
+ ALOG1_EXIT
+ return OK;
+}
+
} // namespace android