Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

addTransceiver specifies that direction is not valid

209 views
Skip to first unread message

唐凌燕

unread,
Jan 16, 2025, 9:41:23 AMJan 16
to discuss-webrtc
Problem Description

While developing audio and video calling functionality using Java Native WebRTC on Android devices, I encountered an issue related to media negotiation and RtpTransceiver. Specifically, even though the answer side (receiver) sets the direction of the RtpTransceiver to SEND_RECV, the generated SDP answer still includes a=recvonly. This results in the media stream being received only, and not sent, which affects the bidirectional communication.

Development Environment
  • Programming Language: Java
  • WebRTC Version: m132
  • Platform: Android (using Java Native WebRTC)
Problem Details
  1. Initial Code Setup:

    RtpTransceiver.RtpTransceiverInit rtpTransceiverInit = new RtpTransceiver.RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_RECV);
    RtpTransceiver rtpTransceiver = config.getPc().addTransceiver(videoTrackTemp, rtpTransceiverInit);

    config.getPc().createAnswer(new SdpObserver() {
    @Override
    public void onCreateSuccess(SessionDescription sessionDescription) {
    Log.i(TAG, "Setting local description");
    PluginsHandle.SdpDesc sdpDesc = pluginsHandle.new SdpDesc();
    sdpDesc.setSessionDescription(sessionDescription);
    config.setMySdp(sdpDesc);
    config.getPc().setLocalDescription(this, sessionDescription);
    }

    @Override
    public void onSetSuccess() {
    callbacks.onSuccess(config.getMySdp().getSessionDescription());
    }

    @Override
    public void onCreateFailure(String s) {
    Log.e(TAG, "onCreateFailure," + s);
    }

    @Override
    public void onSetFailure(String s) {
    Log.e(TAG, "onSetFailure," + s);
    }
    }, new MediaConstraints());

    Problem: Despite setting SEND_RECV, the generated SDP answer still contains a=recvonly.

  2. Attempted Debugging Steps

    1. Logging:

      • Printed the direction and currentDirection of the Transceiver, and found that currentDirection is null.
      • Printed the SDP content to verify whether the media direction is correctly set.
    2. Verified Transceiver Configuration:

      • Ensured that the Transceiver direction is correctly set to SEND_RECV after adding it.
      • Used getTransceivers() to check the status and direction of all transceivers.
Issues Encountered
  • Even after adjusting the order of setting the Transceiver and remote description, the generated SDP answer still contains a=recvonly.
  • During debugging, Transceiver currentDirection is null, indicating that the direction has not been correctly negotiated.
Specific Help Request
  1. Why does the generated SDP answer still contain a=recvonly even after setting RtpTransceiverDirection.SEND_RECV?
  2. How can I ensure that the Transceiver direction is correctly negotiated as SEND_RECV?
Additional Information
  • WebRTC Version: m132
  • Technology Used: Java Native WebRTC
  • Debugging Output:
    • Transceiver currentDirection: null
    • SDP content printed in the logs (can be provided if needed)
Help Needed
  • Analyzing why the SDP answer contains a=recvonly even after setting RtpTransceiverDirection.SEND_RECV.
  • Ensuring that the Transceiver direction is correctly negotiated as SEND_RECV.
Thanks

Thank you for your time and help!

Paweł Domas

unread,
Jan 17, 2025, 1:05:58 PMJan 17
to discuss-webrtc
Hi,

Check what direction is set in the offer for that mline. It's probably set to SEND_ONLY and thus does not allow the answerer to send.

lingyan tang

unread,
Jan 20, 2025, 12:48:16 AMJan 20
to discuss-webrtc
I don't quite understand your solution. I look forward to your next reply

Paweł Domas

unread,
Jan 20, 2025, 12:32:23 PMJan 20
to discuss-webrtc
Please read the section 6 of this document:


Specifically it says:

"If the offer was sendonly, the list is constructed as if the answer were recvonly."

lingyan tang

unread,
Jan 20, 2025, 8:39:39 PMJan 20
to discuss-webrtc
answer's sdp contains a=recvonly, which I didn't set artificially; I explicitly specified a=sendrecv

RtpTransceiver.RtpTransceiverInit rtpTransceiverInit = new RtpTransceiver.RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_RECV);
RtpTransceiver rtpTransceiver = config.getPc().addTransceiver(videoTrackTemp, rtpTransceiverInit);

Below is my sdp info

sdp for offer

{"type":"offer","sdp":"v=0
o=- 5452548368114549181 2 IN IP4 198.18.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=ice-options:trickle
a=fingerprint:sha-256 FF:D9:4F:7D:77:B8:75:DC:A7:D7:EF:5C:6D:7F:55:AE:13:8C:FF:61:4D:BC:57:BB:7C:64:BE:DC:28:38:0E:20
a=extmap-allow-mixed
a=msid-semantic: WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
c=IN IP4 198.18.0.1
a=sendrecv
a=mid:0
a=rtcp-mux
a=ice-ufrag:858r
a=ice-pwd:7SUS62zAtnbuqvs8xcdZj+
a=ice-options:trickle
a=setup:actpass
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
a=msid:- 101
a=ssrc:92170245 cname:janus
a=candidate:1 1 udp 2015364351 192.168.1.103 27648 typ host
a=candidate:2 1 udp 2015364863 192.168.10.21 33365 typ host
a=candidate:3 1 udp 2015363327 198.18.0.1 30075 typ host
a=end-of-candidates
m=video 9 UDP/TLS/RTP/SAVPF 96 39 98 97 40 99
c=IN IP4 198.18.0.1
a=sendrecv
a=mid:1
a=rtcp-mux
a=ice-ufrag:858r
a=ice-pwd:7SUS62zAtnbuqvs8xcdZj+
a=ice-options:trickle
a=setup:actpass
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:13 urn:3gpp:video-orientation
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:39 AV1/90000
a=rtcp-fb:39 goog-remb
a=rtcp-fb:39 transport-cc
a=rtcp-fb:39 ccm fir
a=rtcp-fb:39 nack
a=rtcp-fb:39 nack pli
a=fmtp:39 level-idx=5;profile=0;tier=0
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:40 rtx/90000
a=fmtp:40 apt=39
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=ssrc-group:FID 3155141792 3932369809
a=msid:- 102
a=ssrc:3155141792 cname:janus
a=ssrc:3932369809 cname:janus
a=candidate:1 1 udp 2015364351 192.168.1.103 27648 typ host
a=candidate:2 1 udp 2015364863 192.168.10.21 33365 typ host
a=candidate:3 1 udp 2015363327 198.18.0.1 30075 typ host
a=end-of-candidates
"}
sdp for answer
{"type":"answer","sdp":"v=0
o=- 4036896141800220943 2 IN IP4 198.18.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=ice-options:trickle
a=fingerprint:sha-256 FF:D9:4F:7D:77:B8:75:DC:A7:D7:EF:5C:6D:7F:55:AE:13:8C:FF:61:4D:BC:57:BB:7C:64:BE:DC:28:38:0E:20
a=extmap-allow-mixed
a=msid-semantic: WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
c=IN IP4 198.18.0.1
a=recvonly
a=mid:0
a=rtcp-mux
a=ice-ufrag:iG5T
a=ice-pwd:geHu0+3wvJNuB08EnjxaZ4
a=ice-options:trickle
a=setup:active
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
a=msid:janus janus0
a=ssrc:2676864120 cname:janus
a=candidate:1 1 udp 2015364351 192.168.1.103 35320 typ host
a=candidate:2 1 udp 2015364863 192.168.10.21 33856 typ host
a=candidate:3 1 udp 2015363327 198.18.0.1 28982 typ host
a=end-of-candidates
m=video 9 UDP/TLS/RTP/SAVPF 96 39 98 97 40 99
c=IN IP4 198.18.0.1
a=recvonly
a=mid:1
a=rtcp-mux
a=ice-ufrag:iG5T
a=ice-pwd:geHu0+3wvJNuB08EnjxaZ4
a=ice-options:trickle
a=setup:active
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:13 urn:3gpp:video-orientation
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:39 AV1/90000
a=rtcp-fb:39 goog-remb
a=rtcp-fb:39 transport-cc
a=rtcp-fb:39 ccm fir
a=rtcp-fb:39 nack
a=rtcp-fb:39 nack pli
a=fmtp:39 level-idx=5;profile=0;tier=0
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:40 rtx/90000
a=fmtp:40 apt=39
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=msid:janus janus1
a=ssrc:2067473890 cname:janus
a=candidate:1 1 udp 2015364351 192.168.1.103 35320 typ host
a=candidate:2 1 udp 2015364863 192.168.10.21 33856 typ host
a=candidate:3 1 udp 2015363327 198.18.0.1 28982 typ host
a=end-of-candidates
"}

Paweł Domas

unread,
Jan 22, 2025, 11:40:50 AMJan 22
to discuss...@googlegroups.com
If the offer has SENDRECV then I'm not sure what's wrong here. Maybe someone else can help. Otherwise I'd suggest looking at verbose logging for clues and studying webrtc source code.

--
This list falls under the WebRTC Code of Conduct - https://webrtc.org/support/code-of-conduct.
---
You received this message because you are subscribed to a topic in the Google Groups "discuss-webrtc" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/discuss-webrtc/57ePfB1yRao/unsubscribe.
To unsubscribe from this group and all its topics, send an email to discuss-webrt...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/discuss-webrtc/b559f9a8-0cad-4dc3-824c-1c0f15eb111cn%40googlegroups.com.

Parallelc

unread,
Jan 28, 2025, 6:41:05 AM (14 days ago) Jan 28
to discuss...@googlegroups.com

No need to call addTransceiver on the answer side. A new transceiver with recvonly direction will be added after setting the offer. Just call getTransceivers to get it and modify its direction to sendrecv before creating the answer.


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 visit https://groups.google.com/d/msgid/discuss-webrtc/CAMioq0vvU8c5q%3D%2BJ_pFsOn5mJQ3H9%2Bs-xBV9RQ-5jPcVa-QtoQ%40mail.gmail.com.

lingyan tang

unread,
Feb 7, 2025, 6:25:46 AM (4 days ago) Feb 7
to discuss-webrtc
The receiver's direction does change from recvonly to sendrecv, but the originator still doesn't see the receiver's video.
I tried rtpTransceiver.getSender().setTrack(videoTrackTemp,true); But it didn't work out
Thank you very much for your help
Reply all
Reply to author
Forward
0 new messages