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
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);
status_t result = checkPid();
if (result != NO_ERROR) return result;
Mutex::Autolock surfaceLock(mSurfaceLock);
result = NO_ERROR;
// asBinder() is safe on NULL (returns NULL)
if (surface->asBinder() != mSurface->asBinder()) {
if (mSurface != 0 && !mUseOverlay) {
@ -422,8 +425,17 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
mSurface->unregisterBuffers();
}
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
@ -436,7 +448,7 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
mPreviewCallbackFlag = callback_flag;
}
// start preview mode, must call setPreviewDisplay first
// start preview mode
status_t CameraService::Client::startCameraMode(camera_mode mode)
{
int callingPid = getCallingPid();
@ -456,16 +468,18 @@ status_t CameraService::Client::startCameraMode(camera_mode mode)
return INVALID_OPERATION;
}
if (mSurface == 0) {
LOGE("setPreviewDisplay must be called before startCameraMode!");
return INVALID_OPERATION;
}
switch(mode) {
case CAMERA_RECORDING_MODE:
if (mSurface == 0) {
LOGE("setPreviewDisplay must be called before startRecordingMode.");
return INVALID_OPERATION;
}
return startRecordingMode();
default: // CAMERA_PREVIEW_MODE
if (mSurface == 0) {
LOGD("mSurface is not set yet.");
}
return startPreviewMode();
}
}
@ -498,28 +512,15 @@ status_t CameraService::Client::startRecordingMode()
return ret;
}
status_t CameraService::Client::startPreviewMode()
status_t CameraService::Client::setOverlay()
{
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 = UNKNOWN_ERROR;
LOGD("setOverlay");
int w, h;
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
if (mUseOverlay) {
const char *format = params.getPreviewFormat();
int fmt;
LOGD("Use Overlays");
if (!strcmp(format, "yuv422i"))
fmt = OVERLAY_FORMAT_YCbCr_422_I;
else if (!strcmp(format, "rgb565"))
@ -528,22 +529,25 @@ status_t CameraService::Client::startPreviewMode()
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;
}
ret = mHardware->startPreview(NULL, mCameraService.get());
if (ret != NO_ERROR)
LOGE("mHardware->startPreview() failed with status %d\n", ret);
return ret;
}
} else {
ret = mHardware->startPreview(previewCallback,
mCameraService.get());
if (ret == NO_ERROR) {
mSurface->unregisterBuffers();
status_t CameraService::Client::registerPreviewBuffers()
{
int w, h;
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
uint32_t transform = 0;
if (params.getOrientation() ==
@ -557,9 +561,44 @@ status_t CameraService::Client::startPreviewMode()
0,
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 {
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;

View File

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

View File

@ -155,7 +155,11 @@ public class Camera {
* @throws IOException if the method fails.
*/
public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
if (holder != null) {
setPreviewDisplay(holder.getSurface());
} else {
setPreviewDisplay((Surface)null);
}
}
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);
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) {
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)
{
LOGV("setPreviewDisplay");
if (surface == 0) {
LOGE("app passed NULL surface");
return NO_INIT;
}
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
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)
{
LOGV("setPreviewDisplay");
if (surface == 0) {
LOGE("app passed NULL surface");
return NO_INIT;
LOGD("app passed NULL surface");
}
sp <ICamera> c = mCamera;
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()
{
LOGV("startPreview");