Garmaine Staff asked 2 years ago

can somebody help me out a little? I am a little stuck.

I am trying to write a signaling process with ajax and a database involved (this is just for learning the basics of WebRTC for now). I am receiving the SDP fine from the JSON-object as it seems, but then I always get an error "Cannot create answer in stable" when I try to create an answer in get_remote_offer() for pc_partner.

I am pretty sure it is something obvious, but I am pretty new to WebRTC and just can't see what. I am using Firefox here and just trying to connect two instances of it (one in private mode, one in "normal" mode, but I am trying to make it work for remote users.

This is my code:

var opt;
var video_el_partner;
var video_el_local;
var pc_partner;
var pc_local;
var interval_gro;
var remote_offer_available = false; 

var service_url = "https://xyz.de/webrtc";
var pwd = "xxx";
var signaling_url = "https://xyz.de/webrtc/sdp_transfer.php";

function init_stream(video_partner_id, video_local_id, allow_video, allow_audio){
    if (location.protocol === 'https:') { // only possible for https!
        pc_local = new RTCPeerConnection();
        pc_partner = new RTCPeerConnection();

        if(document.getElementById(video_partner_id) != null){
            video_el_partner = document.getElementById(video_partner_id);
            video_el_local = document.getElementById(video_local_id);

            if(allow_video == null){
                allow_video = true;
            }
            if(allow_audio == null){
                allow_audio = true;
            }

            opt = { audio: allow_audio, video: allow_video }; 

            if(typeof navigator != 'undefined' && typeof navigator.mediaDevices != 'undefined' &&  navigator.mediaDevices.getUserMedia != null){
                navigator.mediaDevices.getUserMedia(opt).then (
                    function (this_stream){
                        // local video directly into video element:
                        video_el_local.srcObject = this_stream;

                        // remote one is more insteresting:
                        pc_local.addStream(this_stream);

                        pc_local.createOffer().then(
                            function (this_sdp) {
                                // sdp (session dependend protocol object) is now available... this would need to go to a server somehow now.
                                // they use socket.io for that... maybe I can use my own thing to do that?
                                pc_local.setLocalDescription(this_sdp);
                                var this_sdp_json = JSON.stringify(this_sdp)
                                var params_ins = "mode=insert_offer&sdp_con=" + this_sdp_json + "&pass=" + pwd + "&service_url=" + service_url;

                                ajax_request_simple (
                                    signaling_url, 
                                    params_ins, 
                                    function (res_ins) {
                                        // insert done. Lets read for another candidate.
                                        console.log('Set Interval!');
                                        interval_gro = window.setInterval('get_remote_offer();', 5000);
                                    }
                                );
                            }
                        );
                    }
                ).catch(
                    function (error) {
                        console.log('Problem: ');
                        console.log(error);
                    }
                );
            } else {
                console.log("navgiator or navigator.mediaDevices is not defined.");
            }
        }
    } else {
        console.log('init_stream(): We can only do anything like that on https-connections! Http is not supported by the browser!');
    }
}

window.onload = function () {
    document.getElementById('button_start_stream').onclick = function () {
        init_stream('video_partner', 'video_local', true, false);
    }
}

function is_json_str(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

function get_remote_offer() {
    var params_read = "mode=get_offer&pass=" + pwd + "&service_url=" + service_url;
    ajax_request_simple (
        signaling_url, 
        params_read, 
        function (res_read) {
            // done.
            if(is_json_str(res_read)){
                // seems like we get one now.
                // lets use that to connect and stream the video to the remote view.
                var partner_offer = res_read;
                partner_offer = JSON.parse(partner_offer);

                // clear interval if found.
                window.clearInterval(interval_gro);
                console.log('Cleared Interval. Found!');

                pc_local.setRemoteDescription(
                    new RTCSessionDescription(partner_offer), function(){
                        // video_el_partner.srcObject = event.stream;
                        pc_local.onicecandidate = function (e) {
                            if ( e.candidate != null ) {
                                pc_partner.addIceCandidate( new RTCIceCandidate(e.candidate) );
                            }
                        };

                        pc_partner.onicecandidate = function (e) {
                            if ( e.candidate != null ) {
                                pc_local.addIceCandidate( new RTCIceCandidate(e.candidate) );
                            }
                        };

                        pc_partner.createAnswer(
                            function (offer) {
                                pc_local.setRemoteDescription(offer);
                                pc_partner.setLocalDescription(offer);
                            }
                        );

                        // pc_local.ontrack = function (evt) {
                            // video_el_local.srcObject = evt.stream;
                        // };

                        pc_partner.ontrack = function (evt) {
                            video_el_partner.srcObject = evt.stream;
                        };

                    }, 
                    function(e) { 
                        console.log("Problem while doing client-answer: ", e);
                    }
                );
            } else {
                console.log("Can not parse: ");
                console.log(res_read);
            }
        }
    );
}

Sorry for the mix of promises and callbacks… I tried a couple of things out just in case… when it is working I will rewrite the callback parts. Thank you very much in advance for any hint you can give me :).

Best regards and thanks for reading till now ;).

Fuchur