*/
package org.linphone.core.video;
+import java.util.List;
+
+import org.linphone.core.VideoSize;
+
/**
* @author Guillaume Beraudo
boolean isFrontCamera(int cameraId);
+ List<VideoSize> getSupportedPreviewSizes(int cameraId);
+
/**
* Default: no front; rear=0; default=rear
* @author Guillaume Beraudo
*/
package org.linphone.core.video;
+import java.util.List;
+
import org.linphone.core.Hacks;
import org.linphone.core.Log;
+import org.linphone.core.VideoSize;
+
+import android.hardware.Camera;
class AndroidCameraConf5 implements AndroidCameraConf {
return false;
}
+
+ public List<VideoSize> getSupportedPreviewSizes(int cameraId) {
+ if (getNumberOfCameras() >1) {
+ Log.w("Hack: on older devices, using video formats supported by default camera");
+ }
+ Log.i("Opening camera to retrieve supported video sizes");
+ Camera c = Camera.open();
+ List<VideoSize> sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes());
+ c.release();
+ Log.i("Camera opened to retrieve supported video sizes released");
+ return sizes;
+ }
*/
package org.linphone.core.video;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.linphone.core.Log;
+import org.linphone.core.VideoSize;
import android.hardware.Camera;
class AndroidCameraConf9 implements AndroidCameraConf {
private AndroidCameras foundCameras;
+ private Map<Integer,List<VideoSize>> supportedSizes = new HashMap<Integer, List<VideoSize>>();
public AndroidCameras getFoundCameras() {return foundCameras;}
public AndroidCameraConf9() {
} else {
foundCameras.rear = id;
}
+ supportedSizes.put(id, findSupportedVideoSizes(id));
}
}
+ private List<VideoSize> findSupportedVideoSizes(int id) {
+ Log.i("Opening camera ",id," to retrieve supported video sizes");
+ Camera c = Camera.open(id);
+ List<VideoSize> sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes());
+ c.release();
+ Log.i("Camera ",id," opened to retrieve supported video sizes released");
+ return sizes;
+ }
+
public int getNumberOfCameras() {
return Camera.getNumberOfCameras();
}
return info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? true : false;
}
+ public List<VideoSize> getSupportedPreviewSizes(int cameraId) {
+ return supportedSizes.get(cameraId);
+ }
+
}
*/
package org.linphone.core.video;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.linphone.core.Log;
import org.linphone.core.Version;
+import org.linphone.core.VideoSize;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
private PreviewCallback storedPreviewCallback;
private boolean previewStarted;
- private List <Size> supportedVideoSizes;
+ private List <VideoSize> supportedVideoSizes;
private Size currentPreviewSize;
public AndroidCameraRecord(RecorderParams parameters) {
return Collections.emptyList();
}
+ private int[] findClosestFpsRange(int expectedFps, List<int[]> fpsRanges) {
+ Log.d("Searching for closest fps range from ",expectedFps);
+ int measure = Integer.MAX_VALUE;
+ int[] closestRange = {expectedFps,expectedFps};
+ for (int[] curRange : fpsRanges) {
+ if (curRange[0] > expectedFps || curRange[1] < expectedFps) continue;
+ int curMeasure = Math.abs(curRange[0] - expectedFps)
+ + Math.abs(curRange[1] - expectedFps);
+ if (curMeasure < measure) {
+ closestRange=curRange;
+ Log.d("a better range has been found: w=",closestRange[0],",h=",closestRange[1]);
+ }
+ }
+ Log.d("The closest fps range is w=",closestRange[0],",h=",closestRange[1]);
+ return closestRange;
+ }
+
public synchronized void startPreview() { // FIXME throws exception?
if (previewStarted) {
Log.w("Already started");
Camera.Parameters parameters=camera.getParameters();
- if (Version.sdkStrictlyBelow(9)) {
+ if (Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23)) {
parameters.set("camera-id",params.cameraId);
}
if (supportedVideoSizes == null) {
- supportedVideoSizes = new ArrayList<Size>(getSupportedPreviewSizes(parameters));
+ supportedVideoSizes = VideoUtil.createList(getSupportedPreviewSizes(parameters));
}
// should setParameters and get again to have the real one??
currentPreviewSize = parameters.getPreviewSize();
- parameters.setPreviewFrameRate(Math.round(params.fps));
+ // Frame rate
+ if (Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23)) {
+ parameters.setPreviewFrameRate(Math.round(params.fps));
+ } else {
+ int[] range=findClosestFpsRange((int)(1000*params.fps), parameters.getSupportedPreviewFpsRange());
+ parameters.setPreviewFpsRange(range[0], range[1]);
+ }
onSettingCameraParameters(parameters);
return previewStarted;
}
- public List<Size> getSupportedVideoSizes() {
- return new ArrayList<Size>(supportedVideoSizes);
+ public List<VideoSize> getSupportedVideoSizes() {
+ return supportedVideoSizes;
}
camera.setPreviewCallback(cb);
}
+
}
import java.util.List;
-
import org.linphone.core.LinphoneCore;
import org.linphone.core.Log;
import org.linphone.core.Version;
+import org.linphone.core.VideoSize;
import org.linphone.core.video.AndroidCameraRecord.RecorderParams;
import android.content.Context;
-import android.hardware.Camera.Size;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
private int cameraId;
private AndroidCameraRecord recorder;
- private List<Size> supportedVideoSizes;
private int mAlwaysChangingPhoneOrientation=0;
p.cameraId = cameraId;
p.isFrontCamera = isUseFrontCamera();
parameters = p;
-
+
+ // Mirror the sent frames in order to make them readable
+ // (otherwise it is mirrored and thus unreadable)
if (p.isFrontCamera) {
- if (!isCameraOrientationPortrait()) {
- // Code for Nexus S: to be tested
- p.mirror = RecorderParams.MirrorType.CENTRAL;
+ if (!isCameraMountedPortrait()) {
+ // Code for Nexus S
+ if (isFrameToBeShownPortrait())
+ p.mirror = RecorderParams.MirrorType.CENTRAL;
} else {
// Code for Galaxy S like: camera mounted landscape when phone hold portrait
p.mirror = RecorderParams.MirrorType.HORIZONTAL;
- /**
- * FIXME select right camera
- */
- public List<Size> supportedVideoSizes() {
- if (supportedVideoSizes != null) {
- return supportedVideoSizes;
- }
-
- if (recorder != null) {
- supportedVideoSizes = recorder.getSupportedVideoSizes();
- if (supportedVideoSizes != null) return supportedVideoSizes;
- }
-
- return supportedVideoSizes;
+ public List<VideoSize> supportedVideoSizes() {
+ Log.d("Using supportedVideoSizes of camera ",cameraId);
+ return cc.getSupportedPreviewSizes(cameraId);
}
parameters = null;
}
- public boolean isOutputPortraitDependingOnCameraAndPhoneOrientations() {
+ /** Depends on currently selected camera, camera mounted portrait/landscape, current phone orientation */
+ public boolean isFrameToBeShownPortrait() {
final int rotation = bufferRotationToCompensateCameraAndPhoneOrientations();
- final boolean isPortrait = (rotation % 180) == 90;
-
- Log.d("Camera sensor in ", isPortrait? "portrait":"landscape"," orientation.");
+
+ boolean isPortrait;
+ if (isCameraMountedPortrait()) {
+ // Nexus S
+ isPortrait = (rotation % 180) == 0;
+ } else {
+ isPortrait = (rotation % 180) == 90;
+ }
+
+ Log.d("The frame to be shown and sent to remote is ", isPortrait? "portrait":"landscape"," orientation.");
return isPortrait;
}
-
-
- public boolean isCameraOrientationPortrait() {
+
+
+ public boolean isCameraMountedPortrait() {
return (cc.getCameraOrientation(cameraId) % 180) == 0;
}
final int phoneOrientation = mAlwaysChangingPhoneOrientation;
final int cameraOrientation = cc.getCameraOrientation(cameraId);
int frontCameraCorrection = 0;
- if (cc.isFrontCamera(cameraId)) // TODO: check with other phones (Nexus S, ...)
- frontCameraCorrection=180; // hack that "just works" on Galaxy S.
+ if (cc.isFrontCamera(cameraId)) {
+ frontCameraCorrection=180; // hack that "just works" on Galaxy S and Nexus S.
+ // See also magic with mirrors in setParametersFromFilter
+ }
final int rotation = (cameraOrientation + phoneOrientation + frontCameraCorrection) % 360;
Log.d("Capture video buffer of cameraId=",cameraId,
" will need a rotation of ",rotation,
*/
public boolean isOutputOrientationMismatch(LinphoneCore lc) {
final boolean currentlyPortrait = lc.getPreferredVideoSize().isPortrait();
- final boolean shouldBePortrait = isOutputPortraitDependingOnCameraAndPhoneOrientations();
+ final boolean shouldBePortrait = isFrameToBeShownPortrait();
return currentlyPortrait ^ shouldBePortrait;
}
--- /dev/null
+/*
+VideoUtil.java
+Copyright (C) 2011 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.video;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.linphone.core.VideoSize;
+
+import android.hardware.Camera.Size;
+
+/**
+ * @author Guillaume Beraudo
+ */
+final class VideoUtil {
+
+ private VideoUtil() {}
+
+ public static List<VideoSize> createList(List<Size> supportedVideoSizes) {
+ List<VideoSize> converted = new ArrayList<VideoSize>(supportedVideoSizes.size());
+ for (Size s : supportedVideoSizes) {
+ converted.add(new VideoSize(s.width, s.height));
+ }
+ return converted;
+ }
+}