src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
/**
     * Handles the specified <tt>answer</tt> by creating and initializing the
     * corresponding <tt>MediaStream</tt>s.
     *
     * @param answer the SDP <tt>SessionDescription</tt>.
     *
     * @throws OperationFailedException if we fail to handle <tt>answer</tt> for
     * reasons like failing to initialize media devices or streams.
     * @throws IllegalArgumentException if there's a problem with the syntax or
     * the semantics of <tt>answer</tt>. Method is synchronized in order to
     * avoid closing mediaHandler when we are currently in process of
     * initializing, configuring and starting streams and anybody interested
     * in this operation can synchronize to the mediaHandler instance to wait
     * processing to stop (method setState in CallPeer).
     */
Handles the specified answer by creating and initializing the
corresponding MediaStreams.

@param answer the SDP SessionDescription.

@throws OperationFailedException if we fail to handle answer for
reasons like failing to initialize media devices or streams.
@throws IllegalArgumentException if there's a problem with the syntax or
the semantics of answer. Method is synchronized in order to
avoid closing mediaHandler when we are currently in process of
initializing, configuring and starting streams and anybody interested
in this operation can synchronize to the mediaHandler instance to wait
processing to stop (method setState in CallPeer).
Handles the specified answer by creating and initializing the corresponding MediaStreams . @param answer the SDP SessionDescription . @throws OperationFailedException if we fail to handle answer for reasons like failing to initialize media devices or streams . @throws IllegalArgumentException if there ' s a problem with the syntax or the semantics of answer . Method is synchronized in order to avoid closing mediaHandler when we are currently in process of initializing configuring and starting streams and anybody interested in this operation can synchronize to the mediaHandler instance to wait processing to stop ( method setState in CallPeer ) .
private void doNonSynchronisedProcessAnswer(SessionDescription answer)
            throws OperationFailedException,
                   IllegalArgumentException
    {
        List<MediaDescription> remoteDescriptions
            = SdpUtils.extractMediaDescriptions(answer);
        this.setCallInfoURL(SdpUtils.getCallInfoURL(answer));
        boolean masterStreamSet = false;
        List<MediaType> seenMediaTypes = new ArrayList<MediaType>();
        for (MediaDescription mediaDescription : remoteDescriptions)
        {
            MediaType mediaType;
            try
            {
                mediaType = SdpUtils.getMediaType(mediaDescription);
                if(seenMediaTypes.contains(mediaType))
                    continue;
                seenMediaTypes.add(mediaType);
            }
            catch(IllegalArgumentException iae)
            {
                logger.info("Remote party added to answer a media type that " +
                        "we don't understand. Ignoring stream.");
                continue;
            }
            MediaStreamTarget target
                = SdpUtils.extractDefaultTarget(mediaDescription, answer);
            if(target.getDataAddress().getPort() == 0)
            {
                closeStream(mediaType);
                continue;
            }
            List<MediaFormat> supportedFormats
                = SdpUtils.extractFormats(
                        mediaDescription,
                        getDynamicPayloadTypes());
            MediaDevice dev = getDefaultDevice(mediaType);
            if(!isDeviceActive(dev))
            {
                closeStream(mediaType);
                continue;
            }
            MediaDirection devDirection
                = (dev == null) ? MediaDirection.INACTIVE : dev.getDirection();
            devDirection
                = devDirection.and(getDirectionUserPreference(mediaType));
            if (supportedFormats.isEmpty())
            {
                ProtocolProviderServiceSipImpl.throwOperationFailedException(
                    "Remote party sent an invalid SDP answer. The codecs in " +
                            "the answer are either not present or not " +
                            "supported",
                     OperationFailedException.ILLEGAL_ARGUMENT, null, logger);
            }
            StreamConnector connector
                = getTransportManager().getStreamConnector(mediaType);
            MediaDirection remoteDirection
                = SdpUtils.getDirection(mediaDescription);
            MediaDirection direction
                = devDirection.getDirectionForAnswer(remoteDirection);
            if(isLocallyOnHold())
                direction = direction.and(MediaDirection.SENDONLY);
            List<RTPExtension> remoteRTPExtensions
                = SdpUtils.extractRTPExtensions(
                        mediaDescription,
                        getRtpExtensionsRegistry());
            List<RTPExtension> supportedExtensions
                = getExtensionsForType(mediaType);
            List<RTPExtension> rtpExtensions
                = intersectRTPExtensions(
                        remoteRTPExtensions,
                        supportedExtensions);
            if(MediaType.VIDEO.equals(mediaType))
            {
                supportQualityControls
                    = SdpUtils.containsAttribute(mediaDescription, "imageattr");
            }
            updateSrtpControlsForDtls(mediaType, null, mediaDescription);
            SrtpControls srtpControls = getSrtpControls();
            SDesControl sdesControl
                = (SDesControl)
                    srtpControls.get(mediaType, SrtpControlType.SDES);
            if(sdesControl != null)
            {
                if(selectSdesCryptoSuite(
                        true,
                        sdesControl,
                        mediaDescription) == null)
                {
                    sdesControl.cleanup(null);
                    srtpControls.remove(mediaType, SrtpControlType.SDES);
                    logger.warn("Received unsupported sdes crypto attribute.");
                }
                else
                {
                    removeAndCleanupOtherSrtpControls(
                            mediaType,
                            SrtpControlType.SDES);
                    addAdvertisedEncryptionMethod(SrtpControlType.SDES);
                }
            }
            boolean masterStream = false;
            if(!masterStreamSet)
            {
                if(remoteDescriptions.size() > 1)
                {
                    if(MediaType.AUDIO.equals(mediaType))
                    {
                        masterStream = true;
                        masterStreamSet = true;
                    }
                }
                else
                {
                    masterStream = true;
                    masterStreamSet = true;
                }
            }
            try
            {
                if(mediaDescription.getAttribute(SdpUtils.ZRTP_HASH_ATTR)
                        != null)
                {
                    addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
                }
            }
            catch (SdpParseException e)
            {
                logger.error("received an unparsable sdp attribute", e);
            }
            MediaStream stream
                = initStream(
                        connector,
                        dev,
                        supportedFormats.get(0),
                        target,
                        direction,
                        rtpExtensions,
                        masterStream);
            if (stream != null)
            {
                String rtcpxr;
                try
                {
                    rtcpxr
                        = mediaDescription.getAttribute(
                                RTCPExtendedReport.SDP_ATTRIBUTE);
                }
                catch (SdpException se)
                {
                    rtcpxr = null;
                }
                stream.setProperty(RTCPExtendedReport.SDP_ATTRIBUTE, rtcpxr);
            }
        }
    }
private void doNonSynchronisedProcessAnswer ( SessionDescription answer ) throws OperationFailedException , IllegalArgumentException { List < MediaDescription > remoteDescriptions = SdpUtils . extractMediaDescriptions ( answer ) ; this . setCallInfoURL ( SdpUtils . getCallInfoURL ( answer ) ) ; boolean masterStreamSet = false ; List < MediaType > seenMediaTypes = new ArrayList < MediaType > ( ) ; for ( MediaDescription mediaDescription : remoteDescriptions ) { MediaType mediaType ; try { mediaType = SdpUtils . getMediaType ( mediaDescription ) ; if ( seenMediaTypes . contains ( mediaType ) ) continue ; seenMediaTypes . add ( mediaType ) ; } catch ( IllegalArgumentException iae ) { logger . info ( "Remote party added to answer a media type that " + "we don't understand. Ignoring stream." ) ; continue ; } MediaStreamTarget target = SdpUtils . extractDefaultTarget ( mediaDescription , answer ) ; if ( target . getDataAddress ( ) . getPort ( ) == 0 ) { closeStream ( mediaType ) ; continue ; } List < MediaFormat > supportedFormats = SdpUtils . extractFormats ( mediaDescription , getDynamicPayloadTypes ( ) ) ; MediaDevice dev = getDefaultDevice ( mediaType ) ; if ( ! isDeviceActive ( dev ) ) { closeStream ( mediaType ) ; continue ; } MediaDirection devDirection = ( dev == null ) ? MediaDirection . INACTIVE : dev . getDirection ( ) ; devDirection = devDirection . and ( getDirectionUserPreference ( mediaType ) ) ; if ( supportedFormats . isEmpty ( ) ) { ProtocolProviderServiceSipImpl . throwOperationFailedException ( "Remote party sent an invalid SDP answer. The codecs in " + "the answer are either not present or not " + "supported" , OperationFailedException . ILLEGAL_ARGUMENT , null , logger ) ; } StreamConnector connector = getTransportManager ( ) . getStreamConnector ( mediaType ) ; MediaDirection remoteDirection = SdpUtils . getDirection ( mediaDescription ) ; MediaDirection direction = devDirection . getDirectionForAnswer ( remoteDirection ) ; if ( isLocallyOnHold ( ) ) direction = direction . and ( MediaDirection . SENDONLY ) ; List < RTPExtension > remoteRTPExtensions = SdpUtils . extractRTPExtensions ( mediaDescription , getRtpExtensionsRegistry ( ) ) ; List < RTPExtension > supportedExtensions = getExtensionsForType ( mediaType ) ; List < RTPExtension > rtpExtensions = intersectRTPExtensions ( remoteRTPExtensions , supportedExtensions ) ; if ( MediaType . VIDEO . equals ( mediaType ) ) { supportQualityControls = SdpUtils . containsAttribute ( mediaDescription , "imageattr" ) ; } updateSrtpControlsForDtls ( mediaType , null , mediaDescription ) ; SrtpControls srtpControls = getSrtpControls ( ) ; SDesControl sdesControl = ( SDesControl ) srtpControls . get ( mediaType , SrtpControlType . SDES ) ; if ( sdesControl != null ) { if ( selectSdesCryptoSuite ( true , sdesControl , mediaDescription ) == null ) { sdesControl . cleanup ( null ) ; srtpControls . remove ( mediaType , SrtpControlType . SDES ) ; logger . warn ( "Received unsupported sdes crypto attribute." ) ; } else { removeAndCleanupOtherSrtpControls ( mediaType , SrtpControlType . SDES ) ; addAdvertisedEncryptionMethod ( SrtpControlType . SDES ) ; } } boolean masterStream = false ; if ( ! masterStreamSet ) { if ( remoteDescriptions . size ( ) > 1 ) { if ( MediaType . AUDIO . equals ( mediaType ) ) { masterStream = true ; masterStreamSet = true ; } } else { masterStream = true ; masterStreamSet = true ; } } try { if ( mediaDescription . getAttribute ( SdpUtils . ZRTP_HASH_ATTR ) != null ) { addAdvertisedEncryptionMethod ( SrtpControlType . ZRTP ) ; } } catch ( SdpParseException e ) { logger . error ( "received an unparsable sdp attribute" , e ) ; } MediaStream stream = initStream ( connector , dev , supportedFormats . get ( 0 ) , target , direction , rtpExtensions , masterStream ) ; if ( stream != null ) { String rtcpxr ; try { rtcpxr = mediaDescription . getAttribute ( RTCPExtendedReport . SDP_ATTRIBUTE ) ; } catch ( SdpException se ) { rtcpxr = null ; } stream . setProperty ( RTCPExtendedReport . SDP_ATTRIBUTE , rtcpxr ) ; } } }
Handles the specified <tt>answer</tt> by creating and initializing the
 corresponding <tt>MediaStream</tt>s.
Handles the specified <tt > answer< / tt > by creating and initializing the corresponding <tt > MediaStream< / tt > s .
//don't process a second media of the same type //stream target // not target port - try next media description // Take the preference of the user with respect to streaming // mediaType into account. //remote party must have messed up our SDP. throw an exception. //determine the direction that we need to announce. // take into account and the direction previously set/sent // to change directions properly, this is in case // where we set a direction and the other side don't agree with us // we need to be in the state we have offered // update the RTP extensions that we will be exchanging. // check for options from remote party and set // is quality controls supported // DTLS-SRTP // SDES // select the crypto key the peer has chosen from our proposal //found an SDES answer, remove all other controls // if we have more than one stream, lets the audio be the master // create the corresponding stream... // RTCP XR