Fix video on Nexus S.
This commit is contained in:
parent
a68b03baab
commit
4d47899e2f
9 changed files with 177 additions and 42 deletions
|
@ -18,8 +18,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.LinphoneCallParams;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.VideoSize;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
|
||||
|
@ -81,7 +84,10 @@ public class BandwidthManager {
|
|||
// Setting Linphone Core Preferred Video Size
|
||||
boolean bandwidthOKForVideo = isVideoPossible();
|
||||
if (bandwidthOKForVideo) {
|
||||
VideoSize targetVideoSize = getMaximumVideoSize();
|
||||
AndroidCameraRecordManager acrm = AndroidCameraRecordManager.getInstance();
|
||||
boolean isPortrait=acrm.isFrameToBeShownPortrait();
|
||||
VideoSize targetVideoSize=maxSupportedVideoSize(isPortrait, getMaximumVideoSize(isPortrait),
|
||||
acrm.supportedVideoSizes());
|
||||
|
||||
lc.setPreferredVideoSize(targetVideoSize);
|
||||
VideoSize actualVideoSize = lc.getPreferredVideoSize();
|
||||
|
@ -103,6 +109,26 @@ public class BandwidthManager {
|
|||
}
|
||||
|
||||
|
||||
private VideoSize maxSupportedVideoSize(boolean isPortrait, VideoSize maximumVideoSize,
|
||||
List<VideoSize> supportedVideoSizes) {
|
||||
Log.d("Searching for maximum video size for ", isPortrait ? "portrait" : "landscape","capture from (",maximumVideoSize);
|
||||
VideoSize selected = VideoSize.createStandard(VideoSize.QCIF, isPortrait);
|
||||
for (VideoSize s : supportedVideoSizes) {
|
||||
int sW = s.width;
|
||||
int sH = s.height;
|
||||
if (s.isPortrait() != isPortrait) {
|
||||
sW=s.height;
|
||||
sH=s.width;
|
||||
}
|
||||
if (sW >maximumVideoSize.width || sH>maximumVideoSize.height) continue;
|
||||
if (selected.width <sW && selected.height <sH) {
|
||||
selected=new VideoSize(sW, sH);
|
||||
Log.d("A better video size has been found: ",selected);
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
private VideoSize maximumVideoSize(int profile, boolean cameraIsPortrait) {
|
||||
switch (profile) {
|
||||
case LOW_RESOLUTION:
|
||||
|
@ -119,7 +145,7 @@ public class BandwidthManager {
|
|||
return currentProfile != LOW_BANDWIDTH;
|
||||
}
|
||||
|
||||
public VideoSize getMaximumVideoSize() {
|
||||
return maximumVideoSize(currentProfile, AndroidCameraRecordManager.getInstance().isOutputPortraitDependingOnCameraAndPhoneOrientations());
|
||||
private VideoSize getMaximumVideoSize(boolean isPortrait) {
|
||||
return maximumVideoSize(currentProfile, isPortrait);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ public class VideoCallActivity extends SoftVolumeActivity implements OnCapturing
|
|||
|
||||
// Force to display in portrait orientation for old devices
|
||||
// as they do not support surfaceView rotation
|
||||
setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
|
||||
setRequestedOrientation(recordManager.isCameraMountedPortrait() ?
|
||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
resizeCapturePreview(mVideoCaptureView);
|
||||
|
|
|
@ -18,6 +18,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone.core.video;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.VideoSize;
|
||||
|
||||
|
||||
/**
|
||||
* @author Guillaume Beraudo
|
||||
|
@ -33,6 +37,8 @@ interface AndroidCameraConf {
|
|||
|
||||
boolean isFrontCamera(int cameraId);
|
||||
|
||||
List<VideoSize> getSupportedPreviewSizes(int cameraId);
|
||||
|
||||
/**
|
||||
* Default: no front; rear=0; default=rear
|
||||
* @author Guillaume Beraudo
|
||||
|
|
|
@ -18,8 +18,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
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 {
|
||||
|
@ -91,6 +96,18 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -18,12 +18,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
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() {
|
||||
|
@ -38,9 +44,19 @@ class AndroidCameraConf9 implements AndroidCameraConf {
|
|||
} 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();
|
||||
}
|
||||
|
@ -58,4 +74,8 @@ class AndroidCameraConf9 implements AndroidCameraConf {
|
|||
return info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? true : false;
|
||||
}
|
||||
|
||||
public List<VideoSize> getSupportedPreviewSizes(int cameraId) {
|
||||
return supportedSizes.get(cameraId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
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;
|
||||
|
@ -44,7 +44,7 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
|||
|
||||
private PreviewCallback storedPreviewCallback;
|
||||
private boolean previewStarted;
|
||||
private List <Size> supportedVideoSizes;
|
||||
private List <VideoSize> supportedVideoSizes;
|
||||
private Size currentPreviewSize;
|
||||
|
||||
public AndroidCameraRecord(RecorderParams parameters) {
|
||||
|
@ -55,6 +55,23 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
|||
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");
|
||||
|
@ -83,12 +100,12 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
|||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,7 +118,13 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
|||
// 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);
|
||||
|
@ -223,8 +246,8 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
|||
return previewStarted;
|
||||
}
|
||||
|
||||
public List<Size> getSupportedVideoSizes() {
|
||||
return new ArrayList<Size>(supportedVideoSizes);
|
||||
public List<VideoSize> getSupportedVideoSizes() {
|
||||
return supportedVideoSizes;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -135,4 +135,5 @@ class AndroidCameraRecord5 extends AndroidCameraRecord implements PreviewCallbac
|
|||
camera.setPreviewCallback(cb);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,14 +20,13 @@ package org.linphone.core.video;
|
|||
|
||||
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;
|
||||
|
@ -63,7 +62,6 @@ public class AndroidCameraRecordManager {
|
|||
private int cameraId;
|
||||
|
||||
private AndroidCameraRecord recorder;
|
||||
private List<Size> supportedVideoSizes;
|
||||
private int mAlwaysChangingPhoneOrientation=0;
|
||||
|
||||
|
||||
|
@ -127,10 +125,13 @@ public class AndroidCameraRecordManager {
|
|||
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;
|
||||
|
@ -236,20 +237,9 @@ public class AndroidCameraRecordManager {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,11 +257,19 @@ public class AndroidCameraRecordManager {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -280,7 +278,7 @@ public class AndroidCameraRecordManager {
|
|||
|
||||
|
||||
|
||||
public boolean isCameraOrientationPortrait() {
|
||||
public boolean isCameraMountedPortrait() {
|
||||
return (cc.getCameraOrientation(cameraId) % 180) == 0;
|
||||
}
|
||||
|
||||
|
@ -296,8 +294,10 @@ public class AndroidCameraRecordManager {
|
|||
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,
|
||||
|
@ -342,7 +342,7 @@ public class AndroidCameraRecordManager {
|
|||
*/
|
||||
public boolean isOutputOrientationMismatch(LinphoneCore lc) {
|
||||
final boolean currentlyPortrait = lc.getPreferredVideoSize().isPortrait();
|
||||
final boolean shouldBePortrait = isOutputPortraitDependingOnCameraAndPhoneOrientations();
|
||||
final boolean shouldBePortrait = isFrameToBeShownPortrait();
|
||||
return currentlyPortrait ^ shouldBePortrait;
|
||||
}
|
||||
|
||||
|
|
42
src/org/linphone/core/video/VideoUtil.java
Normal file
42
src/org/linphone/core/video/VideoUtil.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue