@ -54,7 +54,7 @@ public class CallPeerMediaHandlerJabberImpl
* remote side . We use { @link LinkedHashMap } s to make sure that we preserve
* the order of the individual content extensions .
* /
private Map < String , ContentPacketExtension > localContentMap
private final Map < String , ContentPacketExtension > localContentMap
= new LinkedHashMap < String , ContentPacketExtension > ( ) ;
/ * *
@ -62,7 +62,7 @@ public class CallPeerMediaHandlerJabberImpl
* We use { @link LinkedHashMap } s to make sure that we preserve
* the order of the individual content extensions .
* /
private Map < String , ContentPacketExtension > remoteContentMap
private final Map < String , ContentPacketExtension > remoteContentMap
= new LinkedHashMap < String , ContentPacketExtension > ( ) ;
/ * *
@ -77,9 +77,9 @@ public class CallPeerMediaHandlerJabberImpl
private boolean supportQualityControls = false ;
/ * *
* The current quality controls for this peer media handler if any .
* The < tt > QualityControl < / tt > of this < tt > CallPeerMediaHandler < / tt > .
* /
private QualityControlWrapper qualityControls = null ;
private final QualityControlWrapper qualityControls ;
/ * *
* Creates a new handler that will be managing media streams for
@ -91,6 +91,7 @@ public class CallPeerMediaHandlerJabberImpl
public CallPeerMediaHandlerJabberImpl ( CallPeerJabberImpl peer )
{
super ( peer ) ;
qualityControls = new QualityControlWrapper ( peer ) ;
}
@ -196,7 +197,7 @@ protected MediaStream initStream(String streamName,
MediaStreamTarget target ,
MediaDirection direction ,
List < RTPExtension > rtpExtensions ,
boolean masterStream )
boolean masterStream )
throws OperationFailedException
{
MediaStream stream
@ -209,7 +210,7 @@ protected MediaStream initStream(String streamName,
rtpExtensions ,
masterStream ) ;
if ( stream ! = null )
if ( stream ! = null )
stream . setName ( streamName ) ;
return stream ;
@ -266,8 +267,8 @@ public void processOffer(List<ContentPacketExtension> offer)
// determine the direction that we need to announce.
MediaDirection remoteDirection = JingleUtils . getDirection (
content , getPeer ( ) . isInitiator ( ) ) ;
MediaDirection direction = devDirection
. getDirectionForAnswer ( remoteDirection ) ;
MediaDirection direction
= devDirection . getDirectionForAnswer ( remoteDirection ) ;
// intersect the MediaFormats of our device with remote ones
List < MediaFormat > mutuallySupportedFormats
@ -315,14 +316,14 @@ public void processOffer(List<ContentPacketExtension> offer)
: ( target ! = null ) ? target . getDataAddress ( ) . getPort ( ) : 0 ;
/ *
* TODO If the offered transport is not supported , attempt to
* fall back to a supported one using transport - replace .
* TODO If the offered transport is not supported , attempt to fall
* back to a supported one using transport - replace .
* /
setTransportManager ( transport . getNamespace ( ) ) ;
if ( mutuallySupportedFormats . isEmpty ( )
| | ( devDirection = = MediaDirection . INACTIVE )
| | ( targetDataPort = = 0 ) )
| | ( devDirection = = MediaDirection . INACTIVE )
| | ( targetDataPort = = 0 ) )
{
// skip stream and continue. contrary to sip we don't seem to
// need to send per-stream disabling answer and only one at the
@ -368,8 +369,8 @@ public void processOffer(List<ContentPacketExtension> offer)
description ) ;
}
// got an content which have inputevt, it means that peer requests
// a desktop sharing session so tell it we support inputevt
// Got a content which has inputevt. It means that the peer requests
// a desktop sharing session so tell it we support inputevt .
if ( content . getChildExtensionsOfType ( InputEvtPacketExtension . class )
! = null )
{
@ -449,14 +450,17 @@ public Iterable<ContentPacketExtension> generateSessionAccept()
RtpDescriptionPacketExtension > contents
= new HashMap < ContentPacketExtension ,
RtpDescriptionPacketExtension > ( ) ;
for ( ContentPacketExtension ourContent : sessAccept )
{
RtpDescriptionPacketExtension description
= JingleUtils . getRtpDescription ( ourContent ) ;
= JingleUtils . getRtpDescription ( ourContent ) ;
contents . put ( ourContent , description ) ;
}
boolean masterStreamSet = false ;
for ( Map . Entry < ContentPacketExtension , RtpDescriptionPacketExtension > en
: contents . entrySet ( ) )
{
@ -480,9 +484,11 @@ public Iterable<ContentPacketExtension> generateSessionAccept()
= JingleUtils . getDirection ( ourContent , ! peer . isInitiator ( ) ) ;
// if we answer with video, tell remote peer that video direction is
// sendrecv, and whether video device can capture(send)
if ( type = = MediaType . VIDEO & & isLocalVideoTransmissionEnabled ( )
& & dev . getDirection ( ) . allowsSending ( ) )
// sendrecv, and whether video device can capture/send
if ( ( type = = MediaType . VIDEO )
& & ( isLocalVideoTransmissionEnabled ( )
| | isRTPTranslationEnabled ( ) )
& & dev . getDirection ( ) . allowsSending ( ) )
{
direction = MediaDirection . SENDRECV ;
ourContent . setSenders ( ContentPacketExtension . SendersEnum . both ) ;
@ -503,15 +509,13 @@ public Iterable<ContentPacketExtension> generateSessionAccept()
= JingleUtils . payloadTypeToMediaFormat (
payload ,
getDynamicPayloadTypes ( ) ) ;
if ( format ! = null )
break ;
}
if ( format = = null )
{
ProtocolProviderServiceJabberImpl .
throwOperationFailedException (
ProtocolProviderServiceJabberImpl . throwOperationFailedException (
"No matching codec." ,
OperationFailedException . ILLEGAL_ARGUMENT ,
null ,
@ -521,8 +525,9 @@ public Iterable<ContentPacketExtension> generateSessionAccept()
//extract the extensions that we are advertising:
// check whether we will be exchanging any RTP extensions.
List < RTPExtension > rtpExtensions
= JingleUtils . extractRTPExtensions (
description , this . getRtpExtensionsRegistry ( ) ) ;
= JingleUtils . extractRTPExtensions (
description ,
this . getRtpExtensionsRegistry ( ) ) ;
Map < String , String > adv = format . getAdvancedAttributes ( ) ;
if ( adv ! = null )
@ -554,8 +559,15 @@ public Iterable<ContentPacketExtension> generateSessionAccept()
}
// create the corresponding stream...
initStream ( ourContent . getName ( ) , connector , dev , format , target ,
direction , rtpExtensions , masterStream ) ;
initStream (
ourContent . getName ( ) ,
connector ,
dev ,
format ,
target ,
direction ,
rtpExtensions ,
masterStream ) ;
}
return sessAccept ;
}
@ -573,11 +585,16 @@ public Iterable<ContentPacketExtension> generateSessionAccept()
private ContentPacketExtension createContent ( MediaDevice dev )
throws OperationFailedException
{
MediaDirection direction
= dev . getDirection ( ) . and (
getDirectionUserPreference ( dev . getMediaType ( ) ) ) ;
MediaType mediaType = dev . getMediaType ( ) ;
MediaDirection direction = dev . getDirection ( ) ;
if ( isLocallyOnHold ( ) )
/ *
* In the case of RTP translation performed by the conference focus ,
* the conference focus is not required to capture media .
* /
if ( ! ( MediaType . VIDEO . equals ( mediaType ) & & isRTPTranslationEnabled ( ) ) )
direction = direction . and ( getDirectionUserPreference ( mediaType ) ) ;
if ( isLocallyOnHold ( ) )
direction = direction . and ( MediaDirection . SENDONLY ) ;
QualityPreset sendQualityPreset = null ;
@ -585,36 +602,30 @@ private ContentPacketExtension createContent(MediaDevice dev)
if ( qualityControls ! = null )
{
// the one we will send is the one the oth er part has announced
// as receive
// the one we will send is the one the rem ote has announced as
// receive
sendQualityPreset = qualityControls . getRemoteReceivePreset ( ) ;
// the one we want to receive is the setting that remote
// can send
// the one we want to receive is the one the remote can send
receiveQualityPreset = qualityControls . getRemoteSendMaxPreset ( ) ;
}
if ( direction ! = MediaDirection . INACTIVE )
{
ContentPacketExtension content = createContentForOffer (
dev . getSupportedFormats ( sendQualityPreset ,
receiveQualityPreset ) , direction ,
dev . getSupportedExtensions ( ) ) ;
RtpDescriptionPacketExtension description =
JingleUtils . getRtpDescription ( content ) ;
ContentPacketExtension content
= createContentForOffer (
dev . getSupportedFormats (
sendQualityPreset ,
receiveQualityPreset ) ,
direction ,
dev . getSupportedExtensions ( ) ) ;
RtpDescriptionPacketExtension description
= JingleUtils . getRtpDescription ( content ) ;
//SDES
// It is important to set SDES before ZRTP in order to make GTALK
// application able to work with SDES.
setSDesEncryptionToDescription (
dev . getMediaType ( ) ,
description ,
null ) ;
setSDesEncryptionToDescription ( mediaType , description , null ) ;
//ZRTP
setZrtpEncryptionToDescription (
dev . getMediaType ( ) ,
description ,
null ) ;
setZrtpEncryptionToDescription ( mediaType , description , null ) ;
return content ;
}
@ -657,40 +668,41 @@ public List<ContentPacketExtension> createContentList(MediaType mediaType)
{
MediaDevice dev = getDefaultDevice ( mediaType ) ;
List < ContentPacketExtension > mediaDescs
= new ArrayList < ContentPacketExtension > ( ) ;
= new ArrayList < ContentPacketExtension > ( ) ;
if ( dev ! = null )
{
ContentPacketExtension content = createContent ( dev ) ;
if ( content ! = null )
if ( content ! = null )
mediaDescs . add ( content ) ;
}
// fail if all devices were inactive
if ( mediaDescs . isEmpty ( ) )
// Fail if no media is described (e.g. all devices are inactive).
if ( mediaDescs . isEmpty ( ) )
{
ProtocolProviderServiceJabberImpl
. throwOperationFailedException (
ProtocolProviderServiceJabberImpl . throwOperationFailedException (
"We couldn't find any active Audio/Video devices and "
+ "couldn't create a call" ,
OperationFailedException . GENERAL_ERROR , null , logger ) ;
OperationFailedException . GENERAL_ERROR ,
null ,
logger ) ;
}
TransportInfoSender transportInfoSender =
getTransportManager ( ) . getXmlNamespace ( ) . equals (
ProtocolProviderServiceJabberImpl . URN_GOOGLE_TRANSPORT_P2P )
// Describe the transport(s).
TransportInfoSender transportInfoSender
= getTransportManager ( ) . getXmlNamespace ( ) . equals (
ProtocolProviderServiceJabberImpl . URN_GOOGLE_TRANSPORT_P2P )
? new TransportInfoSender ( )
{
public void sendTransportInfo (
Iterable < ContentPacketExtension > contents )
{
getPeer ( ) . sendTransportInfo ( contents ) ;
}
}
{
public void sendTransportInfo (
Iterable < ContentPacketExtension > contents )
{
getPeer ( ) . sendTransportInfo ( contents ) ;
}
}
: null ;
//now add the transport elements
return harvestCandidates ( null , mediaDescs , transportInfoSender ) ;
}
@ -709,7 +721,7 @@ public void sendTransportInfo(
public List < ContentPacketExtension > createContentList ( )
throws OperationFailedException
{
// Audio Media Description
// Describe the media.
List < ContentPacketExtension > mediaDescs
= new ArrayList < ContentPacketExtension > ( ) ;
@ -719,11 +731,19 @@ public List<ContentPacketExtension> createContentList()
if ( dev ! = null )
{
MediaDirection direction
= dev . getDirection ( ) . and (
getDirectionUserPreference ( mediaType ) ) ;
MediaDirection direction = dev . getDirection ( ) ;
if ( isLocallyOnHold ( ) )
/ *
* In the case of RTP translation performed by the conference
* focus , the conference focus is not required to capture media .
* /
if ( ! ( MediaType . VIDEO . equals ( mediaType )
& & isRTPTranslationEnabled ( ) ) )
{
direction
= direction . and ( getDirectionUserPreference ( mediaType ) ) ;
}
if ( isLocallyOnHold ( ) )
direction = direction . and ( MediaDirection . SENDONLY ) ;
/ *
@ -734,16 +754,15 @@ public List<ContentPacketExtension> createContentList()
if ( MediaDirection . RECVONLY . equals ( direction ) )
direction = MediaDirection . INACTIVE ;
if ( direction ! = MediaDirection . INACTIVE )
if ( direction ! = MediaDirection . INACTIVE )
{
ContentPacketExtension content
= createContentForOffer (
dev . getSupportedFormats ( ) ,
direction ,
dev . getSupportedExtensions ( ) ) ;
RtpDescriptionPacketExtension description =
JingleUtils . getRtpDescription ( content ) ;
RtpDescriptionPacketExtension description
= JingleUtils . getRtpDescription ( content ) ;
//SDES
// It is important to set SDES before ZRTP in order to make
@ -752,17 +771,16 @@ public List<ContentPacketExtension> createContentList()
mediaType ,
description ,
null ) ;
//ZRTP
setZrtpEncryptionToDescription (
mediaType ,
description ,
null ) ;
/ * we request a desktop sharing session so add the inputevt
* extension in the "video" content
* /
if ( description . getMedia ( ) . equals ( MediaType . VIDEO . toString ( ) )
// we request a desktop sharing session so add the inputevt
// extension in the "video" content
if ( description . getMedia ( ) . equals (
MediaType . VIDEO . toString ( ) )
& & getLocalInputEvtAware ( ) )
{
content . addChildExtension (
@ -774,8 +792,8 @@ && getLocalInputEvtAware())
}
}
// fail if all devices were inactive
if ( mediaDescs . isEmpty ( ) )
// Fail if no media is described (e.g. all devices are inactive).
if ( mediaDescs . isEmpty ( ) )
{
ProtocolProviderServiceJabberImpl . throwOperationFailedException (
"We couldn't find any active Audio/Video devices"
@ -785,6 +803,7 @@ && getLocalInputEvtAware())
logger ) ;
}
// Describe the transport(s).
TransportInfoSender transportInfoSender
= getTransportManager ( ) . getXmlNamespace ( ) . equals (
ProtocolProviderServiceJabberImpl . URN_GOOGLE_TRANSPORT_P2P )
@ -798,7 +817,6 @@ public void sendTransportInfo(
}
: null ;
//now add the transport elements
return harvestCandidates ( null , mediaDescs , transportInfoSender ) ;
}
@ -849,8 +867,8 @@ private ContentPacketExtension createContentForOffer(
* processing to stop ( method setState in CallPeer ) .
* /
public void reinitAllContents ( )
throws OperationFailedException ,
IllegalArgumentException
throws OperationFailedException ,
IllegalArgumentException
{
boolean masterStreamSet = false ;
for ( String key : remoteContentMap . keySet ( ) )
@ -982,15 +1000,17 @@ private void removeContent(
* in this operation can synchronize to the mediaHandler instance to wait
* processing to stop ( method setState in CallPeer ) .
* /
private void processContent ( ContentPacketExtension content , boolean modify ,
boolean masterStream )
private void processContent (
ContentPacketExtension content ,
boolean modify ,
boolean masterStream )
throws OperationFailedException ,
IllegalArgumentException
{
RtpDescriptionPacketExtension description
= JingleUtils . getRtpDescription ( content ) ;
MediaType mediaType
= MediaType . parseString ( description . getMedia ( ) ) ;
= MediaType . parseString ( description . getMedia ( ) ) ;
//stream target
TransportManagerJabberImpl transportManager = getTransportManager ( ) ;
@ -1480,32 +1500,34 @@ private MediaDirection calculatePostHoldDirection(MediaStream stream)
{
MediaDirection streamDirection = stream . getDirection ( ) ;
if ( streamDirection . allowsSending ( ) )
if ( streamDirection . allowsSending ( ) )
return streamDirection ;
//when calculating a direction we need to take into account 1) what
//direction the remote party had asked for before putting us on hold,
//2) what the user preference is for the stream's media type, 3) our
//local hold status, 4) the direction supported by the device this
//stream is reading from.
/ *
* When calculating a direction we need to take into account 1 ) what
* direction the remote party had asked for before putting us on hold ,
* 2 ) what the user preference is for the stream ' s media type , 3 ) our
* local hold status , 4 ) the direction supported by the device this
* stream is reading from .
* /
//1. check what the remote party originally told us (from our persp.)
// 1. what the remote party originally told us (from our perspective )
ContentPacketExtension content = remoteContentMap . get ( stream . getName ( ) ) ;
MediaDirection postHoldDir
= JingleUtils . getDirection ( content , ! getPeer ( ) . isInitiator ( ) ) ;
MediaDirection postHoldDir = JingleUtils . getDirection ( content ,
! getPeer ( ) . isInitiator ( ) ) ;
//2. check the user preference.
// 2. the user preference
MediaDevice device = stream . getDevice ( ) ;
postHoldDir
= postHoldDir . and (
getDirectionUserPreference ( device . getMediaType ( ) ) ) ;
// 3. check our local hold status.
if ( isLocallyOnHold ( ) )
postHoldDir . and ( MediaDirection . SENDONLY ) ;
// 3. our local hold status
if ( isLocallyOnHold ( ) )
postHoldDir = postHoldDir . and ( MediaDirection . SENDONLY ) ;
// 4. check the device direction.
// 4. the device direction
postHoldDir = postHoldDir . and ( device . getDirection ( ) ) ;
stream . setDirection ( postHoldDir ) ;