Im a new react native learner trying to implement video call with web rtc. I am now facing an issue which i have a blank remote video call. I checked my logging and i can see that my web rtc has logged onIceGatheringChangeCOMPLETE but for some reason the frames received on my remote stream is always this EglRenderer: Duration: 4007 ms. Frames received: 0. Dropped: 0. Rendered: 0. Render fps: .0. Average render time: NA. Average swapBuffer time: NA.
Attached is my code
function ConnectScreen2({ route }) {
const ctx = useContext(AuthContext)
const MyRandomId = "554433";
const [localStream, setLocalStream] = useState();
const [remoteStream, setRemoteStream] = useState();
// for ending call
const [CachedLocalPC, setCachedLocalPC] = useState();
const ref = collection(firebase, "Room");
const targetCollectionRef = collection(firebase, "expenses");
let timer = null;
function SnapShotAndSetICE(Collection, MyPC) {
console.log("SnapShotAndSetICE cached local " + MyPC);
onSnapshot(Collection, (snapshot) => {
snapshot.docChanges().forEach((change) => {
if (change.type === "added") {
let data = change.doc.data();
console.log("Addcaller " + data.candidate);
MyPC.addIceCandidate(new RTCIceCandidate(data));
}
});
});
}
async function StartCall2() {
const localPC = new RTCPeerConnection(peerConstraints);
console.log("StartCall2");
const UserRef = doc(ref, MyRandomId);
localStream.getTracks().forEach((track) => {
localPC.addTrack(track, localStream);
});
const roomRef = doc(ref, MyRandomId);
const callerCandidatesCollection = collection(roomRef, "callerCandidates");
const calleeCandidatesCollection = collection(roomRef, "calleeCandidates");
//setup when ice candidate is added add to doc
localPC.addEventListener("icecandidate", (e) => {
if (!e.candidate) {
return;
}
try { addDoc(callerCandidatesCollection, e.candidate.toJSON()) }
catch (error) {
console.log("OnAdd ice candidate error");
}
});
// setup to listen for when remote stream is added
localPC.ontrack = (e) => {
console.log("on track " + e.streams.length);
const newStream = new MediaStream();
if (e.streams.length > 0) {
e.streams[0].getTracks().forEach((track) => {
newStream.addTrack(track);
});
console.log("start call Remote stream " + newStream.toURL())
setRemoteStream(newStream);
}
};
// make offer
let offer = null
try {
console.log("Start call create offer");
offer = await localPC.createOffer();
}
catch (error) {
console.log("Start call create offer fail");
}
try {
await localPC.setLocalDescription(offer);
}
catch (error) {
console.log("Start call setLocalDescription fail");
}
await setDoc(roomRef, { offer, connected: false, RoomDetails: { HostName: ctx.UserName } }, { merge: true });
// Listen for remote answer
onSnapshot(roomRef, (doc) => {
console.log(" Start call SetupRemoteDescription2 " + localPC);
const data = doc.data();
if (!localPC.currentRemoteDescription && data.answer) {
const rtcSessionDescription = new RTCSessionDescription(data.answer);
localPC.setRemoteDescription(rtcSessionDescription);
//timer=setTimeout(SnapShotAndSetICE.bind(this,calleeCandidatesCollection,CachedLocalPC),10000);
SnapShotAndSetICE(calleeCandidatesCollection, localPC);
console.log("local pc " + localPC.iceConnectionState)
}
else {
setRemoteStream();
}
});
const TargetRef = doc(targetCollectionRef, route.params.targetuid);
await setDoc(TargetRef, { InvitationId: MyRandomId }, { merge: true });
console.log("ice connection 3 " + localPC.iceConnectionState + " signal str " + localPC.signalingState);
setCachedLocalPC(localPC)
setInterval(checkIce, 5000, localPC);
}
///// join call
async function JoinCall() {
const localPC = new RTCPeerConnection(peerConstraints);
const roomRef = doc(ref, route.params.id);
const roomSnapshot = await getDoc(roomRef);
console.log("join call");
if (!roomSnapshot.exists) {
console.log("Join call no room exist");
return;
}
localStream.getTracks().forEach((track) => {
localPC.addTrack(track, localStream);
});
const callerCandidatesCollection = collection(roomRef, "callerCandidates");
const calleeCandidatesCollection = collection(roomRef, "calleeCandidates");
localPC.addEventListener("icecandidate", (e) => {
if (!e.candidate) {
return;
}
addDoc(calleeCandidatesCollection, e.candidate.toJSON());
});
localPC.ontrack = (e) => {
const newStream = new MediaStream();
e.streams[0].getTracks().forEach((track) => {
newStream.addTrack(track);
});
console.log("Join call Remote stream " + newStream.toURL())
setRemoteStream(newStream);
};
let answer = null;
const offer = roomSnapshot.data().offer;
if (!localPC.currentLocalDescription) {
try { await localPC.setRemoteDescription(new RTCSessionDescription(offer)); }
catch (error) {
console.log("create new remote description fail");
}
try { answer = await localPC.createAnswer(); }
catch (error) {
console.log("create createAnswer fail");
}
try { await localPC.setLocalDescription(answer); }
catch (error) {
console.log("localdescription fail");
}
//timer=setTimeout(SnapShotAndSetICE.bind(this,callerCandidatesCollection,CachedLocalPC),10000);
SnapShotAndSetICE(callerCandidatesCollection, localPC);
}
await updateDoc(roomRef, { answer, connected: true }, { merge: true });
setCachedLocalPC(localPC);
setInterval(checkIce, 5000, localPC);
}
function checkIce(MyPC) {//console.log("ice connection 4");
if (MyPC) {
console.log("ice connection 4" + MyPC.iceConnectionState + " signal str " + MyPC.signalingState);
}
else {
console.log("CachedLocalPC " + MyPC);
}
//
}
useEffect(() => {
async function SetupStream() {
const Stream = await GetStreams();
setLocalStream(Stream);
console.log("Stream " + Stream);
}
async function Setups() {
await SetupStream();
}
Setups();
}, []);
useEffect(() => {
if (localStream) {
if (route.params.StartCall === true) {
StartCall2();
}
else {
JoinCall();
}
}
}, [localStream])
const peerConstraints = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' },
{ urls: 'stun:stun2.l.google.com:19302' },
{ urls: 'stun:stun3.l.google.com:19302' },
{ urls: 'turn:numb.viagenie.ca', credential: 'muazkh', username: '[email protected]' },
{ urls: 'turn:relay.backups.cz', credential: 'webrtc', username: 'webrtc' },
{ urls: 'turn:relay.backups.cz?transport=tcp', credential: 'webrtc', username: 'webrtc' },
{ urls: 'turn:192.158.29.39:3478?transport=udp', credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=', username: '28224511:1379330808' },
]
};
return (
<View className="flex-1 bg-red-600" style={styles.MainContainer}>
{!remoteStream && (
<View style={styles.LocalCamContainer} >
<Text style={styles.Text}> MyCam</Text>
<RTCView
className="flex-1"
streamURL={localStream && localStream.toURL()}
objectFit={"cover"}
style={styles.LocalCamContainer}
/>
</View>
)}
{remoteStream && (
<View style={styles.LocalCamContainer} >
<RTCView
className="flex-1"
streamURL={localStream && localStream.toURL()}
objectFit={"cover"}
style={styles.LocalCamContainer}
/>
{(
<RTCView
className="flex-1"
streamURL={remoteStream && remoteStream.toURL()}
objectFit={"cover"}
style={styles.LocalCamContainer}
/>
)}
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
MainContainer:
{
flex: 1
},
LocalCamContainer:
{
flex: 1,
backgroundColor: "red",
borderRadius: 8
},
Text:
{
alignItems: "center",
justifyContent: "center"
}
})
export default ConnectScreen2;