parse sdp to jingle (yet w/o transport)
This commit is contained in:
		
							parent
							
								
									ef51ec2c1d
								
							
						
					
					
						commit
						b44a3aeac6
					
				@ -36,6 +36,7 @@ public final class Namespace {
 | 
				
			|||||||
    public static final String JINGLE_TRANSPORT_ICE_UDP = "urn:xmpp:jingle:transports:ice-udp:1";
 | 
					    public static final String JINGLE_TRANSPORT_ICE_UDP = "urn:xmpp:jingle:transports:ice-udp:1";
 | 
				
			||||||
    public static final String JINGLE_APPS_RTP = "urn:xmpp:jingle:apps:rtp:1";
 | 
					    public static final String JINGLE_APPS_RTP = "urn:xmpp:jingle:apps:rtp:1";
 | 
				
			||||||
    public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0";
 | 
					    public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0";
 | 
				
			||||||
 | 
					    public static final String JINGLE_APPS_GROUPING = "urn:xmpp:jingle:apps:grouping:0";
 | 
				
			||||||
    public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio";
 | 
					    public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio";
 | 
				
			||||||
    public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video";
 | 
					    public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video";
 | 
				
			||||||
    public static final String JINGLE_RTP_HEADER_EXTENSIONS = "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0";
 | 
					    public static final String JINGLE_RTP_HEADER_EXTENSIONS = "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0";
 | 
				
			||||||
 | 
				
			|||||||
@ -592,7 +592,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
            content.setTransport(new S5BTransportInfo(this.transportId, candidates));
 | 
					            content.setTransport(new S5BTransportInfo(this.transportId, candidates));
 | 
				
			||||||
            Log.d(Config.LOGTAG, String.format("%s: sending S5B offer with %d candidates", id.account.getJid().asBareJid(), candidates.size()));
 | 
					            Log.d(Config.LOGTAG, String.format("%s: sending S5B offer with %d candidates", id.account.getJid().asBareJid(), candidates.size()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.sendJinglePacket(packet, (account, response) -> {
 | 
					        this.sendJinglePacket(packet, (account, response) -> {
 | 
				
			||||||
            if (response.getType() == IqPacket.TYPE.RESULT) {
 | 
					            if (response.getType() == IqPacket.TYPE.RESULT) {
 | 
				
			||||||
                Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": other party received offer");
 | 
					                Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": other party received offer");
 | 
				
			||||||
@ -617,7 +617,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        hash.setAttribute("algo", "sha-1").setContent(Base64.encodeToString(file.getSha1Sum(), Base64.NO_WRAP));
 | 
					        hash.setAttribute("algo", "sha-1").setContent(Base64.encodeToString(file.getSha1Sum(), Base64.NO_WRAP));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final JinglePacket packet = this.bootstrapPacket(JinglePacket.Action.SESSION_INFO);
 | 
					        final JinglePacket packet = this.bootstrapPacket(JinglePacket.Action.SESSION_INFO);
 | 
				
			||||||
        packet.setJingleChild(checksum);
 | 
					        packet.addJingleChild(checksum);
 | 
				
			||||||
        this.sendJinglePacket(packet);
 | 
					        this.sendJinglePacket(packet);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -651,7 +651,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
                    public void failed() {
 | 
					                    public void failed() {
 | 
				
			||||||
                        Log.d(Config.LOGTAG, "connection to our own proxy65 candidate failed");
 | 
					                        Log.d(Config.LOGTAG, "connection to our own proxy65 candidate failed");
 | 
				
			||||||
                        content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
 | 
					                        content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
 | 
				
			||||||
                        packet.setJingleContent(content);
 | 
					                        packet.addJingleContent(content);
 | 
				
			||||||
                        sendJinglePacket(packet);
 | 
					                        sendJinglePacket(packet);
 | 
				
			||||||
                        connectNextCandidate();
 | 
					                        connectNextCandidate();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -661,7 +661,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
                        Log.d(Config.LOGTAG, "connected to proxy65 candidate");
 | 
					                        Log.d(Config.LOGTAG, "connected to proxy65 candidate");
 | 
				
			||||||
                        mergeCandidate(candidate);
 | 
					                        mergeCandidate(candidate);
 | 
				
			||||||
                        content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
 | 
					                        content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
 | 
				
			||||||
                        packet.setJingleContent(content);
 | 
					                        packet.addJingleContent(content);
 | 
				
			||||||
                        sendJinglePacket(packet);
 | 
					                        sendJinglePacket(packet);
 | 
				
			||||||
                        connectNextCandidate();
 | 
					                        connectNextCandidate();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -669,7 +669,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                Log.d(Config.LOGTAG, "did not find a proxy65 candidate for ourselves");
 | 
					                Log.d(Config.LOGTAG, "did not find a proxy65 candidate for ourselves");
 | 
				
			||||||
                content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
 | 
					                content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
 | 
				
			||||||
                packet.setJingleContent(content);
 | 
					                packet.addJingleContent(content);
 | 
				
			||||||
                sendJinglePacket(packet);
 | 
					                sendJinglePacket(packet);
 | 
				
			||||||
                connectNextCandidate();
 | 
					                connectNextCandidate();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -682,7 +682,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        final Content content = new Content(contentCreator, contentName);
 | 
					        final Content content = new Content(contentCreator, contentName);
 | 
				
			||||||
        content.setDescription(this.description);
 | 
					        content.setDescription(this.description);
 | 
				
			||||||
        content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
 | 
					        content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.transport.receive(file, onFileTransmissionStatusChanged);
 | 
					        this.transport.receive(file, onFileTransmissionStatusChanged);
 | 
				
			||||||
        this.sendJinglePacket(packet);
 | 
					        this.sendJinglePacket(packet);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -909,7 +909,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        Content content = new Content(this.contentCreator, this.contentName);
 | 
					        Content content = new Content(this.contentCreator, this.contentName);
 | 
				
			||||||
        this.transportId = JingleConnectionManager.nextRandomId();
 | 
					        this.transportId = JingleConnectionManager.nextRandomId();
 | 
				
			||||||
        content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
 | 
					        content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.sendJinglePacket(packet);
 | 
					        this.sendJinglePacket(packet);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -941,7 +941,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        final Content content = new Content(contentCreator, contentName);
 | 
					        final Content content = new Content(contentCreator, contentName);
 | 
				
			||||||
        content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
 | 
					        content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
 | 
				
			||||||
        answer.setJingleContent(content);
 | 
					        answer.addJingleContent(content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        respondToIq(packet, true);
 | 
					        respondToIq(packet, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1122,7 +1122,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        final JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
					        final JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
				
			||||||
        final Content content = new Content(this.contentCreator, this.contentName);
 | 
					        final Content content = new Content(this.contentCreator, this.contentName);
 | 
				
			||||||
        content.setTransport(new S5BTransportInfo(this.transportId, new Element("activated").setAttribute("cid", cid)));
 | 
					        content.setTransport(new S5BTransportInfo(this.transportId, new Element("activated").setAttribute("cid", cid)));
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.sendJinglePacket(packet);
 | 
					        this.sendJinglePacket(packet);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1130,7 +1130,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        final JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
					        final JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
				
			||||||
        final Content content = new Content(this.contentCreator, this.contentName);
 | 
					        final Content content = new Content(this.contentCreator, this.contentName);
 | 
				
			||||||
        content.setTransport(new S5BTransportInfo(this.transportId, new Element("proxy-error")));
 | 
					        content.setTransport(new S5BTransportInfo(this.transportId, new Element("proxy-error")));
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.sendJinglePacket(packet);
 | 
					        this.sendJinglePacket(packet);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1138,7 +1138,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
					        JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
				
			||||||
        final Content content = new Content(this.contentCreator, this.contentName);
 | 
					        final Content content = new Content(this.contentCreator, this.contentName);
 | 
				
			||||||
        content.setTransport(new S5BTransportInfo(this.transportId, new Element("candidate-used").setAttribute("cid", cid)));
 | 
					        content.setTransport(new S5BTransportInfo(this.transportId, new Element("candidate-used").setAttribute("cid", cid)));
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.sentCandidate = true;
 | 
					        this.sentCandidate = true;
 | 
				
			||||||
        if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) {
 | 
					        if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) {
 | 
				
			||||||
            connect();
 | 
					            connect();
 | 
				
			||||||
@ -1151,7 +1151,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
 | 
				
			|||||||
        JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
					        JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
 | 
				
			||||||
        Content content = new Content(this.contentCreator, this.contentName);
 | 
					        Content content = new Content(this.contentCreator, this.contentName);
 | 
				
			||||||
        content.setTransport(new S5BTransportInfo(this.transportId, new Element("candidate-error")));
 | 
					        content.setTransport(new S5BTransportInfo(this.transportId, new Element("candidate-error")));
 | 
				
			||||||
        packet.setJingleContent(content);
 | 
					        packet.addJingleContent(content);
 | 
				
			||||||
        this.sentCandidate = true;
 | 
					        this.sentCandidate = true;
 | 
				
			||||||
        this.sendJinglePacket(packet);
 | 
					        this.sendJinglePacket(packet);
 | 
				
			||||||
        if (receivedCandidate && mJingleStatus == JINGLE_STATUS_ACCEPTED) {
 | 
					        if (receivedCandidate && mJingleStatus == JINGLE_STATUS_ACCEPTED) {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,9 @@ package eu.siacs.conversations.xmpp.jingle;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.util.Log;
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.base.Function;
 | 
					 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.google.common.collect.ImmutableMap;
 | 
					import com.google.common.collect.ImmutableMap;
 | 
				
			||||||
import com.google.common.collect.Maps;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
 | 
					 | 
				
			||||||
import org.webrtc.AudioSource;
 | 
					import org.webrtc.AudioSource;
 | 
				
			||||||
import org.webrtc.AudioTrack;
 | 
					import org.webrtc.AudioTrack;
 | 
				
			||||||
import org.webrtc.DataChannel;
 | 
					import org.webrtc.DataChannel;
 | 
				
			||||||
@ -26,9 +23,6 @@ import java.util.Map;
 | 
				
			|||||||
import eu.siacs.conversations.Config;
 | 
					import eu.siacs.conversations.Config;
 | 
				
			||||||
import eu.siacs.conversations.xml.Element;
 | 
					import eu.siacs.conversations.xml.Element;
 | 
				
			||||||
import eu.siacs.conversations.xml.Namespace;
 | 
					import eu.siacs.conversations.xml.Namespace;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
 | 
					 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.GenericDescription;
 | 
					 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo;
 | 
					 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo;
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
 | 
				
			||||||
@ -73,18 +67,18 @@ public class JingleRtpConnection extends AbstractJingleConnection {
 | 
				
			|||||||
            //TODO respond with out-of-order
 | 
					            //TODO respond with out-of-order
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        final Map<String, DescriptionTransport> contents;
 | 
					        final RtpContentMap contentMap;
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            contents = DescriptionTransport.of(jinglePacket.getJingleContents());
 | 
					            contentMap = RtpContentMap.of(jinglePacket);
 | 
				
			||||||
        } catch (IllegalArgumentException | NullPointerException e) {
 | 
					        } catch (IllegalArgumentException | NullPointerException e) {
 | 
				
			||||||
            Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents", e);
 | 
					            Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents", e);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Log.d(Config.LOGTAG, "processing session-init with " + contents.size() + " contents");
 | 
					        Log.d(Config.LOGTAG, "processing session-init with " + contentMap.contents.size() + " contents");
 | 
				
			||||||
        final State oldState = this.state;
 | 
					        final State oldState = this.state;
 | 
				
			||||||
        if (transition(State.SESSION_INITIALIZED)) {
 | 
					        if (transition(State.SESSION_INITIALIZED)) {
 | 
				
			||||||
            if (oldState == State.PROCEED) {
 | 
					            if (oldState == State.PROCEED) {
 | 
				
			||||||
                processContents(contents);
 | 
					                processContents(contentMap);
 | 
				
			||||||
                sendSessionAccept();
 | 
					                sendSessionAccept();
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                //TODO start ringing
 | 
					                //TODO start ringing
 | 
				
			||||||
@ -94,9 +88,9 @@ public class JingleRtpConnection extends AbstractJingleConnection {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void processContents(final Map<String, DescriptionTransport> contents) {
 | 
					    private void processContents(final RtpContentMap contentMap) {
 | 
				
			||||||
        for (Map.Entry<String, DescriptionTransport> content : contents.entrySet()) {
 | 
					        for (Map.Entry<String, RtpContentMap.DescriptionTransport> content : contentMap.contents.entrySet()) {
 | 
				
			||||||
            final DescriptionTransport descriptionTransport = content.getValue();
 | 
					            final RtpContentMap.DescriptionTransport descriptionTransport = content.getValue();
 | 
				
			||||||
            final RtpDescription rtpDescription = descriptionTransport.description;
 | 
					            final RtpDescription rtpDescription = descriptionTransport.description;
 | 
				
			||||||
            Log.d(Config.LOGTAG, "receive content with name " + content.getKey() + " and media=" + rtpDescription.getMedia());
 | 
					            Log.d(Config.LOGTAG, "receive content with name " + content.getKey() + " and media=" + rtpDescription.getMedia());
 | 
				
			||||||
            for (RtpDescription.PayloadType payloadType : rtpDescription.getPayloadTypes()) {
 | 
					            for (RtpDescription.PayloadType payloadType : rtpDescription.getPayloadTypes()) {
 | 
				
			||||||
@ -154,7 +148,11 @@ public class JingleRtpConnection extends AbstractJingleConnection {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private void sendSessionInitiate() {
 | 
					    private void sendSessionInitiate() {
 | 
				
			||||||
        setupWebRTC();
 | 
					        setupWebRTC();
 | 
				
			||||||
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": sending session-initiate");
 | 
					        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": prepare session-initiate");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void sendSessionInitiate(RtpContentMap rtpContentMap) {
 | 
				
			||||||
 | 
					        Log.d(Config.LOGTAG, rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_INITIATE, id.sessionId).toString());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void sendSessionAccept() {
 | 
					    private void sendSessionAccept() {
 | 
				
			||||||
@ -253,10 +251,8 @@ public class JingleRtpConnection extends AbstractJingleConnection {
 | 
				
			|||||||
            public void onCreateSuccess(org.webrtc.SessionDescription description) {
 | 
					            public void onCreateSuccess(org.webrtc.SessionDescription description) {
 | 
				
			||||||
                final SessionDescription sessionDescription = SessionDescription.parse(description.description);
 | 
					                final SessionDescription sessionDescription = SessionDescription.parse(description.description);
 | 
				
			||||||
                Log.d(Config.LOGTAG, "description: " + description.description);
 | 
					                Log.d(Config.LOGTAG, "description: " + description.description);
 | 
				
			||||||
                for (SessionDescription.Media media : sessionDescription.media) {
 | 
					                final RtpContentMap rtpContentMap = RtpContentMap.of(sessionDescription);
 | 
				
			||||||
                    Log.d(Config.LOGTAG, RtpDescription.of(media).toString());
 | 
					                sendSessionInitiate(rtpContentMap);
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                Log.d(Config.LOGTAG, sessionDescription.toString());
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
@ -306,44 +302,4 @@ public class JingleRtpConnection extends AbstractJingleConnection {
 | 
				
			|||||||
            throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target));
 | 
					            throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static class DescriptionTransport {
 | 
					 | 
				
			||||||
        private final RtpDescription description;
 | 
					 | 
				
			||||||
        private final IceUdpTransportInfo transport;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public DescriptionTransport(final RtpDescription description, final IceUdpTransportInfo transport) {
 | 
					 | 
				
			||||||
            this.description = description;
 | 
					 | 
				
			||||||
            this.transport = transport;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public static DescriptionTransport of(final Content content) {
 | 
					 | 
				
			||||||
            final GenericDescription description = content.getDescription();
 | 
					 | 
				
			||||||
            final GenericTransportInfo transportInfo = content.getTransport();
 | 
					 | 
				
			||||||
            final RtpDescription rtpDescription;
 | 
					 | 
				
			||||||
            final IceUdpTransportInfo iceUdpTransportInfo;
 | 
					 | 
				
			||||||
            if (description instanceof RtpDescription) {
 | 
					 | 
				
			||||||
                rtpDescription = (RtpDescription) description;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                Log.d(Config.LOGTAG, "description was " + description);
 | 
					 | 
				
			||||||
                throw new IllegalArgumentException("Content does not contain RtpDescription");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (transportInfo instanceof IceUdpTransportInfo) {
 | 
					 | 
				
			||||||
                iceUdpTransportInfo = (IceUdpTransportInfo) transportInfo;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                throw new IllegalArgumentException("Content does not contain ICE-UDP transport");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return new DescriptionTransport(rtpDescription, iceUdpTransportInfo);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public static Map<String, DescriptionTransport> of(final Map<String, Content> contents) {
 | 
					 | 
				
			||||||
            return ImmutableMap.copyOf(Maps.transformValues(contents, new Function<Content, DescriptionTransport>() {
 | 
					 | 
				
			||||||
                @NullableDecl
 | 
					 | 
				
			||||||
                @Override
 | 
					 | 
				
			||||||
                public DescriptionTransport apply(@NullableDecl Content content) {
 | 
					 | 
				
			||||||
                    return content == null ? null : of(content);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					package eu.siacs.conversations.xmpp.jingle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.base.Function;
 | 
				
			||||||
 | 
					import com.google.common.base.Preconditions;
 | 
				
			||||||
 | 
					import com.google.common.collect.ImmutableMap;
 | 
				
			||||||
 | 
					import com.google.common.collect.Iterables;
 | 
				
			||||||
 | 
					import com.google.common.collect.Maps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.checkerframework.checker.nullness.compatqual.NullableDecl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import eu.siacs.conversations.Config;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.GenericDescription;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.Group;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class RtpContentMap {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public final Group group;
 | 
				
			||||||
 | 
					    public final Map<String, DescriptionTransport> contents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private RtpContentMap(Group group, Map<String, DescriptionTransport> contents) {
 | 
				
			||||||
 | 
					        this.group = group;
 | 
				
			||||||
 | 
					        this.contents = contents;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static RtpContentMap of(final JinglePacket jinglePacket) {
 | 
				
			||||||
 | 
					        return new RtpContentMap(jinglePacket.getGroup(), DescriptionTransport.of(jinglePacket.getJingleContents()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static RtpContentMap of(final SessionDescription sessionDescription) {
 | 
				
			||||||
 | 
					        final ImmutableMap.Builder<String, DescriptionTransport> contentMapBuilder = new ImmutableMap.Builder<>();
 | 
				
			||||||
 | 
					        for (SessionDescription.Media media : sessionDescription.media) {
 | 
				
			||||||
 | 
					            final String id = Iterables.getFirst(media.attributes.get("mid"), null);
 | 
				
			||||||
 | 
					            Preconditions.checkNotNull(id, "media has no mid");
 | 
				
			||||||
 | 
					            contentMapBuilder.put(id, DescriptionTransport.of(sessionDescription, media));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        final String groupAttribute = Iterables.getFirst(sessionDescription.attributes.get("group"), null);
 | 
				
			||||||
 | 
					        final Group group = groupAttribute == null ? null : Group.ofSdpString(groupAttribute);
 | 
				
			||||||
 | 
					        return new RtpContentMap(group, contentMapBuilder.build());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public JinglePacket toJinglePacket(final JinglePacket.Action action, final String sessionId) {
 | 
				
			||||||
 | 
					        final JinglePacket jinglePacket = new JinglePacket(action, sessionId);
 | 
				
			||||||
 | 
					        if (this.group != null) {
 | 
				
			||||||
 | 
					            jinglePacket.addGroup(this.group);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (Map.Entry<String, DescriptionTransport> entry : this.contents.entrySet()) {
 | 
				
			||||||
 | 
					            final Content content = new Content(Content.Creator.INITIATOR, entry.getKey());
 | 
				
			||||||
 | 
					            content.addChild(entry.getValue().description);
 | 
				
			||||||
 | 
					            content.addChild(entry.getValue().transport);
 | 
				
			||||||
 | 
					            jinglePacket.addJingleContent(content);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return jinglePacket;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static class DescriptionTransport {
 | 
				
			||||||
 | 
					        public final RtpDescription description;
 | 
				
			||||||
 | 
					        public final IceUdpTransportInfo transport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public DescriptionTransport(final RtpDescription description, final IceUdpTransportInfo transport) {
 | 
				
			||||||
 | 
					            this.description = description;
 | 
				
			||||||
 | 
					            this.transport = transport;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static DescriptionTransport of(final Content content) {
 | 
				
			||||||
 | 
					            final GenericDescription description = content.getDescription();
 | 
				
			||||||
 | 
					            final GenericTransportInfo transportInfo = content.getTransport();
 | 
				
			||||||
 | 
					            final RtpDescription rtpDescription;
 | 
				
			||||||
 | 
					            final IceUdpTransportInfo iceUdpTransportInfo;
 | 
				
			||||||
 | 
					            if (description instanceof RtpDescription) {
 | 
				
			||||||
 | 
					                rtpDescription = (RtpDescription) description;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                Log.d(Config.LOGTAG, "description was " + description);
 | 
				
			||||||
 | 
					                throw new IllegalArgumentException("Content does not contain RtpDescription");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (transportInfo instanceof IceUdpTransportInfo) {
 | 
				
			||||||
 | 
					                iceUdpTransportInfo = (IceUdpTransportInfo) transportInfo;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                throw new IllegalArgumentException("Content does not contain ICE-UDP transport");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return new DescriptionTransport(rtpDescription, iceUdpTransportInfo);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static DescriptionTransport of(final SessionDescription sessionDescription, final SessionDescription.Media media) {
 | 
				
			||||||
 | 
					            final RtpDescription rtpDescription = RtpDescription.of(media);
 | 
				
			||||||
 | 
					            final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
 | 
				
			||||||
 | 
					            return new DescriptionTransport(rtpDescription, transportInfo);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static Map<String, DescriptionTransport> of(final Map<String, Content> contents) {
 | 
				
			||||||
 | 
					            return ImmutableMap.copyOf(Maps.transformValues(contents, new Function<Content, DescriptionTransport>() {
 | 
				
			||||||
 | 
					                @NullableDecl
 | 
				
			||||||
 | 
					                @Override
 | 
				
			||||||
 | 
					                public DescriptionTransport apply(@NullableDecl Content content) {
 | 
				
			||||||
 | 
					                    return content == null ? null : of(content);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -28,7 +28,7 @@ public class SessionDescription {
 | 
				
			|||||||
        this.media = media;
 | 
					        this.media = media;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static SessionDescription parse(final Map<String, JingleRtpConnection.DescriptionTransport> contents) {
 | 
					    public static SessionDescription parse(final Map<String, RtpContentMap.DescriptionTransport> contents) {
 | 
				
			||||||
        final SessionDescriptionBuilder sessionDescriptionBuilder = new SessionDescriptionBuilder();
 | 
					        final SessionDescriptionBuilder sessionDescriptionBuilder = new SessionDescriptionBuilder();
 | 
				
			||||||
        return sessionDescriptionBuilder.createSessionDescription();
 | 
					        return sessionDescriptionBuilder.createSessionDescription();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					package eu.siacs.conversations.xmpp.jingle.stanzas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.base.Preconditions;
 | 
				
			||||||
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xml.Element;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xml.Namespace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Group extends Element {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Group() {
 | 
				
			||||||
 | 
					        super("group", Namespace.JINGLE_APPS_GROUPING);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Group(final String semantics, final Collection<String> identificationTags) {
 | 
				
			||||||
 | 
					        super("group", Namespace.JINGLE_APPS_GROUPING);
 | 
				
			||||||
 | 
					        this.setAttribute("semantics", semantics);
 | 
				
			||||||
 | 
					        for (String tag : identificationTags) {
 | 
				
			||||||
 | 
					            this.addChild(new Element("content").setAttribute("name", tag));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String getSemantics() {
 | 
				
			||||||
 | 
					        return this.getAttribute("semantics");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public List<String> getIdentificationTags() {
 | 
				
			||||||
 | 
					        final ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
 | 
				
			||||||
 | 
					        for (final Element child : this.children) {
 | 
				
			||||||
 | 
					            if ("content".equals(child.getName())) {
 | 
				
			||||||
 | 
					                final String name = child.getAttribute("name");
 | 
				
			||||||
 | 
					                if (name != null) {
 | 
				
			||||||
 | 
					                    builder.add(name);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return builder.build();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Group ofSdpString(final String input) {
 | 
				
			||||||
 | 
					        ImmutableList.Builder<String> tagBuilder = new ImmutableList.Builder<>();
 | 
				
			||||||
 | 
					        final String[] parts = input.split(" ");
 | 
				
			||||||
 | 
					        if (parts.length >= 2) {
 | 
				
			||||||
 | 
					            final String semantics = parts[0];
 | 
				
			||||||
 | 
					            for(int i = 1; i < parts.length; ++i) {
 | 
				
			||||||
 | 
					                tagBuilder.add(parts[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return new Group(semantics,tagBuilder.build());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Group upgrade(final Element element) {
 | 
				
			||||||
 | 
					        Preconditions.checkArgument("group".equals(element.getName()));
 | 
				
			||||||
 | 
					        Preconditions.checkArgument(Namespace.JINGLE_APPS_GROUPING.equals(element.getNamespace()));
 | 
				
			||||||
 | 
					        final Group group = new Group();
 | 
				
			||||||
 | 
					        group.setAttributes(element.getAttributes());
 | 
				
			||||||
 | 
					        group.setChildren(element.getChildren());
 | 
				
			||||||
 | 
					        return group;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -10,8 +10,8 @@ import eu.siacs.conversations.xml.Namespace;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class IceUdpTransportInfo extends GenericTransportInfo {
 | 
					public class IceUdpTransportInfo extends GenericTransportInfo {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private IceUdpTransportInfo(final String name, final String xmlns) {
 | 
					    public IceUdpTransportInfo() {
 | 
				
			||||||
        super(name, xmlns);
 | 
					        super("transport", Namespace.JINGLE_TRANSPORT_ICE_UDP);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Fingerprint getFingerprint() {
 | 
					    public Fingerprint getFingerprint() {
 | 
				
			||||||
@ -32,7 +32,7 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
 | 
				
			|||||||
    public static IceUdpTransportInfo upgrade(final Element element) {
 | 
					    public static IceUdpTransportInfo upgrade(final Element element) {
 | 
				
			||||||
        Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
 | 
					        Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
 | 
				
			||||||
        Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
 | 
					        Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
 | 
				
			||||||
        final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo("transport", Namespace.JINGLE_TRANSPORT_ICE_UDP);
 | 
					        final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
 | 
				
			||||||
        transportInfo.setAttributes(element.getAttributes());
 | 
					        transportInfo.setAttributes(element.getAttributes());
 | 
				
			||||||
        transportInfo.setChildren(element.getChildren());
 | 
					        transportInfo.setChildren(element.getChildren());
 | 
				
			||||||
        return transportInfo;
 | 
					        return transportInfo;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
 | 
					package eu.siacs.conversations.xmpp.jingle.stanzas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import android.support.annotation.NonNull;
 | 
					import android.support.annotation.NonNull;
 | 
				
			||||||
import android.util.Log;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.google.common.base.CaseFormat;
 | 
					import com.google.common.base.CaseFormat;
 | 
				
			||||||
import com.google.common.base.Preconditions;
 | 
					import com.google.common.base.Preconditions;
 | 
				
			||||||
@ -9,7 +8,6 @@ import com.google.common.collect.ImmutableMap;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import eu.siacs.conversations.Config;
 | 
					 | 
				
			||||||
import eu.siacs.conversations.xml.Element;
 | 
					import eu.siacs.conversations.xml.Element;
 | 
				
			||||||
import eu.siacs.conversations.xml.Namespace;
 | 
					import eu.siacs.conversations.xml.Namespace;
 | 
				
			||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 | 
					import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 | 
				
			||||||
@ -44,6 +42,15 @@ public class JinglePacket extends IqPacket {
 | 
				
			|||||||
        return content == null ? null : Content.upgrade(content);
 | 
					        return content == null ? null : Content.upgrade(content);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Group getGroup() {
 | 
				
			||||||
 | 
					        final Element group = this.findChild("group", Namespace.JINGLE_APPS_GROUPING);
 | 
				
			||||||
 | 
					        return group == null ? null : Group.upgrade(group);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void addGroup(final Group group) {
 | 
				
			||||||
 | 
					        this.addJingleChild(group);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Map<String, Content> getJingleContents() {
 | 
					    public Map<String, Content> getJingleContents() {
 | 
				
			||||||
        final Element jingle = findChild("jingle", Namespace.JINGLE);
 | 
					        final Element jingle = findChild("jingle", Namespace.JINGLE);
 | 
				
			||||||
        ImmutableMap.Builder<String, Content> builder = new ImmutableMap.Builder<>();
 | 
					        ImmutableMap.Builder<String, Content> builder = new ImmutableMap.Builder<>();
 | 
				
			||||||
@ -56,8 +63,8 @@ public class JinglePacket extends IqPacket {
 | 
				
			|||||||
        return builder.build();
 | 
					        return builder.build();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void setJingleContent(final Content content) { //take content interface
 | 
					    public void addJingleContent(final Content content) { //take content interface
 | 
				
			||||||
        setJingleChild(content);
 | 
					        addJingleChild(content);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Reason getReason() {
 | 
					    public Reason getReason() {
 | 
				
			||||||
@ -87,7 +94,7 @@ public class JinglePacket extends IqPacket {
 | 
				
			|||||||
        return jingle == null ? null : jingle.findChild(name);
 | 
					        return jingle == null ? null : jingle.findChild(name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void setJingleChild(final Element child) {
 | 
					    public void addJingleChild(final Element child) {
 | 
				
			||||||
        final Element jingle = findChild("jingle", Namespace.JINGLE);
 | 
					        final Element jingle = findChild("jingle", Namespace.JINGLE);
 | 
				
			||||||
        jingle.addChild(child);
 | 
					        jingle.addChild(child);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,11 @@ import eu.siacs.conversations.xmpp.jingle.SessionDescription;
 | 
				
			|||||||
public class RtpDescription extends GenericDescription {
 | 
					public class RtpDescription extends GenericDescription {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private RtpDescription(final String media) {
 | 
				
			||||||
 | 
					        super("description", Namespace.JINGLE_APPS_RTP);
 | 
				
			||||||
 | 
					        this.setAttribute("media", media);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private RtpDescription() {
 | 
					    private RtpDescription() {
 | 
				
			||||||
        super("description", Namespace.JINGLE_APPS_RTP);
 | 
					        super("description", Namespace.JINGLE_APPS_RTP);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -447,7 +452,7 @@ public class RtpDescription extends GenericDescription {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static RtpDescription of(final SessionDescription.Media media) {
 | 
					    public static RtpDescription of(final SessionDescription.Media media) {
 | 
				
			||||||
        final RtpDescription rtpDescription = new RtpDescription();
 | 
					        final RtpDescription rtpDescription = new RtpDescription(media.media);
 | 
				
			||||||
        final Map<String, List<Parameter>> parameterMap = new HashMap<>();
 | 
					        final Map<String, List<Parameter>> parameterMap = new HashMap<>();
 | 
				
			||||||
        final ArrayListMultimap<String, Element> feedbackNegotiationMap = ArrayListMultimap.create();
 | 
					        final ArrayListMultimap<String, Element> feedbackNegotiationMap = ArrayListMultimap.create();
 | 
				
			||||||
        final ArrayListMultimap<String, Source.Parameter> sourceParameterMap = ArrayListMultimap.create();
 | 
					        final ArrayListMultimap<String, Source.Parameter> sourceParameterMap = ArrayListMultimap.create();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user