# Fatal error in: ../../../home/rno/webrtc/src/pc/peer_connection.cc, line 832
# last system error: 0
# Check failed: !IsUnifiedPlan()
# AddStream is not available with Unified Plan SdpSemantics. Please use AddTrack instead.
20:35:34.782 libc com.example code -1 (SI_QUEUE) in tid 32347 (signaling_threa), pid 31746
public class Video_Voice_Call_Fragment extends Fragment {
private static final String TAG = "Video_Voice_Call_Frag";
private static final int PERMISSION_REQUEST_CODE = 1;
public static final int VIDEO_RESOLUTION_WIDTH = 1280;
public static final int VIDEO_RESOLUTION_HEIGHT = 720;
public static final int FPS = 30;
private EglBase rootEglBase;
private PeerConnectionFactory peerConnectionFactory;
private VideoCapturer videoCapturer;
private VideoSource videoSource;
private VideoTrack localVideoTrack;
private AudioTrack localAudioTrack;
private SurfaceViewRenderer localVideoView;
private SurfaceTextureHelper surfaceTextureHelper;
private SurfaceViewRenderer remoteVideoView;
private ImageButton greenCallButton;
private ImageButton redCallButton;
private MediaStream localMediaStream;
OkHttpClient client;
PeerConnection peerConnection,peerConnectionRemote;
private String FCMToken_Other;
TextView CallStatus;
ImageView UserImage;
SessionDescription localSDP;
boolean isCaller = true;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_video_voice_call, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initializePeerConnectionFactory();
setupLocalTracks();
setupUI(view);
startCall();
}
private void initializePeerConnectionFactory() {
// Initialize EGL context for rendering
rootEglBase = EglBase.create();
// Initialize PeerConnectionFactory
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(requireContext())
.setEnableInternalTracer(true)
.createInitializationOptions());
DefaultVideoEncoderFactory videoEncoderFactory = new DefaultVideoEncoderFactory(rootEglBase.getEglBaseContext(),true,true);
DefaultVideoDecoderFactory videoDecoderFactory = new DefaultVideoDecoderFactory(rootEglBase.getEglBaseContext());
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
peerConnectionFactory = PeerConnectionFactory.builder()
.setVideoDecoderFactory(videoDecoderFactory)
.setVideoEncoderFactory(videoEncoderFactory)
.setOptions(options)
.createPeerConnectionFactory();
//Set EGL context
localVideoView.init(rootEglBase.getEglBaseContext(), null);
localVideoView.setMirror(true);
}
private void setupLocalTracks() {
// Create video capturer
videoCapturer = createVideoCapturer();
// Create video source
videoSource = peerConnectionFactory.createVideoSource(false);
localVideoTrack = peerConnectionFactory.createVideoTrack("local_video", videoSource);
// Create audio source and track
AudioSource audioSource = peerConnectionFactory.createAudioSource(new MediaConstraints());
localAudioTrack = peerConnectionFactory.createAudioTrack("local_audio", audioSource);
surfaceTextureHelper = SurfaceTextureHelper.create("SurfaceHelper",rootEglBase.getEglBaseContext());
videoCapturer.initialize(surfaceTextureHelper,getActivity(),videoSource.getCapturerObserver());
if (videoCapturer!=null){
videoCapturer.startCapture(VIDEO_RESOLUTION_WIDTH,VIDEO_RESOLUTION_HEIGHT,FPS);
localVideoTrack.addSink(localVideoView);
}
// Create local media stream
localMediaStream = peerConnectionFactory.createLocalMediaStream("local_stream");
localMediaStream.addTrack(localVideoTrack);
localMediaStream.addTrack(localAudioTrack);
}
private VideoCapturer createVideoCapturer() {
VideoCapturer videoCapturer;
CameraEnumerator enumerator = new Camera2Enumerator(requireContext());
final String[] deviceNames = enumerator.getDeviceNames();
// Find front facing camera
for (String deviceName : deviceNames) {
if (enumerator.isFrontFacing(deviceName)) {
videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
// Front facing camera not found, use the first available
if (deviceNames.length > 0) {
return enumerator.createCapturer(deviceNames[0], null);
} else {
return null;
}
}
private void startCall() {
// Create an offer and set local description
peerConnection = getPeerConnection();
peerConnection.addStream(localMediaStream);
peerConnection.createOffer(new SimpleSdpObserver() {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
Log.d(TAG, "onCreateSuccess: " + sessionDescription.description);
//peerConnection.setLocalDescription(new SimpleSdpObserver(), sessionDescription);
localSDP = sessionDescription;
}
@Override
public void onCreateFailure(String s) {
Log.e(TAG, "onCreateFailure: " + s);
}
}, new MediaConstraints());
}
private PeerConnection getPeerConnection(){
ArrayList<PeerConnection.IceServer> iceServers = new ArrayList<>();
List<String> STUNList= Arrays.asList(
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302",
"stun:stun3.l.google.com:19302",
"stun:stun4.l.google.com:19302",
"stun:stun.vodafone.ro:3478",
"stun:stun.samsungsmartcam.com:3478",
"stun:stun.services.mozilla.com:3478"
);
for(String i:STUNList){
PeerConnection.IceServer.Builder iceServerBuilder = PeerConnection.IceServer.builder(i);
iceServerBuilder.setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK); //this does the magic.
PeerConnection.IceServer iceServer = iceServerBuilder.createIceServer();
iceServers.add(iceServer);
}
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
PeerConnection.Observer observer = new PeerConnection.Observer() {
@Override
public void onSignalingChange(PeerConnection.SignalingState signalingState) {
Log.d(TAG, "onSignalingChange: "+signalingState);
}
@Override
public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
Log.d(TAG, "onIceConnectionChange: "+iceConnectionState);
}
@Override
public void onIceConnectionReceivingChange(boolean b) {
Log.d(TAG, "onIceConnectionReceivingChange: Boolean = "+b);
}
@Override
public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
Log.d(TAG, "onIceGatheringChange: "+iceGatheringState);
}
@Override
public void onIceCandidate(IceCandidate iceCandidate) {
Log.d(TAG, "onIceCandidate: "+iceCandidate);
}
@Override
public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {
Log.d(TAG, "onIceCandidatesRemoved: "+iceCandidates);
}
@Override
public void onAddStream(MediaStream mediaStream) {
Log.d(TAG, "onAddStream: "+mediaStream);
}
@Override
public void onRemoveStream(MediaStream mediaStream) {
Log.d(TAG, "onRemoveStream: "+mediaStream);
}
@Override
public void onDataChannel(DataChannel dataChannel) {
Log.d(TAG, "onDataChannel: "+dataChannel);
}
@Override
public void onRenegotiationNeeded() {
Log.d(TAG, "onRenegotiationNeeded: ");
}
@Override
public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
Log.d(TAG, "onAddTrack: "+rtpReceiver+"--- "+mediaStreams);
}
};
Log.d(TAG, "generateICE: ");
return peerConnectionFactory.createPeerConnection(rtcConfig,observer);
}
}