Handle locked video orientation from ScreenInfo
Centralize video size management in ScreenInfo. This allows to always send the correct initial video size to the client if the video orientation is locked.
This commit is contained in:
parent
c5f5d1e456
commit
ae2d094362
3 changed files with 80 additions and 59 deletions
|
@ -22,14 +22,12 @@ public final class Device {
|
||||||
|
|
||||||
private final ServiceManager serviceManager = new ServiceManager();
|
private final ServiceManager serviceManager = new ServiceManager();
|
||||||
|
|
||||||
private final int lockedVideoOrientation;
|
|
||||||
private ScreenInfo screenInfo;
|
private ScreenInfo screenInfo;
|
||||||
private RotationListener rotationListener;
|
private RotationListener rotationListener;
|
||||||
|
|
||||||
public Device(Options options) {
|
public Device(Options options) {
|
||||||
lockedVideoOrientation = options.getLockedVideoOrientation();
|
|
||||||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
|
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
|
||||||
screenInfo = ScreenInfo.computeScreenInfo(displayInfo, options.getCrop(), options.getMaxSize());
|
screenInfo = ScreenInfo.computeScreenInfo(displayInfo, options.getCrop(), options.getMaxSize(), options.getLockedVideoOrientation());
|
||||||
registerRotationWatcher(new IRotationWatcher.Stub() {
|
registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onRotationChanged(int rotation) throws RemoteException {
|
public void onRotationChanged(int rotation) throws RemoteException {
|
||||||
|
@ -49,55 +47,28 @@ public final class Device {
|
||||||
return screenInfo;
|
return screenInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the rotation to apply to the device rotation to get the requested locked video orientation
|
|
||||||
*
|
|
||||||
* @param deviceRotation the device rotation
|
|
||||||
* @return the rotation offset
|
|
||||||
*/
|
|
||||||
public int getVideoRotation(int deviceRotation) {
|
|
||||||
if (lockedVideoOrientation == -1) {
|
|
||||||
// no offset
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (deviceRotation + 4 - lockedVideoOrientation) % 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the rotation to apply to the requested locked video orientation to get the device rotation
|
|
||||||
*
|
|
||||||
* @param deviceRotation the device rotation
|
|
||||||
* @return the (reverse) rotation offset
|
|
||||||
*/
|
|
||||||
private int getReverseVideoRotation(int deviceRotation) {
|
|
||||||
if (lockedVideoOrientation == -1) {
|
|
||||||
// no offset
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (lockedVideoOrientation + 4 - deviceRotation) % 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point getPhysicalPoint(Position position) {
|
public Point getPhysicalPoint(Position position) {
|
||||||
// it hides the field on purpose, to read it with a lock
|
// it hides the field on purpose, to read it with a lock
|
||||||
@SuppressWarnings("checkstyle:HiddenField")
|
@SuppressWarnings("checkstyle:HiddenField")
|
||||||
ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
|
ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
|
||||||
Size videoSize = screenInfo.getVideoSize();
|
|
||||||
|
|
||||||
int deviceRotation = screenInfo.getDeviceRotation();
|
// ignore the locked video orientation, the events will apply in coordinates considered in the physical device orientation
|
||||||
int reverseVideoRotation = getReverseVideoRotation(deviceRotation);
|
Size unlockedVideoSize = screenInfo.getUnlockedVideoSize();
|
||||||
|
|
||||||
|
int reverseVideoRotation = screenInfo.getReverseVideoRotation();
|
||||||
// reverse the video rotation to apply the events
|
// reverse the video rotation to apply the events
|
||||||
Position devicePosition = position.rotate(reverseVideoRotation);
|
Position devicePosition = position.rotate(reverseVideoRotation);
|
||||||
|
|
||||||
Size clientVideoSize = devicePosition.getScreenSize();
|
Size clientVideoSize = devicePosition.getScreenSize();
|
||||||
if (!videoSize.equals(clientVideoSize)) {
|
if (!unlockedVideoSize.equals(clientVideoSize)) {
|
||||||
// The client sends a click relative to a video with wrong dimensions,
|
// The client sends a click relative to a video with wrong dimensions,
|
||||||
// the device may have been rotated since the event was generated, so ignore the event
|
// the device may have been rotated since the event was generated, so ignore the event
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Rect contentRect = screenInfo.getContentRect();
|
Rect contentRect = screenInfo.getContentRect();
|
||||||
Point point = devicePosition.getPoint();
|
Point point = devicePosition.getPoint();
|
||||||
int convertedX = contentRect.left + point.getX() * contentRect.width() / videoSize.getWidth();
|
int convertedX = contentRect.left + point.getX() * contentRect.width() / unlockedVideoSize.getWidth();
|
||||||
int convertedY = contentRect.top + point.getY() * contentRect.height() / videoSize.getHeight();
|
int convertedY = contentRect.top + point.getY() * contentRect.height() / unlockedVideoSize.getHeight();
|
||||||
return new Point(convertedX, convertedY);
|
return new Point(convertedX, convertedY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,12 +66,15 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
IBinder display = createDisplay();
|
IBinder display = createDisplay();
|
||||||
ScreenInfo screenInfo = device.getScreenInfo();
|
ScreenInfo screenInfo = device.getScreenInfo();
|
||||||
Rect contentRect = screenInfo.getContentRect();
|
Rect contentRect = screenInfo.getContentRect();
|
||||||
|
// include the locked video orientation
|
||||||
Rect videoRect = screenInfo.getVideoSize().toRect();
|
Rect videoRect = screenInfo.getVideoSize().toRect();
|
||||||
int videoRotation = device.getVideoRotation(screenInfo.getDeviceRotation());
|
// does not include the locked video orientation
|
||||||
setSize(format, videoRotation, videoRect.width(), videoRect.height());
|
Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect();
|
||||||
|
int videoRotation = screenInfo.getVideoRotation();
|
||||||
|
setSize(format, videoRect.width(), videoRect.height());
|
||||||
configure(codec, format);
|
configure(codec, format);
|
||||||
Surface surface = codec.createInputSurface();
|
Surface surface = codec.createInputSurface();
|
||||||
setDisplaySurface(display, surface, videoRotation, contentRect, videoRect);
|
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect);
|
||||||
codec.start();
|
codec.start();
|
||||||
try {
|
try {
|
||||||
alive = encode(codec, fd);
|
alive = encode(codec, fd);
|
||||||
|
@ -170,14 +173,9 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setSize(MediaFormat format, int orientation, int width, int height) {
|
private static void setSize(MediaFormat format, int width, int height) {
|
||||||
if (orientation % 2 == 0) {
|
format.setInteger(MediaFormat.KEY_WIDTH, width);
|
||||||
format.setInteger(MediaFormat.KEY_WIDTH, width);
|
format.setInteger(MediaFormat.KEY_HEIGHT, height);
|
||||||
format.setInteger(MediaFormat.KEY_HEIGHT, height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
format.setInteger(MediaFormat.KEY_WIDTH, height);
|
|
||||||
format.setInteger(MediaFormat.KEY_HEIGHT, width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setDisplaySurface(IBinder display, Surface surface, int orientation, Rect deviceRect, Rect displayRect) {
|
private static void setDisplaySurface(IBinder display, Surface surface, int orientation, Rect deviceRect, Rect displayRect) {
|
||||||
|
|
|
@ -9,27 +9,53 @@ public final class ScreenInfo {
|
||||||
private final Rect contentRect; // device size, possibly cropped
|
private final Rect contentRect; // device size, possibly cropped
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Video size, possibly smaller than the device size, already taking the device rotation and crop into account
|
* Video size, possibly smaller than the device size, already taking the device rotation and crop into account.
|
||||||
|
* <p>
|
||||||
|
* However, it does not include the locked video orientation.
|
||||||
*/
|
*/
|
||||||
private final Size videoSize;
|
private final Size unlockedVideoSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Device rotation, related to the natural device orientation (0, 1, 2 or 3)
|
* Device rotation, related to the natural device orientation (0, 1, 2 or 3)
|
||||||
*/
|
*/
|
||||||
private final int deviceRotation;
|
private final int deviceRotation;
|
||||||
|
|
||||||
public ScreenInfo(Rect contentRect, Size videoSize, int deviceRotation) {
|
/**
|
||||||
|
* The locked video orientation (-1: disabled, 0: normal, 1: 90° CCW, 2: 180°, 3: 90° CW)
|
||||||
|
*/
|
||||||
|
private final int lockedVideoOrientation;
|
||||||
|
|
||||||
|
public ScreenInfo(Rect contentRect, Size unlockedVideoSize, int deviceRotation, int lockedVideoOrientation) {
|
||||||
this.contentRect = contentRect;
|
this.contentRect = contentRect;
|
||||||
this.videoSize = videoSize;
|
this.unlockedVideoSize = unlockedVideoSize;
|
||||||
this.deviceRotation = deviceRotation;
|
this.deviceRotation = deviceRotation;
|
||||||
|
this.lockedVideoOrientation = lockedVideoOrientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rect getContentRect() {
|
public Rect getContentRect() {
|
||||||
return contentRect;
|
return contentRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the video size as if locked video orientation was not set.
|
||||||
|
*
|
||||||
|
* @return the unlocked video size
|
||||||
|
*/
|
||||||
|
public Size getUnlockedVideoSize() {
|
||||||
|
return unlockedVideoSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the actual video size if locked video orientation is set.
|
||||||
|
*
|
||||||
|
* @return the actual video size
|
||||||
|
*/
|
||||||
public Size getVideoSize() {
|
public Size getVideoSize() {
|
||||||
return videoSize;
|
if (getVideoRotation() % 2 == 0) {
|
||||||
|
return unlockedVideoSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unlockedVideoSize.rotate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDeviceRotation() {
|
public int getDeviceRotation() {
|
||||||
|
@ -43,18 +69,18 @@ public final class ScreenInfo {
|
||||||
// true if changed between portrait and landscape
|
// true if changed between portrait and landscape
|
||||||
boolean orientationChanged = (deviceRotation + newDeviceRotation) % 2 != 0;
|
boolean orientationChanged = (deviceRotation + newDeviceRotation) % 2 != 0;
|
||||||
Rect newContentRect;
|
Rect newContentRect;
|
||||||
Size newVideoSize;
|
Size newUnlockedVideoSize;
|
||||||
if (orientationChanged) {
|
if (orientationChanged) {
|
||||||
newContentRect = flipRect(contentRect);
|
newContentRect = flipRect(contentRect);
|
||||||
newVideoSize = videoSize.rotate();
|
newUnlockedVideoSize = unlockedVideoSize.rotate();
|
||||||
} else {
|
} else {
|
||||||
newContentRect = contentRect;
|
newContentRect = contentRect;
|
||||||
newVideoSize = videoSize;
|
newUnlockedVideoSize = unlockedVideoSize;
|
||||||
}
|
}
|
||||||
return new ScreenInfo(newContentRect, newVideoSize, newDeviceRotation);
|
return new ScreenInfo(newContentRect, newUnlockedVideoSize, newDeviceRotation, lockedVideoOrientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScreenInfo computeScreenInfo(DisplayInfo displayInfo, Rect crop, int maxSize) {
|
public static ScreenInfo computeScreenInfo(DisplayInfo displayInfo, Rect crop, int maxSize, int lockedVideoOrientation) {
|
||||||
int rotation = displayInfo.getRotation();
|
int rotation = displayInfo.getRotation();
|
||||||
Size deviceSize = displayInfo.getSize();
|
Size deviceSize = displayInfo.getSize();
|
||||||
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
|
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
|
||||||
|
@ -71,7 +97,7 @@ public final class ScreenInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize);
|
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize);
|
||||||
return new ScreenInfo(contentRect, videoSize, rotation);
|
return new ScreenInfo(contentRect, videoSize, rotation, lockedVideoOrientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatCrop(Rect rect) {
|
private static String formatCrop(Rect rect) {
|
||||||
|
@ -109,4 +135,30 @@ public final class ScreenInfo {
|
||||||
private static Rect flipRect(Rect crop) {
|
private static Rect flipRect(Rect crop) {
|
||||||
return new Rect(crop.top, crop.left, crop.bottom, crop.right);
|
return new Rect(crop.top, crop.left, crop.bottom, crop.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the rotation to apply to the device rotation to get the requested locked video orientation
|
||||||
|
*
|
||||||
|
* @return the rotation offset
|
||||||
|
*/
|
||||||
|
public int getVideoRotation() {
|
||||||
|
if (lockedVideoOrientation == -1) {
|
||||||
|
// no offset
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (deviceRotation + 4 - lockedVideoOrientation) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the rotation to apply to the requested locked video orientation to get the device rotation
|
||||||
|
*
|
||||||
|
* @return the (reverse) rotation offset
|
||||||
|
*/
|
||||||
|
public int getReverseVideoRotation() {
|
||||||
|
if (lockedVideoOrientation == -1) {
|
||||||
|
// no offset
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (lockedVideoOrientation + 4 - deviceRotation) % 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue