howto reuse a transceiver

1,186 views
Skip to first unread message

emanuele bizzarri

unread,
Jul 25, 2019, 12:19:19 PM7/25/19
to discuss...@googlegroups.com
Hi,

I created a transceiver using:
transceiver=pc.addTransceiver(track, {
     direction:'sendonly',
      streams:[stream]
 });

(track and stream have been created using getUserMedia)

at some point I need to stop the track:
pc.removeTrack( transceiver.sender);

Looking at the generated sdp I can see that the direction of the m-section changes correctly from sendonly to inactive.

Now how can I do to reuse exactly this transceiver to add a new track?

I already tried using:
pc.addTrack(track,stream);

but if there is one more than one m-section the first available will be used.
Instead I want to reuse exactly this transceiver.

Thank you in advance,

Emanuele



Lorenzo Miniero

unread,
Jul 25, 2019, 1:12:14 PM7/25/19
to discuss-webrtc
You need to operate on the transceiver at that point, adding or replacing the track there. You may want to refer to some docs for more info:

Philipp Hancke

unread,
Jul 25, 2019, 1:23:26 PM7/25/19
to discuss...@googlegroups.com
https://blog.mozilla.org/webrtc/rtcrtptransceiver-explored/ is probably the best reference, Jan-Ivar has a jsfiddle for everything.

--

---
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/86615070-0627-4fc1-93a2-a240c214e8f6%40googlegroups.com.

jib

unread,
Jul 25, 2019, 1:51:42 PM7/25/19
to discuss-webrtc
To clarify: pc.removeTrack(transceiver.sender) is a synchronous equivalent to:

await transceiver.sender.replaceTrack(null);
transceiver
.direction = "inactive";

The first line requires no negotiation while the second does.

But the transceiver is not stopped. Only Firefox implements transceiver.stop() atm.

> I already tried using: pc.addTrack(track,stream);

Yeah with addTrack() you'll get a second transceiver, and you may end up with bidirectional ones as well (combined with addTrack from the other side), so be careful about stop()ing them. If this is what you want, then good, but with BUNDLE in every browser these days, I'd recommend unidirectional transceivers.

In theory, people who don't want to mess with transceivers, could probably get away with doing the following cleanup in the tail of their onnegotiationneeded:

pc.getTransceivers().forEach(tc => !tc.stopped && tc.direction == "inactive" && tc.stop());

But then Chrome would probably need to support stop() first.

.: Jan-Ivar :.
To unsubscribe from this group and stop receiving emails from it, send an email to discuss...@googlegroups.com.

emanuele bizzarri

unread,
Jul 26, 2019, 5:59:50 AM7/26/19
to discuss...@googlegroups.com
Hi,
thank you all for your help.
This do exactly what I need:
await transceiver.sender.replaceTrack(null);
transceiver.direction = "inactive";

I attach a little quick and dirty sample that uses 6 separated unidirectional sections, one for each media (audio,video,screen) between 2 peers.

Regards,

Emanuele


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/cb58e5bd-3a86-44b2-83e5-1708f113e837%40googlegroups.com.
unifiedplan.html

emanuele bizzarri

unread,
Aug 1, 2019, 8:37:28 AM8/1/19
to discuss...@googlegroups.com
Hi,
now I am playing a bit with "offer to receive media" and unified plan.
Attached you can find a demo in which the offer is made by the receiver.
This demo is currently working on both chrome and firefox, but I am not sure if the procedure of starting/restarting the streams on the transmitter side is correct.
If you look at the demo, the issue is inside the startVideo/startScreen functions:
async function startVideo(){
try{
console.warn('startVideo');
streams.pc1.video=await navigator.mediaDevices.getUserMedia({audio:true,video:true});
document.getElementById('local_video_pc1').srcObject = streams.pc1.video;

let update_tranceivers=false;
streams.pc1.video.getTracks().forEach(function(track) {
let media=track.kind;
if (transceivers.pc1[media]){
transceivers.pc1[media].sender.replaceTrack(track);
transceivers.pc1[media].direction = "sendonly";
}else{
//the first time use addTrack, not addTransceiver...
pcs.pc1.addTrack(track,streams.pc1.video);
update_tranceivers=true;
//the next commented code doesn't work:
// transceivers.pc1[media]=pcs.pc1.addTransceiver(track, {
// direction:'sendonly',
// streams:[streams.pc1.video]
// });
}
});
//...but after you have to get tranceivers in order to store their mids
//...and be carefull because when you restart the video you will not have the track associated to the transceiver in this phase, then update transceivers only the first time
if(update_tranceivers){
pcs.pc1.getTransceivers().forEach(function(transceiver){
transceivers.pc1[transceiver.sender.track.kind]=transceiver;
});
}
updateButtons('video',true);
}
catch(error){
streams.pc1.video=null;
console.error('startVideo error=',error);
};
}

What I noticed is that the first time I want to start the stream I cannot use addTransceiver as I wanted, but I have to use addTrack:
//the first time use addTrack, not addTransceiver...
pcs.pc1.addTrack(track,streams.pc1.video);
update_tranceivers=true;
//the next commented code doesn't work:
// transceivers.pc1[media]=pcs.pc1.addTransceiver(track, {
// direction:'sendonly',
// streams:[streams.pc1.video]
// });

but then if I want to know the transceiver associated to each track, in order to match the tracks between the endpoints through transceiver.mid, I have to get them:
pcs.pc1.getTransceivers().forEach(function(transceiver){
transceivers.pc1[transceiver.sender.track.kind]=transceiver;
});
now, if I need to stop and restart the stream, I don't have to use addTrack anymore, but I can reuse the previous transceiver:
transceivers.pc1[media].sender.replaceTrack(track);
transceivers.pc1[media].direction = "sendonly";
but then I have absolutely to avoid to loop inside transceivers, because the  transceiver.sender.track is null in his phase.

This implementation is a bit weird in my opinion, I think that there should be a better way to do that.
Can you give me suggestions on a better way to do that?

The main reason I'd want to use the "offer to receive media" is because it allows to me to take under control the flow of offer/answer between the peers and avoid "offer/answer conflicts" in a very easy way.

Thank you,
Emanuele


unifiedplan_offer_to_receive.html
Reply all
Reply to author
Forward
0 new messages