Which codec will be used after sdp exchange in WebRTC? - webrtc

In a WebRTC video call
A->B a SDP offer, it means that A supports VP8, VP9 and H264
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 124 125
a=sendrecv
a=rtpmap:96 VP8/90000
...
a=rtpmap:98 VP9/90000
...
a=rtpmap:100 H264/90000
while B->A answered a SDP answer, it also means that B supports VP8, VP9 and H264
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 124 125
a=sendrecv
a=rtpmap:96 VP8/90000
...
a=rtpmap:98 VP9/90000
...
a=rtpmap:100 H264/90000
...
My question is in this case, which codec will be used? How A or B knows another choice?
Thanks

The answer can be found in RFC3264.
Section 5.1:
If multiple formats are listed, it
means that the offerer is capable of making use of any of those
formats during the session. In other words, the answerer MAY change
formats in the middle of the session, making use of any of the
formats listed, without sending a new offer.
The offerer will list the supported codecs in order of preference in the m-line. The answerer will most likely honor that preference, but is not obliged to do so. See Section 6.1:
Although the answerer MAY list the formats in their desired order of
preference, it is RECOMMENDED that unless there is a specific reason,
the answerer list formats in the same relative order they were
present in the offer.
Section 7:
When the offerer receives the answer, it MAY send media on the
accepted stream(s) (assuming it is listed as sendrecv or recvonly in
the answer). It MUST send using a media format listed in the answer,
and it SHOULD use the first media format listed in the answer when it
does send.
So in short: the offerer and answerer will most likely use the first codec in the answerer's m-line and this may change during the media session.

B signals that it would prefer 96, i.e. VP8 since that is listed first in the m= line formats.
https://webrtc.github.io/samples/src/content/peerconnection/change-codecs/ has a sample allows you to change the order of codecs and inspect the results.

Related

Why does Chome choose the wrong video codec in webrtc connection?

So I have two peers, Alice and Bob. Alice wants to receive video from Bob but not send her own. Bob does not support VP8/9, only h.264. Currently the webrtc connection is established without errors, but Alice sees a purple mess for video. The video displays correctly after modifying the offer m line.
In more detail.. Alice creates an offer with the following m line and sends to Bob. Stream ids 96 - 101 use vp8 or vp9 codecs. ids > 101 use h.264.
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123 119 114 115 116
Since Bob does not support vp8 or vp9, his answer contains the following m line:
m=video 9 UDP/TLS/RTP/SAVPF 102 122 127 121 125 107 108 109 114 115 116
Alice receives the answer from Bob, calls setRemoteDescription, then gets the ontrack callback, and then the setRemoteDescriptionFinished callback.
I would expect Alice’s browser (Chrome 79.0.3945.130, Mac) to choose 102 and use an h.264 decoder. The purple, garbled video looks suspiciously like video data being decoded by the wrong decoder.
So as an experiment I removed the entries in the 96 - 101 range from Alice’s offer before setLocalDescription and before sending to Bob. With this change the video displays correctly.
Does someone more knowledgable about webrtc have any idea what might cause Chrome to choose a stream not present in the peer answer?
I am in the process of testing this on other browsers and simplifying the code for more testing.
Also worth noting is that only the offer passed to setLocalDescription needs to be modified. If the unmodified offer is then sent to Bob, video is still displayed correctly.
According to webrtc-internals, Alice's Chrome is indeed selecting 96 (VP8) as the format of the inbound-rtp stream, even though it is H264.

webrtc and peerjs: how to choose H264 instead of vp8?

I do use peerjs https://peerjs.com to stablish connection between 2 peers.
Is there a way to force the use of H264 code instead of VP8 ?
Regards
Update:
You can use setCodecPreferences to achieve the same result, once browsers support it.
Old Answer:
You will have to edit the peerjs code to change codecs.
Basically you will have to update the SDP , more specifically, the video line in the sdp.
The video line will look something like
m=video 60372 UDP/TLS/RTP/SAVPF 96 98 100 101 116 111
The numbers 100 101 etc correspond to the various codecs that the peer support, they are represented by lines like the following:
a=rtpmap:98 VP9/90000
a=rtpmap:96 VP8/90000
So you have to first get the sdp and find out the number for the H264 codec, next move the number to the beginning of the list in the video line.
For example, if 100 is the number of the H264 codec, you need to change the above video line to
m=video 60372 UDP/TLS/RTP/SAVPF 100 96 98 101 116 111
For the caller side, modify the sdp after creating the offer but before setting the localDescription
pc.createOffer().then(function(offer) {
sdp = offer.sdp;
changedsdp = updateCodec(sdp) //Function to modify the sdp
offer.sdp = changedsdp
pc.setLocalDescription(offer)
For the answerer side, modify the sdp after create answer
pc.createAnswer(function(answer) {
sdp = answer.sdp;
changedsdp = updateCodec(sdp) //Function to modify the sdp
answer.sdp = changedsdp
pc.setLocalDescription(answer)

Understanding SDP generated by WebRTC

I went to chrome://webrtc-internals/ to copy the sdp. Overall, I'd like to understand the meaning.
setRemoteDescription
type: answer, sdp: v=0
o=mozilla...THIS_IS_SDPARTA-39.0 6618245136742574887 0 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 27:8B:F6:1A:72:47:17:2B:23:C1:9A:85:AB:3A:E0:29:15:B9:F5:B0:B6:EA:17:C9:11:99:AA:B7:AB:45:A9:60
a=ice-options:trickle
a=msid-semantic:WMS *
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=sendrecv
a=ice-pwd:a33017ce6eae687d1afdae61c9f0db55
a=ice-ufrag:f8acf035
a=mid:data
a=sctpmap:5000 webrtc-datachannel 256
a=setup:active
Specifically, I'd like the understand the meaning of
a=sctpmap:5000 webrtc-datachannel 256
The format of the sctpmap attribute is defined as:
The sctpmap attribute maps from a port number (as used in an "m="
line) to an encoding name denoting the payload format to be used on
top of the SCTP association or the actual protocol running on top of
it.
The sctpmap MUST include the app parameter indicating the application
running on top of the association.
The sctpmap line should also contain the max-message-size parameter
indicating the maximum message size, in bytes, the endpoint is
willing to accept.
So the line a=sctpmap:5000 webrtc-datachannel 256 Is indicating port 5000, an application name of 'webrtc-datachannel' and a message size of 256 bytes.
This is in your generated SDP because your application is making use of datachannels on your PeerConnection.

Difference Between POS Entry Modes (Field 22)

I was wondering if anyone could help me understand difference between ISO 8583 Field 22 i.e. POS Entry Mode. I already know that:
52 means ICC Card
80 in case of fallback
But what I want to know is difference between
22 (Magnetic Stripe)
and 90
Can anyone help me on this?
The length of Field 22 usually 3-digits (or 4-digits in case it is BCD packed into two Bytes) in protocols based on ISO 8583:1987 or 12-digits in case protocols based on ISO 8583:1993 version. Customized protocols could use different sub-fields content and values meaning behind.
While you use short values in the requested question, I guess, your Field 22 based on ISO 8583:1987 version and you lost the leading and/or ending zero. So, your sample values becomes 3 digits length - 052, 800, 022, and 090 or 900.
Usually the 3-digits Field 22 splited into two sub-fields:
Position 1 and 2 - Personal Account Number (PAN) Entry (or capability);
Position 3 - Personal Identification Number (PIN) Entry (or capability);
Here are the possible interpretations:
02 - PAN auto-entry via magnetic stripe, track data is not required, 2 - no PIN.
05 - PAN auto-entry via chip, 2 - no PIN.
09 - E-Commerce, 0 - unknown PIN capability.
80 - Fallback to magnetic stripe, 0 - unknown PIN capability.
90 - PAN auto-entry via magnetic stripe, track data should be transmitted within the authorization request, 0 - unknown PIN capability.
etc.
90 used in case track data present in the ISO 8583 request message, 02 - if, for same reason, acquirer or terminal device not qualified to transfer track data in the request messages.
Depending of protocol requirements could be exceptions with Field 22 values. It is usually checked during the terminal device and communication interface certifications.
I will elaborate few things here. From above comments I can see that 09 is for E commerce transactions,but as per my knowledge for E commerce transactions we should use PAN Entry mode as 01(manual entry). Because for card not present transactions entry mode has always in manually.
POS Entry mode says whether the particular transaction is E commerce or POS. The possible values are :
01 Manual entry
02 Magnetic Stripe,track 2 data will ignore
05 Smart card,track 2 data required
90 Magnetic stripe no track 2 data
91 contactless card
95 Smart card , track2 data not required
Thanks share your ideas on this

Troubleshooting WebRTC code

I'm pulling my hair out with this one. A month or so ago, I was able to put together a proof-of-concept WebRTC demo, using some sample code from the good folks at SignalR. The demo is located here, the source for it is here, and it does what it's supposed to do.
But when I took that code and moved it into our actual application, I haven't been able to get it to work. Of course the code had to be changed significantly - different backends, different set of frameworks and supporting code, supporting multiple simultaneous connections, that sort of thing - but the core logic is very similar. But I can't get it to work.
I've put together a sample app here that demonstrates the problem:
https://bitbucket.org/smithkl42/signalr.webrtc
The core WebRTC logic is all in this TypeScript file:
https://bitbucket.org/smithkl42/signalr.webrtc/src/tip/SignalR.WebRTC/Scripts/Media/WebRTC.ts?at=default
It's several hundred lines long, so I won't bother posting it here, but you can see it by clicking on the link above.
When it runs, it produces output like this:
12:17:58.531 WebRTCController.call(): Calling 7d9e0d39-5047-4afe-86e5-e6e01b9f5955 when preparations have finished
12:17:58.533 WebRTCController.prepareForCall(): Preparing for call: localSessionId='39d2df53-6854-415a-8748-b5230eda2eb1'; remoteSessionId='7d9e0d39-5047-4afe-86e5-e6e01b9f5955'
12:18:0.139 Object.(): The user has granted media device access, so proceeding to prepare for call
12:18:0.141 Connection.createPeerConnection(): Creating peer connection; using stunServer stun:stun1.l.google.com:19302
12:18:0.144 (): Preparations finished. Creating and sending JSEP offer. Util.js:21
12:18:0.272 Connection.handleIceCandidate(): STUN server has found an ICE candidate (event.type='icecandidate').
12:18:0.282 Connection.handleIceCandidate(): STUN server has found an ICE candidate (event.type='icecandidate').
(More like that)
12:18:0.655 WebRTCController.handleJsepAnswer(): Handling JsepAnswer from 7d9e0d39-5047-4afe-86e5-e6e01b9f5955
12:18:0.694 Object.(): Sending ICE candidate to the remote machine: {"sdpMLineIndex":0,"sdpMid":"audio","candidate":"a=candidate:2999745851 1 udp 2113937151 192.168.56.1 62978 typ host generation 0\r\n"}
12:18:0.706 Object.(): Sending ICE candidate to the remote machine: {"sdpMLineIndex":0,"sdpMid":"audio","candidate":"a=candidate:2999745851 2 udp 2113937151 192.168.56.1 62978 typ host generation 0\r\n"}
(More like that)
But then it never connects, i.e., the video from the other side never starts playing. At the signaling layer, I can tell by the logs and by stepping through the code that the first browser is sending a JSEP offer; the second browser is receiving it, storing it and sending back an appropriate JSEP answer; and the first machine is storing that answer. Each peerConnection is then finding the ICE candidates and sending them to the remote machine; and each peerConnection is receiving and apparently trying those ICE candidates; and the peerConnections are even raising the onaddstream event. But the video never starts playing.
The state of the peerConnection object all the way through looks like this:
(iceGatheringState=new; iceState=starting; readyState=active)
The frustrating bit is that every so often, maybe one time out of 20, it does work, i.e., both videos show up. So I'm not doing everything wrong. It sounds like a timing issue of some sort - but I can't figure out what it is. And so far as I can tell, there's not much in the WebRTC objects (specifically RTCPeerConnection) to tell you what's going wrong.
I hate to ask anybody else to do my troubleshooting for me, but... well, I'm running out of options. Does anybody else see anything I'm doing obviously wrong?
Update 2012-12-19: I'm making some progress. I realized I was calling peerConnection.setLocalDescription() synchronously, i.e., without specifying callbacks. So now I've got some lines of code that look like this:
// Answer the call by sending a JsepAnswer message.
connection.peerConnection.createAnswer(
answer => {
connection.peerConnection.setLocalDescription(answer, () => {
var signalState: mData.SignalState = {
FromSessionId: connection.localSessionId,
ToSessionId: connection.remoteSessionId,
Message: JSON.stringify(answer)
};
me.roomHub.server.jsepAnswer(signalState);
mUtil.log("Sent JSEP answer: " + signalState.Message);
connection.readyForIceCandidates.resolve();
},
error => {
mUtil.error("Error setting local description from created answer: " + error + "; answer=" + JSON.stringify(answer));
});
},
error => {
mUtil.error("Error creating answer: " + error);
}, me.mediaConstraints);
And the setLocalDescription() error callback is showing this error:
16:14:42.439 WebRTCController.handleJsepOffer(): Error setting local description from created answer: SetLocalDescription failed.; answer={"sdp":"v=0\r\no=- 439659381 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf\r\nm=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:vOKflTJ56gV0R9i0\r\na=ice-pwd:9nuXPMDvQ2mZATFCQyEzPRQz\r\na=sendrecv\r\na=mid:audio\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:m9q9pmLgLuFnfFC09KXKW5p8TjsKk+VdqX0OWv77\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:111 opus/48000/2\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:107 CN/48000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:548068416 cname:IXg8QRisWrd7+7f8\r\na=ssrc:548068416 msid:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf a0\r\na=ssrc:548068416 mslabel:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf\r\na=ssrc:548068416 label:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjfa0\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:vOKflTJ56gV0R9i0\r\na=ice-pwd:9nuXPMDvQ2mZATFCQyEzPRQz\r\na=sendrecv\r\na=mid:video\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:m9q9pmLgLuFnfFC09KXKW5p8TjsKk+VdqX0OWv77\r\na=rtpmap:100 VP8/90000\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=ssrc:1460425980 cname:IXg8QRisWrd7+7f8\r\na=ssrc:1460425980 msid:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf v0\r\na=ssrc:1460425980 mslabel:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf\r\na=ssrc:1460425980 label:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjfv0\r\n","type":"answer"}
Now I just need to figure out why that particular SDP - which comes straight from the createAnswer() method - is failing.
Update 2012-12-20: I've created an online demonstration of the problem here: http://srdemo.alanta.com/. I've also turned on Chrome debug logging, with the result that I see a bunch of errors that look like this:
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.
Not sure what relationship they have to my problem, but I'm continuing to look into it.
*Edit 2012-12-20: I've managed (I think) to narrow the problem down. See this question for more precise details.
Figured it out. Turns out that SignalR 1.0 RC1 has a bug in it that changes any "+" in a string into a space. So lines in the SDP that looked like this:
a=ice-pwd:qZFVvgfnSso1b8UV1SUDd2+z
Were getting changed into this:
a=ice-pwd:qZFVvgfnSso1b8UV1SUDd2 z
But because not every SDP had a "+" in it on a critical line, sometimes it would work. Everything explained.
The bug has been reported to the good folks working on SignalR (see https://github.com/SignalR/SignalR/issues/1194), and in the meantime, a simple encodeURIComponent() and decodeURIComponent() around the strings in question fixed it.