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