I've created a simple test in which the answer to receive video contains only 
the H264 codec. The SPDs are:
Offer:
v=0
o=Mozilla-SIPUA-35.0.1 3446 0 IN IP4 0.0.0.0
s=SIP Call
t=0 0
a=ice-ufrag:5e31d4db
a=ice-pwd:c4a974d252cb15f6a15852baffa3d72f
a=fingerprint:sha-256 
21:2A:C3:90:E7:AB:B1:5C:83:75:CF:63:B0:CF:8C:81:77:76:37:1F:2C:27:D2:46:F9:6E:14:20:D9:9E:36:6D
m=video 9 RTP/SAVPF 120 126 97
c=IN IP4 0.0.0.0
a=rtpmap:120 VP8/90000
a=rtpmap:126 H264/90000
a=fmtp:126 profile-level-id=42e01f;packetization-mode=1
a=rtpmap:97 H264/90000
a=fmtp:97 profile-level-id=42e01f
a=sendrecv
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=setup:actpass
a=rtcp-mux

Answer:
v=0
o=Mozilla-SIPUA-35.0 1744 0 IN IP4 0.0.0.0
s=SIP Call
t=0 0
a=ice-ufrag:deaece8c
a=ice-pwd:ec2b99eb37c45908322798c4ebee1fa1
a=fingerprint:sha-256 
BC:D5:15:B1:81:61:3E:BB:03:EC:12:CC:F4:70:43:85:C8:56:87:12:5D:11:03:6D:6B:2A:DD:2D:6A:3D:0E:59
m=video 9 RTP/SAVPF 97
c=IN IP4 0.0.0.0
a=rtpmap:97 H264/90000
a=sendrecv
a=fmtp:97 profile-level-id=42e01f
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=setup:active
a=rtcp-mux


The offer was generated using the createOffer function call of the 
RTCPeerConnection. The answer was created from a modified SDP of the 
createAnswer function.

The test is:
<pre>
<!DOCTYPE html>
<html id="home" lang="en">
    <head><title>RTCPeerConnection Demo</title></head>

    <body>
        <article>
            <div style="text-align:center;">
                <div>
                    <video id="peer2-to-peer1" autoplay controls></video>
                     <h2>Offerer-to-Answerer</h2>

                </div>
                <div>
                    <video id="peer1-to-peer2" autoplay controls></video>
                     <h2>Answerer-to-Offerer</h2>

                </div>
            </div>
            <script>
               var mediaConstraints = {
                optional: [],
                mandatory: {
                  OfferToReceiveVideo: true
                }
              };
            </script>

            <script>
                var offerer, answerer;
                var offererToAnswerer = 
document.getElementById('peer1-to-peer2');
                var answererToOfferer = 
document.getElementById('peer2-to-peer1');

                window.RTCPeerConnection = window.mozRTCPeerConnection || 
window.webkitRTCPeerConnection;
                window.RTCSessionDescription = window.mozRTCSessionDescription 
|| window.RTCSessionDescription;
                window.RTCIceCandidate = window.mozRTCIceCandidate || 
window.RTCIceCandidate;

                navigator.getUserMedia = navigator.mozGetUserMedia || 
navigator.webkitGetUserMedia;
                window.URL = window.webkitURL || window.URL;
            </script>

            <script>
                /* offerer */

                function offererPeer(video_stream) {
                    offerer = new RTCPeerConnection(/*window.iceServers*/);
                    offerer.addStream(video_stream);

                    offerer.onaddstream = function (event) {
                        offererToAnswerer.src = 
URL.createObjectURL(event.stream);
                        offererToAnswerer.play();
                    };

                    offerer.onicecandidate = function (event) {
                        if (!event || !event.candidate) return;
                        answerer.addIceCandidate(event.candidate);
                    };

                    offerer.createOffer(function (offer) {
                        console.log("Offer:");
                        console.log(offer.sdp);
                        offerer.setLocalDescription(offer);
                        answererPeer(offer, video_stream);
                    }, function() {}, mediaConstraints);
                }
            </script>

            <script>
                /* answerer */
                function answererPeer(offer, video_stream) {
                    answerer = new RTCPeerConnection();
                    answerer.addStream(video_stream);

                    answerer.onaddstream = function (event) {
                        answererToOfferer.src = 
URL.createObjectURL(event.stream);
                        answererToOfferer.play();
                    };

                    answerer.onicecandidate = function (event) {
                        if (!event || !event.candidate) return;
                          offerer.addIceCandidate(event.candidate);
                    };

                    answerer.setRemoteDescription(offer);
                    answerer.createAnswer(function (answer) {
                        sdp = "v=0\n" +
                                "o=Mozilla-SIPUA-35.0 1744 0 IN IP4 0.0.0.0\n" +
                                "s=SIP Call\n" +
                                "t=0 0\n" +
                                "a=ice-ufrag:" + 
answer.sdp.split("a=ice-ufrag:")[1].split("\r")[0]  + "\n" +
                                "a=ice-pwd:" + 
answer.sdp.split("a=ice-pwd:")[1].substr(0, 32) + "\n" +
                                "a=fingerprint:" + "sha-256" + " " + 
answer.sdp.split("a=fingerprint:")[1].split(" ")[1].split("\n")[0] + "\n" +
                                // H264 codec payload 126
                                /*
                                "m=video 9 RTP/SAVPF 126\n" +
                                "c=IN IP4 0.0.0.0\n" +
                                "a=rtpmap:126 H264/90000\n" +
                                "a=sendrecv\n" +
                                "a=fmtp:126 
profile-level-id=42e01f;packetization-mode=1\n" +
                                "a=rtcp-fb:126 nack\n" +
                                "a=rtcp-fb:126 nack pli\n" +
                                "a=rtcp-fb:126 ccm fir\n" +
                                */
                                // H264 codec payload 97
                                "m=video 9 RTP/SAVPF 97\n" +
                                "c=IN IP4 0.0.0.0\n" +
                                "a=rtpmap:97 H264/90000\n" +
                                "a=sendrecv\n" +
                                "a=fmtp:97 profile-level-id=42e01f\n" +
                                "a=rtcp-fb:97 nack\n" +
                                "a=rtcp-fb:97 nack pli\n" +
                                "a=rtcp-fb:97 ccm fir\n" +
                                // VP8 codec
                                /*
                                "m=video 9 RTP/SAVPF 120\n" +
                                "c=IN IP4 0.0.0.0\n" +
                                "a=rtpmap:120 VP8/90000\n" +
                                "a=sendrecv\n" +
                                "a=rtcp-fb:120 nack\n" +
                                "a=rtcp-fb:120 nack pli\n" +
                                "a=rtcp-fb:120 ccm fir\n" +
                                */

                                "a=setup:active\r\n" +
                                "a=rtcp-mux\r\n";

                        console.log("Answer:");
                        console.log(sdp);

                        answer = new RTCSessionDescription({
                            type: "answer",
                            sdp: sdp
                            })

                        answer.sdp = sdp;
                        answerer.setLocalDescription(answer);
                        offerer.setRemoteDescription(answer);
                    }, function() {}, mediaConstraints);
                }
            </script>
            <script>
                var video_constraints = {
                    mandatory: {},
                    optional: []
                };

                function getUserMedia(callback) {
                    var n = navigator;
                    n.getMedia = n.webkitGetUserMedia || n.mozGetUserMedia;
                    n.getMedia({
                        video: video_constraints
                    }, callback, onerror);

                    function onerror(e) {
                        alert(JSON.stringify(e, null, '\t'));
                    }
                }
            </script>

            <script>
                getUserMedia(function (video_stream) {
                    offererPeer(video_stream);
                });
            </script>
        </article>
    </body>
</html>

</pre>

The problem which I am having is that the test works for VP8 codec bu it 
doesn't work for H264. Am I doing something wrong with the SDP? Is H264 support 
fully implemented.

Tested with Firefox 35.0.1| on Fedora 20, I've created a simple test in which 
the answer to receive video contains only the H264 codec. The SPDs are:
Offer:
v=0
o=Mozilla-SIPUA-35.0.1 3446 0 IN IP4 0.0.0.0
s=SIP Call
t=0 0
a=ice-ufrag:5e31d4db
a=ice-pwd:c4a974d252cb15f6a15852baffa3d72f
a=fingerprint:sha-256 
21:2A:C3:90:E7:AB:B1:5C:83:75:CF:63:B0:CF:8C:81:77:76:37:1F:2C:27:D2:46:F9:6E:14:20:D9:9E:36:6D
m=video 9 RTP/SAVPF 120 126 97
c=IN IP4 0.0.0.0
a=rtpmap:120 VP8/90000
a=rtpmap:126 H264/90000
a=fmtp:126 profile-level-id=42e01f;packetization-mode=1
a=rtpmap:97 H264/90000
a=fmtp:97 profile-level-id=42e01f
a=sendrecv
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=setup:actpass
a=rtcp-mux

Answer:
v=0
o=Mozilla-SIPUA-35.0 1744 0 IN IP4 0.0.0.0
s=SIP Call
t=0 0
a=ice-ufrag:deaece8c
a=ice-pwd:ec2b99eb37c45908322798c4ebee1fa1
a=fingerprint:sha-256 
BC:D5:15:B1:81:61:3E:BB:03:EC:12:CC:F4:70:43:85:C8:56:87:12:5D:11:03:6D:6B:2A:DD:2D:6A:3D:0E:59
m=video 9 RTP/SAVPF 97
c=IN IP4 0.0.0.0
a=rtpmap:97 H264/90000
a=sendrecv
a=fmtp:97 profile-level-id=42e01f
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=setup:active
a=rtcp-mux


The offer was generated using the createOffer function call of the 
RTCPeerConnection. The answer was created from a modified SDP of the 
createAnswer function.

The test is:
<pre>
<!DOCTYPE html>
<html id="home" lang="en">
    <head><title>RTCPeerConnection Demo</title></head>

    <body>
        <article>
            <div style="text-align:center;">
                <div>
                    <video id="peer2-to-peer1" autoplay controls></video>
                     <h2>Offerer-to-Answerer</h2>

                </div>
                <div>
                    <video id="peer1-to-peer2" autoplay controls></video>
                     <h2>Answerer-to-Offerer</h2>

                </div>
            </div>
            <script>
               var mediaConstraints = {
                optional: [],
                mandatory: {
                  OfferToReceiveVideo: true
                }
              };
            </script>

            <script>
                var offerer, answerer;
                var offererToAnswerer = 
document.getElementById('peer1-to-peer2');
                var answererToOfferer = 
document.getElementById('peer2-to-peer1');

                window.RTCPeerConnection = window.mozRTCPeerConnection || 
window.webkitRTCPeerConnection;
                window.RTCSessionDescription = window.mozRTCSessionDescription 
|| window.RTCSessionDescription;
                window.RTCIceCandidate = window.mozRTCIceCandidate || 
window.RTCIceCandidate;

                navigator.getUserMedia = navigator.mozGetUserMedia || 
navigator.webkitGetUserMedia;
                window.URL = window.webkitURL || window.URL;
            </script>

            <script>
                /* offerer */

                function offererPeer(video_stream) {
                    offerer = new RTCPeerConnection(/*window.iceServers*/);
                    offerer.addStream(video_stream);

                    offerer.onaddstream = function (event) {
                        offererToAnswerer.src = 
URL.createObjectURL(event.stream);
                        offererToAnswerer.play();
                    };

                    offerer.onicecandidate = function (event) {
                        if (!event || !event.candidate) return;
                        answerer.addIceCandidate(event.candidate);
                    };

                    offerer.createOffer(function (offer) {
                        console.log("Offer:");
                        console.log(offer.sdp);
                        offerer.setLocalDescription(offer);
                        answererPeer(offer, video_stream);
                    }, function() {}, mediaConstraints);
                }
            </script>

            <script>
                /* answerer */
                function answererPeer(offer, video_stream) {
                    answerer = new RTCPeerConnection();
                    answerer.addStream(video_stream);

                    answerer.onaddstream = function (event) {
                        answererToOfferer.src = 
URL.createObjectURL(event.stream);
                        answererToOfferer.play();
                    };

                    answerer.onicecandidate = function (event) {
                        if (!event || !event.candidate) return;
                          offerer.addIceCandidate(event.candidate);
                    };

                    answerer.setRemoteDescription(offer);
                    answerer.createAnswer(function (answer) {
                        sdp = "v=0\n" +
                                "o=Mozilla-SIPUA-35.0 1744 0 IN IP4 0.0.0.0\n" +
                                "s=SIP Call\n" +
                                "t=0 0\n" +
                                "a=ice-ufrag:" + 
answer.sdp.split("a=ice-ufrag:")[1].split("\r")[0]  + "\n" +
                                "a=ice-pwd:" + 
answer.sdp.split("a=ice-pwd:")[1].substr(0, 32) + "\n" +
                                "a=fingerprint:" + "sha-256" + " " + 
answer.sdp.split("a=fingerprint:")[1].split(" ")[1].split("\n")[0] + "\n" +
                                // H264 codec payload 126
                                /*
                                "m=video 9 RTP/SAVPF 126\n" +
                                "c=IN IP4 0.0.0.0\n" +
                                "a=rtpmap:126 H264/90000\n" +
                                "a=sendrecv\n" +
                                "a=fmtp:126 
profile-level-id=42e01f;packetization-mode=1\n" +
                                "a=rtcp-fb:126 nack\n" +
                                "a=rtcp-fb:126 nack pli\n" +
                                "a=rtcp-fb:126 ccm fir\n" +
                                */
                                // H264 codec payload 97
                                "m=video 9 RTP/SAVPF 97\n" +
                                "c=IN IP4 0.0.0.0\n" +
                                "a=rtpmap:97 H264/90000\n" +
                                "a=sendrecv\n" +
                                "a=fmtp:97 profile-level-id=42e01f\n" +
                                "a=rtcp-fb:97 nack\n" +
                                "a=rtcp-fb:97 nack pli\n" +
                                "a=rtcp-fb:97 ccm fir\n" +
                                // VP8 codec
                                /*
                                "m=video 9 RTP/SAVPF 120\n" +
                                "c=IN IP4 0.0.0.0\n" +
                                "a=rtpmap:120 VP8/90000\n" +
                                "a=sendrecv\n" +
                                "a=rtcp-fb:120 nack\n" +
                                "a=rtcp-fb:120 nack pli\n" +
                                "a=rtcp-fb:120 ccm fir\n" +
                                */

                                "a=setup:active\r\n" +
                                "a=rtcp-mux\r\n";

                        console.log("Answer:");
                        console.log(sdp);

                        answer = new RTCSessionDescription({
                            type: "answer",
                            sdp: sdp
                            })

                        answer.sdp = sdp;
                        answerer.setLocalDescription(answer);
                        offerer.setRemoteDescription(answer);
                    }, function() {}, mediaConstraints);
                }
            </script>
            <script>
                var video_constraints = {
                    mandatory: {},
                    optional: []
                };

                function getUserMedia(callback) {
                    var n = navigator;
                    n.getMedia = n.webkitGetUserMedia || n.mozGetUserMedia;
                    n.getMedia({
                        video: video_constraints
                    }, callback, onerror);

                    function onerror(e) {
                        alert(JSON.stringify(e, null, '\t'));
                    }
                }
            </script>

            <script>
                getUserMedia(function (video_stream) {
                    offererPeer(video_stream);
                });
            </script>
        </article>
    </body>
</html>

</pre>

The problem which I am having is that the test works for VP8 codec but it 
doesn't work for H264. 
Am I doing something wrong with the SDP negotiation? 
Is H264 support implemented all the way or only the negotiation part is 
implemented?

Tested with Firefox 35.0.1| on Fedora 20, OpenH264 1.3.
_______________________________________________
dev-media mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-media

Reply via email to