From 5919a5b80d7eaa6bc3e1e894bb4b4dd5fdd4ddd1 Mon Sep 17 00:00:00 2001 From: Damian Minkov <damencho@jitsi.org> Date: Thu, 25 Oct 2012 10:20:13 +0000 Subject: [PATCH] Allows the remote party to override payload type for the media we send to it. Payload types are no more overridden locally, and remote settings are used only for the media we sent to the that participant. --- .../jitsi/impl/neomedia/MediaStreamImpl.java | 32 +++++ .../pt/PayloadTypeTransformEngine.java | 116 ++++++++++++++++++ .../jitsi/service/neomedia/MediaStream.java | 16 +++ 3 files changed, 164 insertions(+) create mode 100644 src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java diff --git a/src/org/jitsi/impl/neomedia/MediaStreamImpl.java b/src/org/jitsi/impl/neomedia/MediaStreamImpl.java index ced31e1f..4145f3b5 100644 --- a/src/org/jitsi/impl/neomedia/MediaStreamImpl.java +++ b/src/org/jitsi/impl/neomedia/MediaStreamImpl.java @@ -25,6 +25,7 @@ import org.jitsi.impl.neomedia.transform.*; import org.jitsi.impl.neomedia.transform.csrc.*; import org.jitsi.impl.neomedia.transform.dtmf.*; +import org.jitsi.impl.neomedia.transform.pt.*; import org.jitsi.impl.neomedia.transform.rtcp.*; import org.jitsi.impl.neomedia.transform.zrtp.*; import org.jitsi.service.neomedia.*; @@ -223,6 +224,11 @@ else if (MediaDeviceSession.SSRC_LIST.equals(propertyName)) */ private MediaStreamStatsImpl mediaStreamStatsImpl; + /** + * Engine chain overriding payload type if needed. + */ + private PayloadTypeTransformEngine ptTransformEngine; + /** * Initializes a new <tt>MediaStreamImpl</tt> instance which will use the * specified <tt>MediaDevice</tt> for both capture and playback of media. @@ -373,6 +379,12 @@ private TransformEngineChain createTransformEngineChain() statisticsEngine = new StatisticsEngine(this); engineChain.add(statisticsEngine); + // here comes the override payload type transformer + // as it changes headers of packets, need to go before encryption + if(ptTransformEngine == null) + ptTransformEngine = new PayloadTypeTransformEngine(); + engineChain.add(ptTransformEngine); + // SRTP engineChain.add(srtpControl.getTransformEngine()); @@ -2845,4 +2857,24 @@ public FECDecoderControl getFecDecoderControl(ReceiveStream receiveStream) } return null; } + + /** + * Adds additional RTP payload mappings that will override the ones in the + * "dynamicPayloadTypes" map for outgoing packets. This is necessary so + * that we can support the RFC3264 case where the answerer has the right + * to declare what payload type mappings it wants to receive even if they + * are different from those in the offer. RFC3264 claims this is for + * support of legacy protocols such as H.323 but we've been bumping with + * a number of cases where multi-component pure SIP systems also need to + * behave this way. + * The <tt>Map<Byte, Byte></tt> maps source payload to payload to use + * for packets when sending. + * @param mappingOverride <tt>Map<Byte, Byte></tt> that maps + * source payload to payload to use for packets when sending. + */ + public void setPTMappingOverrides(Map<Byte, Byte> mappingOverride) + { + if(ptTransformEngine != null) + ptTransformEngine.setPTMappingOverride(mappingOverride); + } } diff --git a/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java b/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java new file mode 100644 index 00000000..298deada --- /dev/null +++ b/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java @@ -0,0 +1,116 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package org.jitsi.impl.neomedia.transform.pt; + +import org.jitsi.impl.neomedia.*; +import org.jitsi.impl.neomedia.transform.*; + +import java.util.*; + +/** + * We use this engine to change payload types of outgoing RTP packets if needed. + * This is necessary so that we can support the RFC3264 case where the answerer + * has the right to declare what payload type mappings it wants to receive even + * if they are different from those in the offer. RFC3264 claims this is for + * support of legacy protocols such as H.323 but we've been bumping with + * a number of cases where multi-component pure SIP systems also need to + * behave this way. + * + * @author Damian Minkov + */ +public class PayloadTypeTransformEngine + implements TransformEngine, + PacketTransformer +{ + /** + * The mapping we use to override payloads. By default it is empty + * and we do nothing, packets are passed through without modification. + * Maps source payload to target payload. + */ + private Map<Byte, Byte> mappingOverride = new HashMap<Byte, Byte>(); + + /** + * Checks if there are any override mappings, if no setting just pass + * through the packet. + * If the <tt>RawPacket</tt> payload has entry in mappings to override, + * we override packet payload type. + * + * @param pkt the RTP <tt>RawPacket</tt> that we check for need to change + * payload type. + * + * @return the updated <tt>RawPacket</tt> instance containing the changed + * payload type. + */ + public RawPacket transform(RawPacket pkt) + { + if(mappingOverride.isEmpty()) + return pkt; + + Byte newPT = mappingOverride.get(pkt.getPayloadType()); + if(newPT != null) + pkt.setPayload(newPT); + + return pkt; + } + + /** + * Do nothing just passes the incoming packet. + * + * @param pkt the RTP <tt>RawPacket</tt> that we will pass through. + * + * @return the same <tt>RawPacket</tt> that is passing through. + */ + public RawPacket reverseTransform(RawPacket pkt) + { + return pkt; + } + + /** + * Closes this <tt>PacketTransformer</tt> i.e. releases the resources + * allocated by it and prepares it for garbage collection. + */ + public void close() + { + } + + /** + * Returns a reference to this class since it is performing RTP + * transformations in here. + * + * @return a reference to <tt>this</tt> instance of the + * <tt>PayloadTypeTransformEngine</tt>. + */ + public PacketTransformer getRTPTransformer() + { + return this; + } + + /** + * Always returns <tt>null</tt> since this engine does not require any + * RTCP transformations. + * + * @return <tt>null</tt> since this engine does not require any + * RTCP transformations. + */ + public PacketTransformer getRTCPTransformer() + { + return null; + } + + /** + * Adds additional RTP payload mappings used to override the outgoing + * payload type. The <tt>Map<Byte, Byte></tt> maps source payload to + * payload to use for packets when sending. + * @param mappingOverride <tt>Map<Byte, Byte></tt> that maps + * source payload to payload to use for packets when sending. + */ + public void setPTMappingOverride(Map<Byte, Byte> mappingOverride) + { + if(mappingOverride != null) + this.mappingOverride = mappingOverride; + } +} diff --git a/src/org/jitsi/service/neomedia/MediaStream.java b/src/org/jitsi/service/neomedia/MediaStream.java index 6ace1dca..479104d1 100644 --- a/src/org/jitsi/service/neomedia/MediaStream.java +++ b/src/org/jitsi/service/neomedia/MediaStream.java @@ -237,6 +237,22 @@ public void addDynamicRTPPayloadType( */ public Map<Byte, MediaFormat> getDynamicRTPPayloadTypes(); + /** + * Adds additional RTP payload mappings that will override the ones in the + * "dynamicPayloadTypes" map for outgoing packets. This is necessary so + * that we can support the RFC3264 case where the answerer has the right + * to declare what payload type mappings it wants to receive even if they + * are different from those in the offer. RFC3264 claims this is for + * support of legacy protocols such as H.323 but we've been bumping with + * a number of cases where multi-component pure SIP systems also need to + * behave this way. + * The <tt>Map<Byte, Byte></tt> maps source payload to payload to use + * for packets when sending. + * @param mappingOverride <tt>Map<Byte, Byte></tt> that maps + * source payload to payload to use for packets when sending. + */ + public void setPTMappingOverrides(Map<Byte, Byte> mappingOverride); + /** * Adds or updates an association in this <tt>MediaStream</tt> mapping the * specified <tt>extensionID</tt> to <tt>rtpExtension</tt> and enabling or -- GitLab