Why is Chrom changing recvonly to sendrecv and adding an empty track?

297 views
Skip to first unread message

Neil Young

unread,
Mar 13, 2023, 7:39:15 AM3/13/23
to discuss-webrtc
I don't notice this behaviour in Firefox, just saying.

I'm having a pub/sub scenario. The publisher receives an incoming SDP offer, which indicates, that the offering counterpart just wants to receive.

v=0
o=- 3887695198 3887695198 IN IP4 0.0.0.0
s=Kurento Media Server
c=IN IP4 0.0.0.0
t=0 0
a=group:BUNDLE video0 application0
m=video 1 RTP/SAVPF 98 97
b=AS:3000
a=setup:actpass
a=rtpmap:97 VP8/90000
a=rtpmap:98 H264/90000
a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtcp:9 IN IP4 0.0.0.0
a=rtcp-mux
a=recvonly
a=mid:video0
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 goog-remb
a=rtcp-fb:97 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 ccm fir
a=ssrc:1753972885 cname:user3608127389@host-fd881d7b
a=ice-ufrag:3BIz
a=ice-pwd:XnpCdATa3P/IqbzWW/1rTb
a=fingerprint:sha-256 98:F6:3A:30:3F:9C:67:F1:E1:6C:92:30:F3:64:B6:58:C6:42:74:3A:9C:65:69:7C:E4:A1:5A:3C:71:16:D4:59
m=application 1 UDP/DTLS/SCTP webrtc-datachannel
a=setup:actpass
a=sctp-port:5000
a=mid:application0
a=ice-ufrag:3BIz
a=ice-pwd:XnpCdATa3P/IqbzWW/1rTb
a=fingerprint:sha-256 98:F6:3A:30:3F:9C:67:F1:E1:6C:92:30:F3:64:B6:58:C6:42:74:3A:9C:65:69:7C:E4:A1:5A:3C:71:16:D4:59

In WebRTC Internals I can see, that immediately after "setRemoteDescription" this trace appears

13.3.2023, 12:19:58
transceiverModified
Caused by: setRemoteDescription

getTransceivers()[0]:{
  mid:'video0',
  kind:'video',
  sender:{
    track:'91d4b3a5-77f9-433d-ae21-702f922b5047',
    streams:['eGbBp0indrMtRCmQKYYGv7PT3f4HWv7NlJ6t'],
  },
  receiver:{
    track:'2aac05ca-a9d8-48bc-88f1-a1cc0b74d729',
    streams:[],
  },
  direction:'sendrecv',
  currentDirection:null,
}

So a "transceiverModified" (making recvonly to sendrecv) with an empty receiver track.

This track later on appears in all stats visible as empty and inactive (because not existent, IMHO)

Basically I would treat this just as an annoyance, but in fact I would not expect any kind of "received track" because of the "recvonly" setup.

inbound-rtp (kind=video, mid=video0, ssrc=1753972885, id=ITvideo01V1753972885)
Statistics ITvideo01V1753972885
timestamp 13.3.2023, 12:38:29
ssrc 1753972885
kind video
transportId Tvideo01
mediaType video
jitter 0
packetsLost 0
mid video0
packetsReceived 0
[packetsReceived/s] 0
bytesReceived 0
[bytesReceived_in_bits/s] 0
headerBytesReceived 0
[headerBytesReceived_in_bits/s] 0
jitterBufferDelay 0
[jitterBufferDelay/jitterBufferEmittedCount_in_ms] 0
jitterBufferEmittedCount 0
framesReceived 0
[framesReceived/s] 0
[framesReceived-framesDecoded-framesDropped] 0
framesDecoded 0
[framesDecoded/s] 0
keyFramesDecoded 0
[keyFramesDecoded/s] 0
framesDropped 0
totalDecodeTime 0
[totalDecodeTime/framesDecoded_in_ms] 0
totalProcessingDelay 0
[totalProcessingDelay/framesDecoded_in_ms] 0
totalAssemblyTime 0
[totalAssemblyTime/framesAssembledFromMultiplePackets_in_ms] 0
framesAssembledFromMultiplePackets 0
totalInterFrameDelay 0
[totalInterFrameDelay/framesDecoded_in_ms] 0
totalSquaredInterFrameDelay 0
[interFrameDelayStDev_in_ms] 0
pauseCount 0
totalPausesDuration 0
freezeCount 0
totalFreezesDuration 0
decoderImplementation unknown
firCount 0
pliCount 0
nackCount 0
minPlayoutDelay* 0

Harald Alvestrand

unread,
Mar 13, 2023, 12:35:32 PM3/13/23
to discuss...@googlegroups.com
A transceiver is always created with a receiver. See https://w3c.github.io/webrtc-pc/#set-the-session-description, search for "create an rtcrtptransceiver". We designed it like tht in order to not have to write special code for checking whether the receiver existed or not.

your description says "currentDirection: null", and "direction: sendrecv".
This indicates that the snapshot was taken boefre the offer/answer process had concluded. Please show what the value was after the offer/answer had finished.


--

---
You received this message because you are subscribed to the Google Groups "discuss-webrtc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrt...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/discuss-webrtc/76510d3f-d356-4992-bc5a-21238a27c2b5n%40googlegroups.com.

Neil Young

unread,
Mar 13, 2023, 12:39:14 PM3/13/23
to discuss-webrtc
Hi Harald,

thanks for the answer. Does this answer your question?
WebRTC_Internals.png

Harald Alvestrand

unread,
Mar 13, 2023, 12:53:08 PM3/13/23
to discuss...@googlegroups.com
Thank you, this shows that "currentDirection" correctly changes to "sendonly", which is the right change given that the remote is "recvonly".

I take it that this transceiver was created by AddTrack() followed by a negotiation where the remote end set direction to "recvonly"?

The direction attribute is (by design) not modified by the negotiation - addTrack (https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtrack) will by default create the transceiver with direction "sendrecv"; you can set the direction attribute later, in order to ensure that if you do a CreateOffer later, the requested direction is "sendonly", but by default it will remain "sendrecv".

I think the spec is followed; the spec may be confusing, but it seems to be followed.



Neil Young

unread,
Mar 13, 2023, 1:00:40 PM3/13/23
to discuss-webrtc
I'm calling `addTrack()` just once in my code within a function called `acquireLocalMedia()`. This function is called on an incoming OFFER, after `createPeerConnection()`:

`mediaOptions` is formed from some outer configuration. In this case `sendAudio` was false and `sendVideo` with an object defining desired resolution and facingMode.

// Acquire local media streams according to options
acquireLocalMedia = async () => {
if (!this.sendAudio && !this.sendVideo) {
return // Nothing to do here
}

let mediaOptions = { audio: this.sendAudio, video: this.sendVideo }
if (this.sendVideo) {
mediaOptions["video"] = { width: this.sendVideoWidth, height: this.sendVideoHeight }
if (this.facingMode) {
mediaOptions["video"] ["facingMode"] = { exact: this.facingMode }
}
}
console.log("Local mediaStreamConstraints", mediaOptions)
this.localStream = await navigator.mediaDevices.getUserMedia(mediaOptions)

console.log("Local stream", this.localStream)
const videoTracks = this.localStream.getVideoTracks()
if (videoTracks.length > 0) {
console.log(`Using video device: ${videoTracks[0].label}`)
}
const audioTracks = this.localStream.getAudioTracks()
if (audioTracks.length > 0) {
console.log(`Using audio device: ${audioTracks[0].label}`)
}
this.localStream.getTracks().forEach(track => {
console.log("Local track to peer", track)
this.pc.addTrack(track, this.localStream)
})
// For display
if (this.localVideo)
this.localVideo.srcObject = this.localStream
}




Reply all
Reply to author
Forward
0 new messages