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,28 +512,15 @@ status_t CameraService::Client::startRecordingMode()
return ret; return ret;
} }
status_t CameraService::Client::startPreviewMode() status_t CameraService::Client::setOverlay()
{ {
LOGD("startPreviewMode (pid %d)", getCallingPid()); LOGD("setOverlay");
// if preview has been enabled, nothing needs to be done
if (mHardware->previewEnabled()) {
return NO_ERROR;
}
// start preview mode
#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
debug_frame_cnt = 0;
#endif
status_t ret = UNKNOWN_ERROR;
int w, h; int w, h;
CameraParameters params(mHardware->getParameters()); CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h); params.getPreviewSize(&w, &h);
if (mUseOverlay) {
const char *format = params.getPreviewFormat(); const char *format = params.getPreviewFormat();
int fmt; int fmt;
LOGD("Use Overlays");
if (!strcmp(format, "yuv422i")) if (!strcmp(format, "yuv422i"))
fmt = OVERLAY_FORMAT_YCbCr_422_I; fmt = OVERLAY_FORMAT_YCbCr_422_I;
else if (!strcmp(format, "rgb565")) else if (!strcmp(format, "rgb565"))
@ -528,22 +529,25 @@ status_t CameraService::Client::startPreviewMode()
LOGE("Invalid preview format for overlays"); LOGE("Invalid preview format for overlays");
return -EINVAL; return -EINVAL;
} }
status_t ret = NO_ERROR;
if (mSurface != 0) {
sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt); sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
ret = mHardware->setOverlay(new Overlay(ref)); ret = mHardware->setOverlay(new Overlay(ref));
} else {
ret = mHardware->setOverlay(NULL);
}
if (ret != NO_ERROR) { if (ret != NO_ERROR) {
LOGE("mHardware->setOverlay() failed with status %d\n", ret); LOGE("mHardware->setOverlay() failed with status %d\n", ret);
return ret;
} }
ret = mHardware->startPreview(NULL, mCameraService.get()); return ret;
if (ret != NO_ERROR) }
LOGE("mHardware->startPreview() failed with status %d\n", ret);
} else { status_t CameraService::Client::registerPreviewBuffers()
ret = mHardware->startPreview(previewCallback, {
mCameraService.get()); int w, h;
if (ret == NO_ERROR) { CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
mSurface->unregisterBuffers();
uint32_t transform = 0; uint32_t transform = 0;
if (params.getOrientation() == if (params.getOrientation() ==
@ -557,9 +561,44 @@ status_t CameraService::Client::startPreviewMode()
0, 0,
mHardware->getPreviewHeap()); mHardware->getPreviewHeap());
mSurface->registerBuffers(buffers); status_t ret = mSurface->registerBuffers(buffers);
if (ret != NO_ERROR) {
LOGE("registerBuffers failed with status %d", ret);
}
return ret;
}
status_t CameraService::Client::startPreviewMode()
{
LOGD("startPreviewMode (pid %d)", getCallingPid());
// if preview has been enabled, nothing needs to be done
if (mHardware->previewEnabled()) {
return NO_ERROR;
}
// start preview mode
#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
debug_frame_cnt = 0;
#endif
status_t ret = NO_ERROR;
if (mUseOverlay) {
// If preview display has been set, set overlay now.
if (mSurface != 0) {
ret = setOverlay();
}
if (ret != NO_ERROR) return ret;
ret = mHardware->startPreview(NULL, mCameraService.get());
} else { } else {
LOGE("mHardware->startPreview() failed with status %d", ret); ret = mHardware->startPreview(previewCallback,
mCameraService.get());
if (ret != NO_ERROR) return ret;
// If preview display has been set, register preview buffers now.
if (mSurface != 0) {
// Unregister here because the surface registered with raw heap.
mSurface->unregisterBuffers();
ret = registerPreviewBuffers();
} }
} }
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 {
if (holder != null) {
setPreviewDisplay(holder.getSurface()); 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;
if (surface != 0) {
return c->setPreviewDisplay(surface->getISurface()); 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");