Split video overlay into 2 classes

This commit is contained in:
Sylvain Berfini 2018-12-14 17:00:19 +01:00
parent 86b8fcd5e6
commit e333e5a58a
4 changed files with 357 additions and 147 deletions

View file

@ -52,7 +52,9 @@ import org.linphone.receivers.BluetoothManager;
import org.linphone.receivers.KeepAliveReceiver;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
import org.linphone.views.LinphoneGL2JNIViewOverlay;
import org.linphone.views.LinphoneOverlay;
import org.linphone.views.LinphoneTextureViewOverlay;
/**
* Linphone service, reacting to Incoming calls, ...<br>
@ -290,19 +292,24 @@ public final class LinphoneService extends Service {
public void createOverlay() {
if (mOverlay != null) destroyOverlay();
Call call = LinphoneManager.getLc().getCurrentCall();
Core core = LinphoneManager.getLc();
Call call = core.getCurrentCall();
if (call == null || !call.getCurrentParams().videoEnabled()) return;
mOverlay = new LinphoneOverlay(this);
if ("MSAndroidOpenGLDisplay".equals(core.getVideoDisplayFilter())) {
mOverlay = new LinphoneGL2JNIViewOverlay(this);
} else {
mOverlay = new LinphoneTextureViewOverlay(this);
}
WindowManager.LayoutParams params = mOverlay.getWindowManagerLayoutParams();
params.x = 0;
params.y = 0;
mWindowManager.addView(mOverlay, params);
mOverlay.addToWindowManager(mWindowManager, params);
}
public void destroyOverlay() {
if (mOverlay != null) {
mWindowManager.removeViewImmediate(mOverlay);
mOverlay.removeFromWindowManager(mWindowManager);
mOverlay.destroy();
}
mOverlay = null;

View file

@ -0,0 +1,182 @@
package org.linphone.views;
/*
LinphoneGL2JNIViewOverlay.java
Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneService;
import org.linphone.core.Call;
import org.linphone.core.CallParams;
import org.linphone.mediastream.Version;
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
public class LinphoneGL2JNIViewOverlay extends org.linphone.mediastream.video.display.GL2JNIView
implements LinphoneOverlay {
private final WindowManager mWindowManager;
private final WindowManager.LayoutParams mParams;
private final DisplayMetrics mMetrics;
private float mX, mY, mTouchX, mTouchY;
private boolean mDragEnabled;
private final AndroidVideoWindowImpl mAndroidVideoWindowImpl;
public LinphoneGL2JNIViewOverlay(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Version.API26_O_80) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
mParams =
new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
mParams.gravity = Gravity.TOP | Gravity.LEFT;
mMetrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(mMetrics);
mAndroidVideoWindowImpl =
new AndroidVideoWindowImpl(
this,
null,
new AndroidVideoWindowImpl.VideoWindowListener() {
public void onVideoRenderingSurfaceReady(
AndroidVideoWindowImpl vw, SurfaceView surface) {
LinphoneManager.getLc().setNativeVideoWindowId(vw);
}
public void onVideoRenderingSurfaceDestroyed(
AndroidVideoWindowImpl vw) {}
public void onVideoPreviewSurfaceReady(
AndroidVideoWindowImpl vw, SurfaceView surface) {}
public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) {}
});
Call call = LinphoneManager.getLc().getCurrentCall();
CallParams callParams = call.getCurrentParams();
mParams.width = callParams.getReceivedVideoDefinition().getWidth();
mParams.height = callParams.getReceivedVideoDefinition().getHeight();
LinphoneManager.getLc().setNativeVideoWindowId(mAndroidVideoWindowImpl);
setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
Context context = LinphoneService.instance();
Intent intent =
new Intent(context, LinphoneActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
setOnLongClickListener(
new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mDragEnabled = true;
return true;
}
});
}
public LinphoneGL2JNIViewOverlay(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LinphoneGL2JNIViewOverlay(Context context) {
this(context, null);
}
@Override
public void destroy() {
mAndroidVideoWindowImpl.release();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mX = event.getRawX();
mY = event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchX = event.getX();
mTouchY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
if (mDragEnabled) {
updateViewPostion();
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchX = mTouchY = 0;
mDragEnabled = false;
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void updateViewPostion() {
mParams.x =
Math.min(
Math.max(0, (int) (mX - mTouchX)),
mMetrics.widthPixels - getMeasuredWidth());
mParams.y =
Math.min(
Math.max(0, (int) (mY - mTouchY)),
mMetrics.heightPixels - getMeasuredHeight());
mWindowManager.updateViewLayout(this, mParams);
}
@Override
public WindowManager.LayoutParams getWindowManagerLayoutParams() {
return mParams;
}
@Override
public void addToWindowManager(WindowManager windowManager, WindowManager.LayoutParams params) {
windowManager.addView(this, params);
}
@Override
public void removeFromWindowManager(WindowManager windowManager) {
windowManager.removeViewImmediate(this);
}
}

View file

@ -2,7 +2,7 @@ package org.linphone.views;
/*
LinphoneOverlay.java
Copyright (C) 2017 Belledonne Communications, Grenoble, France
Copyright (C) 2018 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
@ -19,151 +19,14 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneService;
import org.linphone.core.Call;
import org.linphone.core.CallParams;
import org.linphone.mediastream.Version;
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
public class LinphoneOverlay extends org.linphone.mediastream.video.display.GL2JNIView {
private final WindowManager mWindowManager;
private final WindowManager.LayoutParams mParams;
private final DisplayMetrics mMetrics;
private float mX, mY, mTouchX, mTouchY;
private boolean mDragEnabled;
private final AndroidVideoWindowImpl mAndroidVideoWindowImpl;
public interface LinphoneOverlay {
WindowManager.LayoutParams getWindowManagerLayoutParams();
public LinphoneOverlay(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
void addToWindowManager(WindowManager mWindowManager, WindowManager.LayoutParams params);
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Version.API26_O_80) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
void removeFromWindowManager(WindowManager mWindowManager);
mParams =
new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
mParams.gravity = Gravity.TOP | Gravity.LEFT;
mMetrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(mMetrics);
mAndroidVideoWindowImpl =
new AndroidVideoWindowImpl(
this,
null,
new AndroidVideoWindowImpl.VideoWindowListener() {
public void onVideoRenderingSurfaceReady(
AndroidVideoWindowImpl vw, SurfaceView surface) {
LinphoneManager.getLc().setNativeVideoWindowId(vw);
}
public void onVideoRenderingSurfaceDestroyed(
AndroidVideoWindowImpl vw) {}
public void onVideoPreviewSurfaceReady(
AndroidVideoWindowImpl vw, SurfaceView surface) {}
public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) {}
});
Call call = LinphoneManager.getLc().getCurrentCall();
CallParams callParams = call.getCurrentParams();
mParams.width = callParams.getReceivedVideoDefinition().getWidth();
mParams.height = callParams.getReceivedVideoDefinition().getHeight();
LinphoneManager.getLc().setNativeVideoWindowId(mAndroidVideoWindowImpl);
setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
Context context = LinphoneService.instance();
Intent intent =
new Intent(context, LinphoneActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
setOnLongClickListener(
new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mDragEnabled = true;
return true;
}
});
}
public LinphoneOverlay(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LinphoneOverlay(Context context) {
this(context, null);
}
public void destroy() {
mAndroidVideoWindowImpl.release();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mX = event.getRawX();
mY = event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchX = event.getX();
mTouchY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
if (mDragEnabled) {
updateViewPostion();
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchX = mTouchY = 0;
mDragEnabled = false;
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void updateViewPostion() {
mParams.x =
Math.min(
Math.max(0, (int) (mX - mTouchX)),
mMetrics.widthPixels - getMeasuredWidth());
mParams.y =
Math.min(
Math.max(0, (int) (mY - mTouchY)),
mMetrics.heightPixels - getMeasuredHeight());
mWindowManager.updateViewLayout(this, mParams);
}
public WindowManager.LayoutParams getWindowManagerLayoutParams() {
return mParams;
}
void destroy();
}

View file

@ -0,0 +1,158 @@
package org.linphone.views;
/*
LinphoneTextureViewOverlay.java
Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.TextureView;
import android.view.View;
import android.view.WindowManager;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneService;
import org.linphone.core.Call;
import org.linphone.core.CallParams;
import org.linphone.mediastream.Version;
public class LinphoneTextureViewOverlay extends TextureView implements LinphoneOverlay {
private final WindowManager mWindowManager;
private final WindowManager.LayoutParams mParams;
private final DisplayMetrics mMetrics;
private float mX, mY, mTouchX, mTouchY;
private boolean mDragEnabled;
public LinphoneTextureViewOverlay(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Version.API26_O_80) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
mParams =
new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
mParams.gravity = Gravity.TOP | Gravity.LEFT;
mMetrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(mMetrics);
Call call = LinphoneManager.getLc().getCurrentCall();
CallParams callParams = call.getCurrentParams();
mParams.width = callParams.getReceivedVideoDefinition().getWidth();
mParams.height = callParams.getReceivedVideoDefinition().getHeight();
LinphoneManager.getLc().setNativeVideoWindowId(this);
setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
Context context = LinphoneService.instance();
Intent intent =
new Intent(context, LinphoneActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
setOnLongClickListener(
new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mDragEnabled = true;
return true;
}
});
}
public LinphoneTextureViewOverlay(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LinphoneTextureViewOverlay(Context context) {
this(context, null);
}
@Override
public void destroy() {}
@Override
public boolean onTouchEvent(MotionEvent event) {
mX = event.getRawX();
mY = event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchX = event.getX();
mTouchY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
if (mDragEnabled) {
updateViewPostion();
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchX = mTouchY = 0;
mDragEnabled = false;
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void updateViewPostion() {
mParams.x =
Math.min(
Math.max(0, (int) (mX - mTouchX)),
mMetrics.widthPixels - getMeasuredWidth());
mParams.y =
Math.min(
Math.max(0, (int) (mY - mTouchY)),
mMetrics.heightPixels - getMeasuredHeight());
mWindowManager.updateViewLayout(this, mParams);
}
@Override
public WindowManager.LayoutParams getWindowManagerLayoutParams() {
return mParams;
}
@Override
public void addToWindowManager(WindowManager windowManager, WindowManager.LayoutParams params) {
windowManager.addView(this, params);
}
@Override
public void removeFromWindowManager(WindowManager windowManager) {
windowManager.removeViewImmediate(this);
}
}