Allow setPreviewDisplay after startPreview.

This commit is contained in:
Wu-cheng Li
2009-06-23 23:37:36 +08:00
parent 33a7030f56
commit b8a10fe456
5 changed files with 108 additions and 60 deletions

View File

@ -410,11 +410,14 @@ void CameraService::Client::disconnect()
// pass the buffered ISurface to the camera service // pass the buffered ISurface to the camera service
status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
{ {
LOGD("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); LOGD("setPreviewDisplay(%p) (pid %d)",
((surface == NULL) ? NULL : surface.get()), getCallingPid());
Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock);
status_t result = checkPid(); status_t result = checkPid();
if (result != NO_ERROR) return result; if (result != NO_ERROR) return result;
Mutex::Autolock surfaceLock(mSurfaceLock); Mutex::Autolock surfaceLock(mSurfaceLock);
result = NO_ERROR;
// asBinder() is safe on NULL (returns NULL) // asBinder() is safe on NULL (returns NULL)
if (surface->asBinder() != mSurface->asBinder()) { if (surface->asBinder() != mSurface->asBinder()) {
if (mSurface != 0 && !mUseOverlay) { if (mSurface != 0 && !mUseOverlay) {
@ -422,8 +425,17 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
mSurface->unregisterBuffers(); mSurface->unregisterBuffers();
} }
mSurface = surface; mSurface = surface;
// If preview has been already started, set overlay or register preview
// buffers now.
if (mHardware->previewEnabled()) {
if (mUseOverlay) {
result = setOverlay();
} else if (mSurface != 0) {
result = registerPreviewBuffers();
}
}
} }
return NO_ERROR; return result;
} }
// set the preview callback flag to affect how the received frames from // set the preview callback flag to affect how the received frames from
@ -436,7 +448,7 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
mPreviewCallbackFlag = callback_flag; mPreviewCallbackFlag = callback_flag;
} }
// start preview mode, must call setPreviewDisplay first // start preview mode
status_t CameraService::Client::startCameraMode(camera_mode mode) status_t CameraService::Client::startCameraMode(camera_mode mode)
{ {
int callingPid = getCallingPid(); int callingPid = getCallingPid();
@ -456,16 +468,18 @@ status_t CameraService::Client::startCameraMode(camera_mode mode)
return INVALID_OPERATION; return INVALID_OPERATION;
} }
if (mSurface == 0) {
LOGE("setPreviewDisplay must be called before startCameraMode!");
return INVALID_OPERATION;
}
switch(mode) { switch(mode) {
case CAMERA_RECORDING_MODE: case CAMERA_RECORDING_MODE:
if (mSurface == 0) {
LOGE("setPreviewDisplay must be called before startRecordingMode.");
return INVALID_OPERATION;
}
return startRecordingMode(); return startRecordingMode();
default: // CAMERA_PREVIEW_MODE default: // CAMERA_PREVIEW_MODE
if (mSurface == 0) {
LOGD("mSurface is not set yet.");
}
return startPreviewMode(); return startPreviewMode();
} }
} }
@ -498,6 +512,62 @@ status_t CameraService::Client::startRecordingMode()
return ret; return ret;
} }
status_t CameraService::Client::setOverlay()
{
LOGD("setOverlay");
int w, h;
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
const char *format = params.getPreviewFormat();
int fmt;
if (!strcmp(format, "yuv422i"))
fmt = OVERLAY_FORMAT_YCbCr_422_I;
else if (!strcmp(format, "rgb565"))
fmt = OVERLAY_FORMAT_RGB_565;
else {
LOGE("Invalid preview format for overlays");
return -EINVAL;
}
status_t ret = NO_ERROR;
if (mSurface != 0) {
sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
ret = mHardware->setOverlay(new Overlay(ref));
} else {
ret = mHardware->setOverlay(NULL);
}
if (ret != NO_ERROR) {
LOGE("mHardware->setOverlay() failed with status %d\n", ret);
}
return ret;
}
status_t CameraService::Client::registerPreviewBuffers()
{
int w, h;
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
uint32_t transform = 0;
if (params.getOrientation() ==
CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
LOGV("portrait mode");
transform = ISurface::BufferHeap::ROT_90;
}
ISurface::BufferHeap buffers(w, h, w, h,
PIXEL_FORMAT_YCbCr_420_SP,
transform,
0,
mHardware->getPreviewHeap());
status_t ret = mSurface->registerBuffers(buffers);
if (ret != NO_ERROR) {
LOGE("registerBuffers failed with status %d", ret);
}
return ret;
}
status_t CameraService::Client::startPreviewMode() status_t CameraService::Client::startPreviewMode()
{ {
LOGD("startPreviewMode (pid %d)", getCallingPid()); LOGD("startPreviewMode (pid %d)", getCallingPid());
@ -511,55 +581,24 @@ status_t CameraService::Client::startPreviewMode()
#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
debug_frame_cnt = 0; debug_frame_cnt = 0;
#endif #endif
status_t ret = UNKNOWN_ERROR; status_t ret = NO_ERROR;
int w, h;
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
if (mUseOverlay) { if (mUseOverlay) {
const char *format = params.getPreviewFormat(); // If preview display has been set, set overlay now.
int fmt; if (mSurface != 0) {
LOGD("Use Overlays"); ret = setOverlay();
if (!strcmp(format, "yuv422i"))
fmt = OVERLAY_FORMAT_YCbCr_422_I;
else if (!strcmp(format, "rgb565"))
fmt = OVERLAY_FORMAT_RGB_565;
else {
LOGE("Invalid preview format for overlays");
return -EINVAL;
}
sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
ret = mHardware->setOverlay(new Overlay(ref));
if (ret != NO_ERROR) {
LOGE("mHardware->setOverlay() failed with status %d\n", ret);
return ret;
} }
if (ret != NO_ERROR) return ret;
ret = mHardware->startPreview(NULL, mCameraService.get()); ret = mHardware->startPreview(NULL, mCameraService.get());
if (ret != NO_ERROR)
LOGE("mHardware->startPreview() failed with status %d\n", ret);
} else { } else {
ret = mHardware->startPreview(previewCallback, ret = mHardware->startPreview(previewCallback,
mCameraService.get()); mCameraService.get());
if (ret == NO_ERROR) { if (ret != NO_ERROR) return ret;
// If preview display has been set, register preview buffers now.
mSurface->unregisterBuffers(); if (mSurface != 0) {
// Unregister here because the surface registered with raw heap.
uint32_t transform = 0; mSurface->unregisterBuffers();
if (params.getOrientation() == ret = registerPreviewBuffers();
CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
LOGV("portrait mode");
transform = ISurface::BufferHeap::ROT_90;
}
ISurface::BufferHeap buffers(w, h, w, h,
PIXEL_FORMAT_YCbCr_420_SP,
transform,
0,
mHardware->getPreviewHeap());
mSurface->registerBuffers(buffers);
} else {
LOGE("mHardware->startPreview() failed with status %d", ret);
} }
} }
return ret; return ret;

View File

@ -157,6 +157,8 @@ private:
status_t startCameraMode(camera_mode mode); status_t startCameraMode(camera_mode mode);
status_t startPreviewMode(); status_t startPreviewMode();
status_t startRecordingMode(); status_t startRecordingMode();
status_t setOverlay();
status_t registerPreviewBuffers();
// Ensures atomicity among the public methods // Ensures atomicity among the public methods
mutable Mutex mLock; mutable Mutex mLock;

View File

@ -155,7 +155,11 @@ public class Camera {
* @throws IOException if the method fails. * @throws IOException if the method fails.
*/ */
public final void setPreviewDisplay(SurfaceHolder holder) throws IOException { public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
setPreviewDisplay(holder.getSurface()); if (holder != null) {
setPreviewDisplay(holder.getSurface());
} else {
setPreviewDisplay((Surface)null);
}
} }
private native final void setPreviewDisplay(Surface surface); private native final void setPreviewDisplay(Surface surface);

View File

@ -262,7 +262,10 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz,
sp<Camera> camera = get_native_camera(env, thiz, NULL); sp<Camera> camera = get_native_camera(env, thiz, NULL);
if (camera == 0) return; if (camera == 0) return;
sp<Surface> surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); sp<Surface> surface = NULL;
if (jSurface != NULL) {
surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
}
if (camera->setPreviewDisplay(surface) != NO_ERROR) { if (camera->setPreviewDisplay(surface) != NO_ERROR) {
jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
} }

View File

@ -149,21 +149,21 @@ status_t Camera::unlock()
status_t Camera::setPreviewDisplay(const sp<Surface>& surface) status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
{ {
LOGV("setPreviewDisplay"); LOGV("setPreviewDisplay");
if (surface == 0) {
LOGE("app passed NULL surface");
return NO_INIT;
}
sp <ICamera> c = mCamera; sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT; if (c == 0) return NO_INIT;
return c->setPreviewDisplay(surface->getISurface()); if (surface != 0) {
return c->setPreviewDisplay(surface->getISurface());
} else {
LOGD("app passed NULL surface");
return c->setPreviewDisplay(0);
}
} }
status_t Camera::setPreviewDisplay(const sp<ISurface>& surface) status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
{ {
LOGV("setPreviewDisplay"); LOGV("setPreviewDisplay");
if (surface == 0) { if (surface == 0) {
LOGE("app passed NULL surface"); LOGD("app passed NULL surface");
return NO_INIT;
} }
sp <ICamera> c = mCamera; sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT; if (c == 0) return NO_INIT;
@ -171,7 +171,7 @@ status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
} }
// start preview mode, must call setPreviewDisplay first // start preview mode
status_t Camera::startPreview() status_t Camera::startPreview()
{ {
LOGV("startPreview"); LOGV("startPreview");