Better camera display in dialer

This commit is contained in:
Sylvain Berfini 2012-04-05 15:28:49 +02:00
parent cb08478146
commit ed53b8b62e
4 changed files with 199 additions and 65 deletions

View file

@ -4,7 +4,7 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:gravity="bottom|center_horizontal"> android:gravity="bottom|center_horizontal">
<SurfaceView <org.linphone.ui.CameraView
android:id="@+id/video_background" android:id="@+id/video_background"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"

View file

@ -4,7 +4,7 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:gravity="bottom|center_horizontal"> android:gravity="bottom|center_horizontal">
<SurfaceView <org.linphone.ui.CameraView
android:id="@+id/video_background" android:id="@+id/video_background"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"

View file

@ -18,7 +18,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
package org.linphone; package org.linphone;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -31,6 +30,7 @@ import org.linphone.core.Log;
import org.linphone.ui.AddressAware; import org.linphone.ui.AddressAware;
import org.linphone.ui.AddressText; import org.linphone.ui.AddressText;
import org.linphone.ui.CallButton; import org.linphone.ui.CallButton;
import org.linphone.ui.CameraView;
import org.linphone.ui.EraseButton; import org.linphone.ui.EraseButton;
import android.app.Activity; import android.app.Activity;
@ -40,20 +40,13 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.hardware.Camera; import android.hardware.Camera;
import android.hardware.Camera.CameraInfo; import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.Display;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Adapter; import android.widget.Adapter;
import android.widget.Button; import android.widget.Button;
import android.widget.ListAdapter; import android.widget.ListAdapter;
@ -90,7 +83,7 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
protected String username; protected String username;
private String key; private String key;
private SurfaceView mVideoCaptureViewReady; private CameraView mVideoCaptureView;
private int mCurrentCameraId = 0; private int mCurrentCameraId = 0;
private Camera mCamera; private Camera mCamera;
@ -268,52 +261,13 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
} }
} }
mVideoCaptureViewReady = (SurfaceView) findViewById(R.id.video_background); mVideoCaptureView = (CameraView) findViewById(R.id.video_background);
if (mVideoCaptureViewReady != null) if (mVideoCaptureView != null)
{ {
if (mCamera == null) if (mCamera == null) {
mCamera = Camera.open(mCurrentCameraId); mCamera = Camera.open(mCurrentCameraId);
}
mVideoCaptureViewReady.getHolder().addCallback(new Callback() { mVideoCaptureView.setCamera(mCamera);
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e("IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_90)
{
mCamera.setDisplayOrientation(270);
}
else if(display.getRotation() == Surface.ROTATION_270)
{
mCamera.setDisplayOrientation(90);
}
else if (display.getRotation() == Surface.ROTATION_180)
{
mCamera.setDisplayOrientation(180);
}
mVideoCaptureViewReady.requestLayout();
if (mCamera != null)
mCamera.startPreview();
}
});
mCamera.startPreview(); mCamera.startPreview();
} }
@ -325,12 +279,13 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
switchCamera.setOnClickListener(new OnClickListener() { switchCamera.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
try {
mCamera.setPreviewDisplay(mVideoCaptureViewReady.getHolder());
} catch (IOException exception) { }
mCurrentCameraId = (mCurrentCameraId + 1) % numberOfCameras; mCurrentCameraId = (mCurrentCameraId + 1) % numberOfCameras;
mCamera.release(); mCamera.release();
mVideoCaptureView.setCamera(null);
mCamera = Camera.open(mCurrentCameraId); mCamera = Camera.open(mCurrentCameraId);
mVideoCaptureView.switchCamera(mCamera);
mCamera.startPreview();
} }
}); });
} }
@ -360,6 +315,7 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
if (mCamera != null) { if (mCamera != null) {
mCamera.release(); mCamera.release();
mVideoCaptureView.setCamera(null);
mCamera = null; mCamera = null;
} }
} }
@ -489,14 +445,10 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
super.onResume(); super.onResume();
if (mVideoCaptureViewReady != null && mCamera == null && !LinphoneManager.getLc().isIncall()) if (mVideoCaptureView != null && mCamera == null && !LinphoneManager.getLc().isIncall())
{ {
mCamera = Camera.open(mCurrentCameraId); mCamera = Camera.open(mCurrentCameraId);
mVideoCaptureViewReady.requestLayout(); mVideoCaptureView.switchCamera(mCamera);
try {
mCamera.setPreviewDisplay(mVideoCaptureViewReady.getHolder());
} catch (IOException e) {
}
mCamera.startPreview(); mCamera.startPreview();
} }
} }
@ -507,5 +459,4 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
if (LinphoneUtils.onKeyVolumeSoftAdjust(keyCode)) return true; if (LinphoneUtils.onKeyVolumeSoftAdjust(keyCode)) return true;
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }
} }

View file

@ -0,0 +1,183 @@
package org.linphone.ui;
import java.io.IOException;
import java.util.List;
import org.linphone.core.Log;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
public class CameraView extends ViewGroup implements SurfaceHolder.Callback {
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
CameraView(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedSizes;
Camera mCamera;
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
public void switchCamera(Camera camera) {
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
}
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
camera.setParameters(parameters);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);;
int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);;
setMeasuredDimension(width, height);
if (mSupportedSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedSizes, width, height);
}
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_90 || display.getRotation() == Surface.ROTATION_270) {
Size tempSize = mPreviewSize;
mPreviewSize.width = tempSize.height;
mPreviewSize.height = tempSize.width;
} else {
}
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the surface view
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
mCamera.stopPreview();
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Camera.Parameters parameters = mCamera.getParameters();
if(display.getRotation() == Surface.ROTATION_90) {
mCamera.setDisplayOrientation(270);
}
else if(display.getRotation() == Surface.ROTATION_270) {
mCamera.setDisplayOrientation(90);
}
else if (display.getRotation() == Surface.ROTATION_180) {
mCamera.setDisplayOrientation(180);
}
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}