Hello!
I've managed to let Linphone accept a video call. It uses H264 and I'm only able to let it start if I set the "auto accept video" option: if I start it manually with the dedicated button, the icon starts the loading animation and no video is ever showed.
Now in my app I'm trying to always start the communication with the video stream. I've created a fragment which has a mediastream's GL2JNIView view in the layout. I've done it following the video fragment of Linphone.
In what I called "Call" fragment, I've called the "addVideo" method in the onResume method:
@Override
public void onResume() {
super.onResume();
Log.d("CallFragment", "Resumed");
SIPManager manager = SIPManager.getInstance();
LinphoneCore lc = null;
if (manager != null && manager.getLc() != null) {
lc = manager.getLc();
if (lc.getCurrentCall() != null) {
Log.d("CallFragment", "Enabling video for call");
manager.addVideo();
}
}
if (mVideoView != null) {
((GLSurfaceView) mVideoView).onResume();
}
if (androidVideoWindowImpl != null) {
synchronized (androidVideoWindowImpl) {
if (lc == null) {
return;
}
lc.setVideoWindow(androidVideoWindowImpl);
}
}
}
And this is the relative manager (SIPManager) code of addVideo, (enableCamera,) reinviteWithVideo():
public boolean addVideo() {
LinphoneCall call = mLinphoneCore.getCurrentCall();
// No need to enable local camera
//enableCamera(call, true);
return reinviteWithVideo();
}
public void enableCamera(LinphoneCall call, boolean enable) {
if (call == null) {
return;
}
call.enableCamera(enable);
}
boolean reinviteWithVideo() {
LinphoneCall lCall = mLinphoneCore.getCurrentCall();
if (lCall == null) {
Log.e(TAG, "Trying to reinviteWithVideo while not in call: doing nothing");
return false;
}
LinphoneCallParams params = lCall.getCurrentParamsCopy();
if (params.getVideoEnabled()) return false;
params.setVideoEnabled(true);
params.setAudioBandwidth(0); // disable limitation
// Not yet in video call: try to re-invite with video
mLinphoneCore.updateCall(lCall, params);
return true;
}
The result is that I see nothing (black view) in the fragment... do you have any idea on how to resolve this thing?
Following is the full source code of the Call Fragment class:
package com.be_ssd.sipinterphone;
import android.net.Uri;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import org.linphone.core.LinphoneCore;
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
public class Call extends Fragment {
private SurfaceView mVideoView;
private AndroidVideoWindowImpl androidVideoWindowImpl;
public Call() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_call, container, false);
mVideoView = (SurfaceView) view.findViewById(R.id.callSurface);
androidVideoWindowImpl = new AndroidVideoWindowImpl(mVideoView, null, new AndroidVideoWindowImpl.VideoWindowListener() {
@Override
public void onVideoRenderingSurfaceReady(AndroidVideoWindowImpl androidVideoWindow, SurfaceView surfaceView) {
SIPManager manager = SIPManager.getInstance();
if (manager == null || manager.getLc() == null) {
return;
}
manager.getLc().setVideoWindow(androidVideoWindow);
mVideoView = surfaceView;
}
@Override
public void onVideoRenderingSurfaceDestroyed(AndroidVideoWindowImpl androidVideoWindow) {
SIPManager manager = SIPManager.getInstance();
if (manager == null) {
return;
}
LinphoneCore lc = manager.getLc();
if (lc != null) {
lc.setVideoWindow(null);
}
}
@Override
public void onVideoPreviewSurfaceReady(AndroidVideoWindowImpl androidVideoWindow, SurfaceView surfaceView) {
// video capture, ignored
}
@Override
public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl androidVideoWindow) {
// video capture, ignored
}
});
return view;
}
@Override
public void onResume() {
super.onResume();
Log.d("CallFragment", "Resumed");
SIPManager manager = SIPManager.getInstance();
LinphoneCore lc = null;
if (manager != null && manager.getLc() != null) {
lc = manager.getLc();
if (lc.getCurrentCall() != null) {
Log.d("CallFragment", "Enabling video for call");
manager.addVideo();
}
}
if (mVideoView != null) {
((GLSurfaceView) mVideoView).onResume();
}
if (androidVideoWindowImpl != null) {
synchronized (androidVideoWindowImpl) {
if (lc == null) {
return;
}
lc.setVideoWindow(androidVideoWindowImpl);
}
}
}
@Override
public void onPause() {
if (androidVideoWindowImpl != null) {
synchronized (androidVideoWindowImpl) {
/*
* this call will destroy native opengl renderer which is used by
* androidVideoWindowImpl
*/
SIPManager manager = SIPManager.getInstance();
if (manager == null || manager.getLc() == null) {
return;
}
manager.getLc().setVideoWindow(null);
}
}
if (mVideoView != null) {
((GLSurfaceView) mVideoView).onPause();
}
super.onPause();
}
@Override
public void onDestroy() {
if (mVideoView != null) {
mVideoView.setOnTouchListener(null);
mVideoView = null;
}
if (androidVideoWindowImpl != null) {
// Prevent linphone from crashing if correspondent hang up while you are rotating
androidVideoWindowImpl.release();
androidVideoWindowImpl = null;
}
super.onDestroy();
}
public interface OnFragmentInteractionListener {
public void onFragmentInteraction(Uri uri);
}
}
Thank you very much!
Giacomo Furlan
Software developer
Software Solutions Designs