mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-07 05:53:06 +00:00
292 lines
7.2 KiB
Java
292 lines
7.2 KiB
Java
/*
|
|
AndroidCameraRecordImpl.java
|
|
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
package org.linphone.core;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import android.hardware.Camera;
|
|
import android.hardware.Camera.ErrorCallback;
|
|
import android.hardware.Camera.Parameters;
|
|
import android.hardware.Camera.PreviewCallback;
|
|
import android.hardware.Camera.Size;
|
|
import android.os.Build;
|
|
import android.util.Log;
|
|
import android.view.SurfaceHolder;
|
|
import android.view.SurfaceView;
|
|
import android.view.SurfaceHolder.Callback;
|
|
|
|
|
|
public abstract class AndroidCameraRecord {
|
|
|
|
public static final int ANDROID_VERSION = Integer.parseInt(Build.VERSION.SDK);
|
|
protected static Camera camera;
|
|
private static SurfaceView surfaceView;
|
|
|
|
protected int fps;
|
|
protected int height;
|
|
protected int width;
|
|
private PreviewCallback storedPreviewCallback;
|
|
|
|
private static AndroidCameraRecord instance;
|
|
private static boolean previewStarted;
|
|
private static boolean parametersSet;
|
|
protected static int orientationCode;
|
|
private static boolean muted;
|
|
private static final String tag="Linphone";
|
|
private static List <Size> supportedVideoSizes;
|
|
|
|
public AndroidCameraRecord() {
|
|
// TODO check if another instance is loaded and kill it.
|
|
instance = this;
|
|
}
|
|
|
|
public void setParameters(int height, int width, float fps) {
|
|
this.fps = Math.round(fps);
|
|
this.height = height;
|
|
this.width = width;
|
|
parametersSet = true;
|
|
startPreview();
|
|
}
|
|
|
|
|
|
/*
|
|
* AndroidCameraRecord.setSurfaceView() should be called first, from the Activity code.
|
|
* It will start automatically
|
|
*/
|
|
private void startPreview() {
|
|
if (muted) {
|
|
Log.d(tag, "Not starting preview as camera has been muted");
|
|
return;
|
|
}
|
|
if (surfaceView == null) {
|
|
Log.w(tag, "Surfaceview not defined; postponning video capture");
|
|
return;
|
|
}
|
|
if (!parametersSet) {
|
|
Log.w(tag, "Parameters not set; postponning video capture");
|
|
return;
|
|
}
|
|
|
|
if (previewStarted) {
|
|
Log.w(tag, "Already started");
|
|
return;
|
|
}
|
|
|
|
if (surfaceView.getVisibility() != SurfaceView.VISIBLE) {
|
|
// Illegal state
|
|
Log.e(tag, "Illegal state: video capture surface view is not visible");
|
|
return;
|
|
}
|
|
|
|
|
|
camera=Camera.open();
|
|
camera.setErrorCallback(new ErrorCallback() {
|
|
public void onError(int error, Camera camera) {
|
|
Log.e(tag, "Camera error : " + error);
|
|
}
|
|
});
|
|
|
|
|
|
Camera.Parameters parameters=camera.getParameters();
|
|
if (supportedVideoSizes == null) {
|
|
supportedVideoSizes = camera.getParameters().getSupportedPreviewSizes();
|
|
}
|
|
|
|
parameters.setPreviewSize(width, height);
|
|
parameters.setPreviewFrameRate(fps);
|
|
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
|
Log.w(tag, "Auto Focus supported by camera device");
|
|
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
} else {
|
|
Log.w(tag, "Auto Focus not supported by camera device");
|
|
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
|
|
Log.w(tag, "Infinity Focus supported by camera device");
|
|
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
|
|
} else {
|
|
Log.w(tag, "Infinity Focus not supported by camera device");
|
|
}
|
|
}
|
|
|
|
onSettingParameters(parameters);
|
|
camera.setParameters(parameters);
|
|
|
|
|
|
|
|
SurfaceHolder holder = surfaceView.getHolder();
|
|
try {
|
|
camera.setPreviewDisplay(holder);
|
|
}
|
|
catch (Throwable t) {
|
|
Log.e(tag, "Exception in Video capture setPreviewDisplay()", t);
|
|
}
|
|
|
|
|
|
try {
|
|
camera.startPreview();
|
|
previewStarted = true;
|
|
} catch (Throwable e) {
|
|
Log.e(tag, "Can't start camera preview");
|
|
}
|
|
|
|
previewStarted = true;
|
|
|
|
|
|
|
|
// Register callback to get capture buffer
|
|
if (storedPreviewCallback != null) {
|
|
reallySetPreviewCallback(camera, storedPreviewCallback);
|
|
}
|
|
|
|
|
|
onCameraStarted(camera);
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void onSettingParameters(Parameters parameters) {
|
|
|
|
}
|
|
|
|
/**
|
|
* Hook.
|
|
* @param camera
|
|
*/
|
|
public void onCameraStarted(Camera camera) {}
|
|
|
|
public void setOrStorePreviewCallBack(PreviewCallback cb) {
|
|
if (camera == null) {
|
|
Log.w(tag, "Capture camera not ready, storing callback");
|
|
this.storedPreviewCallback = cb;
|
|
return;
|
|
}
|
|
|
|
reallySetPreviewCallback(camera, cb);
|
|
}
|
|
|
|
|
|
private static void stopPreview() {
|
|
if (camera!=null){
|
|
camera.setPreviewCallback(null); // TODO check if used whatever the SDK version
|
|
camera.stopPreview();
|
|
camera.release();
|
|
}
|
|
camera=null;
|
|
previewStarted = false;
|
|
}
|
|
|
|
public static final void setSurfaceView(final SurfaceView sv) {
|
|
SurfaceHolder holder = sv.getHolder();
|
|
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
|
|
|
holder.addCallback(new Callback() {
|
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
|
AndroidCameraRecord.surfaceView = null;
|
|
|
|
if (camera == null) {
|
|
Log.e(tag, "Video capture: illegal state: surface destroyed but camera is already null");
|
|
return;
|
|
}
|
|
stopPreview();
|
|
Log.w(tag, "Video capture Surface destroyed");
|
|
}
|
|
|
|
public void surfaceCreated(SurfaceHolder holder) {
|
|
AndroidCameraRecord.surfaceView = sv;
|
|
Log.w(tag, "Video capture surface created");
|
|
|
|
if (instance != null) {
|
|
instance.startPreview();
|
|
}
|
|
|
|
holder.isCreating();
|
|
}
|
|
|
|
public void surfaceChanged(SurfaceHolder holder, int format, int width,
|
|
int height) {
|
|
Log.w(tag, "Video capture surface changed");
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
public void stopCaptureCallback() {
|
|
if (camera != null) {
|
|
reallySetPreviewCallback(camera, null);
|
|
}
|
|
}
|
|
|
|
protected void reallySetPreviewCallback(Camera camera, PreviewCallback cb) {
|
|
camera.setPreviewCallback(cb);
|
|
}
|
|
|
|
public static void setOrientationCode(int orientation) {
|
|
AndroidCameraRecord.orientationCode = (4 + 1 - orientation) % 4;
|
|
}
|
|
|
|
protected int getOrientationCode() {
|
|
return orientationCode;
|
|
}
|
|
|
|
public static void setMuteCamera(boolean m) {
|
|
if (m == muted) return;
|
|
|
|
muted = m;
|
|
if (muted && previewStarted) {
|
|
stopPreview();
|
|
return;
|
|
}
|
|
|
|
if (!muted) {
|
|
instance.startPreview();
|
|
}
|
|
|
|
}
|
|
|
|
public static void toggleMute() {
|
|
setMuteCamera(!muted);
|
|
}
|
|
|
|
public static List<Size> supportedVideoSizes() {
|
|
if (supportedVideoSizes != null) {
|
|
return new ArrayList<Size>(supportedVideoSizes);
|
|
}
|
|
|
|
if (camera == null) {
|
|
camera = Camera.open();
|
|
supportedVideoSizes = camera.getParameters().getSupportedPreviewSizes();
|
|
camera.release();
|
|
return supportedVideoSizes;
|
|
}
|
|
|
|
throw new RuntimeException("Should not be there");
|
|
}
|
|
|
|
public static boolean getCameraMuted() {
|
|
return muted;
|
|
}
|
|
|
|
public static void invalidateParameters() {
|
|
parametersSet = false;
|
|
stopPreview();
|
|
}
|
|
}
|